diff options
| author | hachem <im@hachem.wtf> | 2026-08-22 00:13:57 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-08-22 00:14:08 +0200 |
| commit | 1eaefc42a8ea03ac8680ffbb0e53179605f4ad22 (patch) | |
| tree | 360d26a2626ee56c34c481852c49db4dae1b3c54 /src/platform/vulkan/vulkan_renderer.cpp | |
| parent | 4404019a83354125d56003040a5fabb2b36bc1c9 (diff) | |
feat: complete Vulkan
Diffstat (limited to 'src/platform/vulkan/vulkan_renderer.cpp')
| -rw-r--r-- | src/platform/vulkan/vulkan_renderer.cpp | 105 |
1 files changed, 104 insertions, 1 deletions
diff --git a/src/platform/vulkan/vulkan_renderer.cpp b/src/platform/vulkan/vulkan_renderer.cpp index 93b251d..75235ef 100644 --- a/src/platform/vulkan/vulkan_renderer.cpp +++ b/src/platform/vulkan/vulkan_renderer.cpp @@ -142,6 +142,15 @@ namespace Donut VkPipelineLayout sphere_pipeline_layout = VK_NULL_HANDLE; VkPipeline sphere_pipeline = VK_NULL_HANDLE; + VkBuffer skybox_vb = VK_NULL_HANDLE; VkDeviceMemory skybox_vb_mem = VK_NULL_HANDLE; + VkBuffer skybox_ubo = VK_NULL_HANDLE; VkDeviceMemory skybox_ubo_mem = VK_NULL_HANDLE; + void* skybox_ubo_mapped = nullptr; + VkDescriptorSetLayout skybox_set_layout = VK_NULL_HANDLE; + VkDescriptorPool skybox_pool = VK_NULL_HANDLE; + VkDescriptorSet skybox_set = VK_NULL_HANDLE; + VkPipelineLayout skybox_pipeline_layout = VK_NULL_HANDLE; + VkPipeline skybox_pipeline = VK_NULL_HANDLE; + auto find_memory_type(uint32_t type_filter, VkMemoryPropertyFlags flags) const -> uint32_t; auto create_buffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags props, VkBuffer& buf, VkDeviceMemory& mem) const -> bool; static auto load_spirv(const std::string& path) -> std::vector<uint32_t>; @@ -962,6 +971,13 @@ namespace Donut sw.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; sw.pImageInfo = &cube_info; vkUpdateDescriptorSets(device, 1, &sw, 0, nullptr); } + if (skybox_set) + { + VkWriteDescriptorSet kw{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; + kw.dstSet = skybox_set; kw.dstBinding = 1; kw.descriptorCount = 1; + kw.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; kw.pImageInfo = &cube_info; + vkUpdateDescriptorSets(device, 1, &kw, 0, nullptr); + } } auto VulkanRenderer::Impl::create_present_resources() -> bool @@ -1185,7 +1201,73 @@ namespace Donut if (spr != VK_SUCCESS) { DONUT_ERROR("Vulkan: sphere pipeline creation failed ({})", (int)spr); return false; } } - DONUT_INFO("Vulkan: scene resources ready ({} grid verts, {} sphere indices)", grid_vertex_count, sphere_index_count); + { + const float cube[] = { + -1,-1,-1, 1,-1,-1, 1, 1,-1, 1, 1,-1, -1, 1,-1, -1,-1,-1, + -1,-1, 1, 1,-1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1,-1, 1, + -1, 1, 1, -1, 1,-1, -1,-1,-1, -1,-1,-1, -1,-1, 1, -1, 1, 1, + 1, 1, 1, 1, 1,-1, 1,-1,-1, 1,-1,-1, 1,-1, 1, 1, 1, 1, + -1,-1,-1, 1,-1,-1, 1,-1, 1, 1,-1, 1, -1,-1, 1, -1,-1,-1, + -1, 1,-1, 1, 1,-1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1,-1 + }; + if (!create_buffer(sizeof(cube), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, host_vis, skybox_vb, skybox_vb_mem)) return false; + void* kp = nullptr; vkMapMemory(device, skybox_vb_mem, 0, sizeof(cube), 0, &kp); memcpy(kp, cube, sizeof(cube)); vkUnmapMemory(device, skybox_vb_mem); + + if (!create_buffer(128, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, host_vis, skybox_ubo, skybox_ubo_mem)) return false; + vkMapMemory(device, skybox_ubo_mem, 0, 128, 0, &skybox_ubo_mapped); + + VkDescriptorSetLayoutBinding kb[2]{}; + kb[0].binding = 0; kb[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; kb[0].descriptorCount = 1; kb[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + kb[1].binding = 1; kb[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; kb[1].descriptorCount = 1; kb[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + VkDescriptorSetLayoutCreateInfo kdslci{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; kdslci.bindingCount = 2; kdslci.pBindings = kb; + VK_CHECK(vkCreateDescriptorSetLayout(device, &kdslci, nullptr, &skybox_set_layout)); + VkDescriptorPoolSize kps[2] = { { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 }, { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 } }; + VkDescriptorPoolCreateInfo kdpci{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; kdpci.maxSets = 1; kdpci.poolSizeCount = 2; kdpci.pPoolSizes = kps; + VK_CHECK(vkCreateDescriptorPool(device, &kdpci, nullptr, &skybox_pool)); + VkDescriptorSetAllocateInfo kdsai{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; kdsai.descriptorPool = skybox_pool; kdsai.descriptorSetCount = 1; kdsai.pSetLayouts = &skybox_set_layout; + VK_CHECK(vkAllocateDescriptorSets(device, &kdsai, &skybox_set)); + VkDescriptorBufferInfo kbi{ skybox_ubo, 0, VK_WHOLE_SIZE }; + VkDescriptorImageInfo kii{ cube_sampler, cube_view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; + VkWriteDescriptorSet kw[2]{}; + kw[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; kw[0].dstSet = skybox_set; kw[0].dstBinding = 0; kw[0].descriptorCount = 1; kw[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; kw[0].pBufferInfo = &kbi; + kw[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; kw[1].dstSet = skybox_set; kw[1].dstBinding = 1; kw[1].descriptorCount = 1; kw[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; kw[1].pImageInfo = &kii; + vkUpdateDescriptorSets(device, 2, kw, 0, nullptr); + + VkShaderModule kvmod, kfmod; + if (!create_shader_module("assets/shaders/generated/skybox.vertexMain.spv", kvmod)) return false; + if (!create_shader_module("assets/shaders/generated/skybox.fragmentMain.spv", kfmod)) return false; + VkPipelineLayoutCreateInfo kplci{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; kplci.setLayoutCount = 1; kplci.pSetLayouts = &skybox_set_layout; + VK_CHECK(vkCreatePipelineLayout(device, &kplci, nullptr, &skybox_pipeline_layout)); + VkPipelineShaderStageCreateInfo kstages[2]{}; + kstages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; kstages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; kstages[0].module = kvmod; kstages[0].pName = "main"; + kstages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; kstages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; kstages[1].module = kfmod; kstages[1].pName = "main"; + VkVertexInputBindingDescription kvib{ 0, 3 * (uint32_t)sizeof(float), VK_VERTEX_INPUT_RATE_VERTEX }; + VkVertexInputAttributeDescription kvia{ 0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0 }; + VkPipelineVertexInputStateCreateInfo kvin{ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; + kvin.vertexBindingDescriptionCount = 1; kvin.pVertexBindingDescriptions = &kvib; + kvin.vertexAttributeDescriptionCount = 1; kvin.pVertexAttributeDescriptions = &kvia; + VkPipelineInputAssemblyStateCreateInfo kia{ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO }; kia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + VkPipelineViewportStateCreateInfo kvps{ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO }; kvps.viewportCount = 1; kvps.scissorCount = 1; + VkDynamicState kdyn[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo kdsci{ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO }; kdsci.dynamicStateCount = 2; kdsci.pDynamicStates = kdyn; + VkPipelineRasterizationStateCreateInfo krs{ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO }; krs.polygonMode = VK_POLYGON_MODE_FILL; krs.cullMode = VK_CULL_MODE_NONE; krs.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; krs.lineWidth = 1.0f; + VkPipelineMultisampleStateCreateInfo kms{ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO }; kms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + VkPipelineDepthStencilStateCreateInfo kds{ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO }; + kds.depthTestEnable = VK_FALSE; kds.depthWriteEnable = VK_FALSE; + VkPipelineColorBlendAttachmentState kcba{}; kcba.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + VkPipelineColorBlendStateCreateInfo kcb{ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO }; kcb.attachmentCount = 1; kcb.pAttachments = &kcba; + VkGraphicsPipelineCreateInfo kgpci{ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO }; + kgpci.stageCount = 2; kgpci.pStages = kstages; + kgpci.pVertexInputState = &kvin; kgpci.pInputAssemblyState = &kia; kgpci.pViewportState = &kvps; + kgpci.pDynamicState = &kdsci; + kgpci.pRasterizationState = &krs; kgpci.pMultisampleState = &kms; kgpci.pColorBlendState = &kcb; kgpci.pDepthStencilState = &kds; + kgpci.layout = skybox_pipeline_layout; kgpci.renderPass = scene_render_pass; kgpci.subpass = 0; + VkResult kpr = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &kgpci, nullptr, &skybox_pipeline); + vkDestroyShaderModule(device, kvmod, nullptr); vkDestroyShaderModule(device, kfmod, nullptr); + if (kpr != VK_SUCCESS) { DONUT_ERROR("Vulkan: skybox pipeline creation failed ({})", (int)kpr); return false; } + } + + DONUT_INFO("Vulkan: scene resources ready ({} grid verts, {} sphere indices, skybox)", grid_vertex_count, sphere_index_count); return true; } @@ -1236,6 +1318,12 @@ namespace Donut s.outline_color = glm::vec3(1.0f, 1.0f, 0.0f); s.outline_width = 0.1f; if (sphere_ubo_mapped) memcpy(sphere_ubo_mapped, &s, sizeof(s)); + + struct SkyboxUBO { glm::mat4 projection; glm::mat4 view; } sky{}; + static_assert(sizeof(SkyboxUBO) == 128, "SkyboxUBO std140 layout mismatch"); + sky.projection = scene_camera.get_projection_matrix(); + sky.view = glm::mat4(glm::mat3(scene_camera.get_view_matrix())); + if (skybox_ubo_mapped) memcpy(skybox_ubo_mapped, &sky, sizeof(sky)); } auto VulkanRenderer::Impl::update_geodesic_uniforms() -> void @@ -1355,6 +1443,16 @@ namespace Donut if (sphere_vb) vkDestroyBuffer(device, sphere_vb, nullptr); if (sphere_vb_mem) vkFreeMemory(device, sphere_vb_mem, nullptr); + if (skybox_pipeline) vkDestroyPipeline(device, skybox_pipeline, nullptr); + if (skybox_pipeline_layout) vkDestroyPipelineLayout(device, skybox_pipeline_layout, nullptr); + if (skybox_pool) vkDestroyDescriptorPool(device, skybox_pool, nullptr); + if (skybox_set_layout) vkDestroyDescriptorSetLayout(device, skybox_set_layout, nullptr); + if (skybox_ubo_mapped) { vkUnmapMemory(device, skybox_ubo_mem); skybox_ubo_mapped = nullptr; } + if (skybox_ubo) vkDestroyBuffer(device, skybox_ubo, nullptr); + if (skybox_ubo_mem) vkFreeMemory(device, skybox_ubo_mem, nullptr); + if (skybox_vb) vkDestroyBuffer(device, skybox_vb, nullptr); + if (skybox_vb_mem) vkFreeMemory(device, skybox_vb_mem, nullptr); + if (present_pipeline) vkDestroyPipeline(device, present_pipeline, nullptr); if (present_pipeline_layout) vkDestroyPipelineLayout(device, present_pipeline_layout, nullptr); if (present_pool) vkDestroyDescriptorPool(device, present_pool, nullptr); @@ -1404,6 +1502,11 @@ namespace Donut vkCmdSetViewport(cmd, 0, 1, &gvp); vkCmdSetScissor(cmd, 0, 1, &gsc); + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, skybox_pipeline); + vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, skybox_pipeline_layout, 0, 1, &skybox_set, 0, nullptr); + VkDeviceSize skoff = 0; vkCmdBindVertexBuffers(cmd, 0, 1, &skybox_vb, &skoff); + vkCmdDraw(cmd, 36, 1, 0, 0); + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, sphere_pipeline); vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, sphere_pipeline_layout, 0, 1, &sphere_set, 0, nullptr); VkDeviceSize soff = 0; vkCmdBindVertexBuffers(cmd, 0, 1, &sphere_vb, &soff); |
