15 struct PushConstants {
23 StaticWindow(
const std::string path,
const std::string &text,
int width,
int height,
bool fullscreen,
bool enable_vsync) :
mxvk::
VK_Window(text, width, height, fullscreen,
MXVK_VALIDATION, enable_vsync), shader_root((path.empty() ? std::string(static_example_ASSET_DIR) : path) +
"/data") {
setClearColor(0.02f, 0.03f, 0.06f, 1.0f); }
26 if (
device != VK_NULL_HANDLE) {
29 destroyGraphicsPipeline();
32 void event(SDL_Event &e)
override {
33 if (e.type == SDL_EVENT_KEY_DOWN && e.key.key == SDLK_ESCAPE) {
41 if (!ensureGraphicsPipeline()) {
45 vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline);
47 const auto now = std::chrono::steady_clock::now();
48 const float elapsed_seconds = std::chrono::duration<float>(now - start_time).count();
50 const float width =
static_cast<float>(extent.width);
51 const float height =
static_cast<float>(extent.height);
52 const PushConstants push_constants{elapsed_seconds, width, height,
static_cast<float>(frame_index++)};
54 vkCmdPushConstants(cmd, pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0,
sizeof(PushConstants), &push_constants);
56 vkCmdDraw(cmd, 3, 1, 0, 0);
60 std::string shader_root;
61 std::chrono::steady_clock::time_point start_time{std::chrono::steady_clock::now()};
62 uint32_t frame_index = 0;
64 void destroyGraphicsPipeline() {
65 if (
device == VK_NULL_HANDLE) {
66 pipeline_layout = VK_NULL_HANDLE;
67 graphics_pipeline = VK_NULL_HANDLE;
71 if (graphics_pipeline != VK_NULL_HANDLE) {
72 vkDestroyPipeline(
device, graphics_pipeline,
nullptr);
73 graphics_pipeline = VK_NULL_HANDLE;
75 if (pipeline_layout != VK_NULL_HANDLE) {
76 vkDestroyPipelineLayout(
device, pipeline_layout,
nullptr);
77 pipeline_layout = VK_NULL_HANDLE;
81 bool ensureGraphicsPipeline() {
82 if (graphics_pipeline != VK_NULL_HANDLE && pipeline_layout != VK_NULL_HANDLE) {
86 createGraphicsPipeline();
87 return graphics_pipeline != VK_NULL_HANDLE && pipeline_layout != VK_NULL_HANDLE;
90 void createGraphicsPipeline() {
95 const std::string vert_path = shader_root +
"/triangle.vert.spv";
96 const std::string frag_path = shader_root +
"/triangle.frag.spv";
97 const std::vector<char> vert_bytes =
loadSpv(vert_path);
98 const std::vector<char> frag_bytes =
loadSpv(frag_path);
101 VkShaderModule frag_module = VK_NULL_HANDLE;
105 std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages{};
106 shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
107 shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
108 shader_stages[0].module = vert_module;
109 shader_stages[0].pName =
"main";
110 shader_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
111 shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
112 shader_stages[1].module = frag_module;
113 shader_stages[1].pName =
"main";
115 VkPipelineVertexInputStateCreateInfo vertex_input{};
116 vertex_input.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
118 VkPipelineInputAssemblyStateCreateInfo input_assembly{};
119 input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
120 input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
121 input_assembly.primitiveRestartEnable = VK_FALSE;
123 VkPipelineViewportStateCreateInfo viewport_state{};
124 viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
125 viewport_state.viewportCount = 1;
126 viewport_state.scissorCount = 1;
128 const VkDynamicState dynamic_states[] = {
129 VK_DYNAMIC_STATE_VIEWPORT,
130 VK_DYNAMIC_STATE_SCISSOR,
132 VkPipelineDynamicStateCreateInfo dynamic_state{};
133 dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
134 dynamic_state.dynamicStateCount = 2;
135 dynamic_state.pDynamicStates = dynamic_states;
137 VkPipelineRasterizationStateCreateInfo rasterizer{};
138 rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
139 rasterizer.depthClampEnable = VK_FALSE;
140 rasterizer.rasterizerDiscardEnable = VK_FALSE;
141 rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
142 rasterizer.lineWidth = 1.0f;
143 rasterizer.cullMode = VK_CULL_MODE_NONE;
144 rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
145 rasterizer.depthBiasEnable = VK_FALSE;
147 VkPipelineMultisampleStateCreateInfo multisampling{};
148 multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
149 multisampling.sampleShadingEnable = VK_FALSE;
150 multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
152 VkPipelineDepthStencilStateCreateInfo depth_stencil{};
153 depth_stencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
154 depth_stencil.depthTestEnable = VK_FALSE;
155 depth_stencil.depthWriteEnable = VK_FALSE;
156 depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
157 depth_stencil.depthBoundsTestEnable = VK_FALSE;
158 depth_stencil.stencilTestEnable = VK_FALSE;
160 VkPipelineColorBlendAttachmentState color_blend_attachment{};
161 color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
162 color_blend_attachment.blendEnable = VK_FALSE;
164 VkPipelineColorBlendStateCreateInfo color_blending{};
165 color_blending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
166 color_blending.logicOpEnable = VK_FALSE;
167 color_blending.attachmentCount = 1;
168 color_blending.pAttachments = &color_blend_attachment;
170 VkPushConstantRange push_constant_range{};
171 push_constant_range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
172 push_constant_range.offset = 0;
173 push_constant_range.size =
sizeof(PushConstants);
175 VkPipelineLayoutCreateInfo pipeline_layout_info{};
176 pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
177 pipeline_layout_info.pushConstantRangeCount = 1;
178 pipeline_layout_info.pPushConstantRanges = &push_constant_range;
179 if (vkCreatePipelineLayout(
device, &pipeline_layout_info,
nullptr, &pipeline_layout) != VK_SUCCESS) {
180 throw mxvk::Exception(
"Failed to create pipeline layout");
183 VkPipelineRenderingCreateInfo pipeline_rendering_info{};
184 pipeline_rendering_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
185 pipeline_rendering_info.viewMask = 0;
186 pipeline_rendering_info.colorAttachmentCount = 1;
190 pipeline_rendering_info.depthAttachmentFormat =
depth_format;
193 VkGraphicsPipelineCreateInfo pipeline_info{};
194 pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
195 pipeline_info.pNext = &pipeline_rendering_info;
196 pipeline_info.stageCount =
static_cast<uint32_t
>(shader_stages.size());
197 pipeline_info.pStages = shader_stages.data();
198 pipeline_info.pVertexInputState = &vertex_input;
199 pipeline_info.pInputAssemblyState = &input_assembly;
200 pipeline_info.pViewportState = &viewport_state;
201 pipeline_info.pRasterizationState = &rasterizer;
202 pipeline_info.pMultisampleState = &multisampling;
203 pipeline_info.pDepthStencilState = &depth_stencil;
204 pipeline_info.pColorBlendState = &color_blending;
205 pipeline_info.pDynamicState = &dynamic_state;
206 pipeline_info.layout = pipeline_layout;
207 pipeline_info.renderPass = VK_NULL_HANDLE;
208 pipeline_info.subpass = 0;
209 pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
210 pipeline_info.basePipelineIndex = -1;
212 if (vkCreateGraphicsPipelines(
device, VK_NULL_HANDLE, 1, &pipeline_info,
nullptr, &graphics_pipeline) != VK_SUCCESS) {
213 throw mxvk::Exception(
"Failed to create graphics pipeline");
216 if (graphics_pipeline != VK_NULL_HANDLE) {
217 vkDestroyPipeline(
device, graphics_pipeline,
nullptr);
218 graphics_pipeline = VK_NULL_HANDLE;
220 if (pipeline_layout != VK_NULL_HANDLE) {
221 vkDestroyPipelineLayout(
device, pipeline_layout,
nullptr);
222 pipeline_layout = VK_NULL_HANDLE;
224 if (frag_module != VK_NULL_HANDLE) {
225 vkDestroyShaderModule(
device, frag_module,
nullptr);
227 vkDestroyShaderModule(
device, vert_module,
nullptr);
231 vkDestroyShaderModule(
device, frag_module,
nullptr);
232 vkDestroyShaderModule(
device, vert_module,
nullptr);
235 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
236 VkPipeline graphics_pipeline = VK_NULL_HANDLE;