From 1009952a7b410d143677489bea189bbca7ea90a1 Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Sat, 4 Oct 2025 01:02:55 +0100 Subject: [PATCH] Add floor --- CMakeLists.txt | 2 + floor-vert.glsl | 21 ++++++++++ gpu.c | 109 +++++++++++++++++++++++++++++++++++++++++------- gpu.h | 3 ++ 4 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 floor-vert.glsl diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ac1716..0db6d96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,10 +30,12 @@ function(add_shaders target) endfunction() add_shaders(shaders + floor-vert.glsl model-vert.glsl default-frag.glsl ) target_compile_definitions(shaders INTERFACE + FLOOR_VERT_SHADER_SPV="${CMAKE_CURRENT_BINARY_DIR}/shaders/floor-vert.spv" MODEL_VERT_SHADER_SPV="${CMAKE_CURRENT_BINARY_DIR}/shaders/model-vert.spv" FRAG_SHADER_SPV="${CMAKE_CURRENT_BINARY_DIR}/shaders/default-frag.spv") diff --git a/floor-vert.glsl b/floor-vert.glsl new file mode 100644 index 0000000..70a4cf4 --- /dev/null +++ b/floor-vert.glsl @@ -0,0 +1,21 @@ +#version 450 + +layout(location = 0) out vec3 frag_normal; + +layout(push_constant) uniform vp_t { + mat4 view; + mat4 proj; +} vp; + +vec2 vertices[4] = vec2[]( + vec2(-1, -1), + vec2(-1, 1), + vec2(1, 1), + vec2(1, -1) +); + +void main() { + const vec2 pos = 3 * vertices[gl_VertexIndex]; + gl_Position = vp.proj * vp.view * vec4(pos.x, 0, pos.y, 1); + frag_normal = vec3(0, 1, 0); +} diff --git a/gpu.c b/gpu.c index abce301..2b207a1 100644 --- a/gpu.c +++ b/gpu.c @@ -26,7 +26,11 @@ static const char *extensions[] = { static constexpr size_t extension_count = NELEMS(extensions); -static const char vert_shader[] = { +static const char floor_vert_shader[] = { +#embed FLOOR_VERT_SHADER_SPV +}; + +static const char model_vert_shader[] = { #embed MODEL_VERT_SHADER_SPV }; @@ -496,11 +500,82 @@ void gpu_init(gpu_ctx_t *ctx, GLFWwindow *window, const char *name) }; // Load vertex and fragment shader modules - ctx->model_vert_shader - = load_shader_module(ctx->dev, vert_shader, sizeof(vert_shader)); + ctx->floor_vert_shader = load_shader_module( + ctx->dev, floor_vert_shader, sizeof(floor_vert_shader)); + ctx->model_vert_shader = load_shader_module( + ctx->dev, model_vert_shader, sizeof(model_vert_shader)); ctx->frag_shader = load_shader_module(ctx->dev, frag_shader, sizeof(frag_shader)); + // Set up depth stencil config + const VkPipelineDepthStencilStateCreateInfo depth_stencil_config = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + .depthTestEnable = VK_TRUE, + .depthWriteEnable = VK_TRUE, + .depthCompareOp = VK_COMPARE_OP_LESS, + .depthBoundsTestEnable = VK_FALSE, + .stencilTestEnable = VK_FALSE, + }; + + // Create floor pipeline + const VkPipelineShaderStageCreateInfo floor_shader_stages[] = { + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_VERTEX_BIT, + .module = ctx->floor_vert_shader, + .pName = "main", + }, + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_FRAGMENT_BIT, + .module = ctx->frag_shader, + .pName = "main", + }, + }; + const VkPipelineRasterizationStateCreateInfo floor_rasterizer_config = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + .depthClampEnable = VK_FALSE, + .rasterizerDiscardEnable = VK_FALSE, + .polygonMode = VK_POLYGON_MODE_FILL, + .lineWidth = 1.0f, + .cullMode = VK_CULL_MODE_NONE, + }; + const VkPipelineLayoutCreateInfo floor_pipeline_layout_config = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pushConstantRangeCount = 1, + .pPushConstantRanges = &push_constant_range, + }; + result = vkCreatePipelineLayout( + ctx->dev, &floor_pipeline_layout_config, nullptr, + &ctx->floor_pipeline_layout); + assert(result == VK_SUCCESS); + const VkGraphicsPipelineCreateInfo floor_pipeline_config = { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .stageCount = 2, + .pStages = floor_shader_stages, + .pVertexInputState = &(VkPipelineVertexInputStateCreateInfo) { + .sType + = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + }, + .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) { + .sType + = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, + }, + .pViewportState = &viewport_config, + .pRasterizationState = &floor_rasterizer_config, + .pMultisampleState = &multisampling_config, + .pColorBlendState = &colour_blend_config, + .layout = ctx->floor_pipeline_layout, + .renderPass = ctx->render_pass, + .subpass = 0, + .pDepthStencilState = &depth_stencil_config, + }; + result = vkCreateGraphicsPipelines( + ctx->dev, VK_NULL_HANDLE, 1, &floor_pipeline_config, nullptr, + &ctx->floor_pipeline); + assert(result == VK_SUCCESS); + // Create descriptor set layout const VkDescriptorSetLayoutBinding desc_set_layout_bindings[] = { { @@ -621,14 +696,6 @@ void gpu_init(gpu_ctx_t *ctx, GLFWwindow *window, const char *name) ctx->dev, &model_pipeline_layout_config, nullptr, &ctx->model_pipeline_layout); assert(result == VK_SUCCESS); - const VkPipelineDepthStencilStateCreateInfo depth_stencil_config = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, - .depthTestEnable = VK_TRUE, - .depthWriteEnable = VK_TRUE, - .depthCompareOp = VK_COMPARE_OP_LESS, - .depthBoundsTestEnable = VK_FALSE, - .stencilTestEnable = VK_FALSE, - }; const VkGraphicsPipelineCreateInfo model_pipeline_config = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .stageCount = 2, @@ -746,16 +813,20 @@ void gpu_cleanup(const gpu_ctx_t *ctx) vkDestroyCommandPool(ctx->dev, ctx->cmd_pool, nullptr); - vkDestroyPipeline(ctx->dev, ctx->model_pipeline, nullptr); - vkDestroyRenderPass(ctx->dev, ctx->render_pass, nullptr); - vkDestroyPipelineLayout(ctx->dev, ctx->model_pipeline_layout, nullptr); + vkDestroyPipeline(ctx->dev, ctx->floor_pipeline, nullptr); + vkDestroyPipelineLayout(ctx->dev, ctx->floor_pipeline_layout, nullptr); + vkDestroyPipeline(ctx->dev, ctx->model_pipeline, nullptr); + vkDestroyPipelineLayout(ctx->dev, ctx->model_pipeline_layout, nullptr); vkDestroyDescriptorPool(ctx->dev, ctx->desc_pool, nullptr); vkDestroyDescriptorSetLayout(ctx->dev, ctx->desc_set_layout, nullptr); + vkDestroyShaderModule(ctx->dev, ctx->floor_vert_shader, nullptr); vkDestroyShaderModule(ctx->dev, ctx->model_vert_shader, nullptr); vkDestroyShaderModule(ctx->dev, ctx->frag_shader, nullptr); + vkDestroyRenderPass(ctx->dev, ctx->render_pass, nullptr); + vkDestroyImageView(ctx->dev, ctx->depth_img_view, nullptr); vkDestroyImage(ctx->dev, ctx->depth_img, nullptr); vkFreeMemory(ctx->dev, ctx->depth_img_mem, nullptr); @@ -922,9 +993,17 @@ void gpu_render_begin(gpu_ctx_t *ctx, vp_t vp) }; vkCmdBeginRenderPass( ctx->cmd_buf, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); + + // Draw floor + vkCmdBindPipeline( + ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->floor_pipeline); + vkCmdPushConstants( + ctx->cmd_buf, ctx->model_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, + 0, sizeof(vp_t), &vp); + vkCmdDraw(ctx->cmd_buf, 4, 1, 0, 0); + vkCmdBindPipeline( ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->model_pipeline); - vkCmdPushConstants( ctx->cmd_buf, ctx->model_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vp_t), &vp); diff --git a/gpu.h b/gpu.h index 846f490..61cb62a 100644 --- a/gpu.h +++ b/gpu.h @@ -28,11 +28,14 @@ typedef struct { VkDeviceMemory depth_img_mem; VkImageView depth_img_view; VkFramebuffer framebuffers[MAX_FRAMES_IN_FLIGHT]; + VkShaderModule floor_vert_shader; VkShaderModule model_vert_shader; VkShaderModule frag_shader; VkDescriptorSetLayout desc_set_layout; VkDescriptorPool desc_pool; VkRenderPass render_pass; + VkPipelineLayout floor_pipeline_layout; + VkPipeline floor_pipeline; VkPipelineLayout model_pipeline_layout; VkPipeline model_pipeline; VkCommandPool cmd_pool;