diff --git a/default-frag.glsl b/default-frag.glsl index 123c1e0..f053502 100644 --- a/default-frag.glsl +++ b/default-frag.glsl @@ -9,6 +9,8 @@ layout(location = 1) in vec4 light_pos; layout(location = 0) out vec4 out_colour; +layout(binding = 2) uniform sampler2DShadow shadow_map; + void main() { float lambertian = max(dot(frag_normal, light_dir), 0.0); diff --git a/gpu.c b/gpu.c index 66ae709..6ded68b 100644 --- a/gpu.c +++ b/gpu.c @@ -528,6 +528,28 @@ void gpu_init(gpu_ctx_t *ctx, GLFWwindow *window, const char *name) ctx->dev, &render_pass_config, nullptr, &ctx->render_pass); assert(result == VK_SUCCESS); + // Create descriptor pool + const size_t max_desc_sets = MAX_MODEL_COUNT * ctx->swapchain_img_count; + const VkDescriptorPoolSize desc_pool_sizes[] = { + { + .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .descriptorCount = 2 * max_desc_sets, + }, + { + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = max_desc_sets, + }, + }; + const VkDescriptorPoolCreateInfo desc_pool_config = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .poolSizeCount = 2, + .pPoolSizes = desc_pool_sizes, + .maxSets = max_desc_sets, + }; + result = vkCreateDescriptorPool( + ctx->dev, &desc_pool_config, nullptr, &ctx->desc_pool); + assert(result == VK_SUCCESS); + // Populate multisampling configuration const VkPipelineMultisampleStateCreateInfo multisampling_config = { .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, @@ -573,6 +595,22 @@ void gpu_init(gpu_ctx_t *ctx, GLFWwindow *window, const char *name) .stencilTestEnable = VK_FALSE, }; + // Create shadow descriptor set layout + const VkDescriptorSetLayoutCreateInfo floor_desc_set_layout_config = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .bindingCount = 1, + .pBindings = &(VkDescriptorSetLayoutBinding) { + .binding = 2, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + }, + }; + result = vkCreateDescriptorSetLayout( + ctx->dev, &floor_desc_set_layout_config, nullptr, + &ctx->floor_desc_set_layout); + assert(result == VK_SUCCESS); + // Create floor pipeline const VkPipelineShaderStageCreateInfo floor_shader_stages[] = { { @@ -598,6 +636,8 @@ void gpu_init(gpu_ctx_t *ctx, GLFWwindow *window, const char *name) }; const VkPipelineLayoutCreateInfo floor_pipeline_layout_config = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 1, + .pSetLayouts = &ctx->floor_desc_set_layout, .pushConstantRangeCount = 1, .pPushConstantRanges = &push_constant_range, }; @@ -646,6 +686,12 @@ void gpu_init(gpu_ctx_t *ctx, GLFWwindow *window, const char *name) .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, }, + { + .binding = 2, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + }, }; const VkDescriptorSetLayoutCreateInfo desc_set_layout_config = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, @@ -656,21 +702,6 @@ void gpu_init(gpu_ctx_t *ctx, GLFWwindow *window, const char *name) ctx->dev, &desc_set_layout_config, nullptr, &ctx->desc_set_layout); assert(result == VK_SUCCESS); - // Create descriptor pool - const VkDescriptorPoolCreateInfo desc_pool_config = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .poolSizeCount = 1, - .pPoolSizes = &(VkDescriptorPoolSize) { - .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount - = MAX_MODEL_COUNT * 2 * ctx->swapchain_img_count, - }, - .maxSets = MAX_MODEL_COUNT * 2 * ctx->swapchain_img_count, - }; - result = vkCreateDescriptorPool( - ctx->dev, &desc_pool_config, nullptr, &ctx->desc_pool); - assert(result == VK_SUCCESS); - // Set up model input configuration const VkVertexInputBindingDescription input_binding_descs[] = { { @@ -936,6 +967,41 @@ void gpu_init(gpu_ctx_t *ctx, GLFWwindow *window, const char *name) ctx->dev, &transient_cmd_pool_config, nullptr, &ctx->transient_cmd_pool); assert(result == VK_SUCCESS); + + // Allocate floor descriptor sets + VkDescriptorSetLayout desc_set_layouts[ctx->swapchain_img_count]; + for (unsigned i = 0; i < ctx->swapchain_img_count; ++i) + desc_set_layouts[i] = ctx->floor_desc_set_layout; + const VkDescriptorSetAllocateInfo desc_sets_alloc_config = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .descriptorPool = ctx->desc_pool, + .descriptorSetCount = ctx->swapchain_img_count, + .pSetLayouts = desc_set_layouts, + }; + result = vkAllocateDescriptorSets( + ctx->dev, &desc_sets_alloc_config, ctx->floor_desc_sets); + assert(result == VK_SUCCESS); + + // Write to floor descriptor sets + for (unsigned i = 0; i < ctx->swapchain_img_count; ++i) { + const VkWriteDescriptorSet desc_writes[] = { + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = ctx->floor_desc_sets[i], + .dstBinding = 2, + .dstArrayElement = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 1, + .pImageInfo = &(VkDescriptorImageInfo) { + .sampler = ctx->shadow_sampler, + .imageView = ctx->shadow_view, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }, + }, + }; + vkUpdateDescriptorSets( + ctx->dev, NELEMS(desc_writes), desc_writes, 0, nullptr); + } } void gpu_cleanup(const gpu_ctx_t *ctx) @@ -960,6 +1026,8 @@ void gpu_cleanup(const gpu_ctx_t *ctx) vkDestroyPipelineLayout(ctx->dev, ctx->model_pipeline_layout, nullptr); vkDestroyDescriptorPool(ctx->dev, ctx->desc_pool, nullptr); vkDestroyDescriptorSetLayout(ctx->dev, ctx->desc_set_layout, nullptr); + vkDestroyDescriptorSetLayout( + ctx->dev, ctx->floor_desc_set_layout, nullptr); vkDestroyShaderModule(ctx->dev, ctx->floor_vert_shader, nullptr); vkDestroyShaderModule(ctx->dev, ctx->model_vert_shader, nullptr); @@ -1018,7 +1086,7 @@ void gpu_model_load( &out->index_mem); load_buffer(ctx, out->index_buf, model->indices, index_size); - // Create and configure descriptor sets + // Allocate descriptor sets VkDescriptorSetLayout desc_set_layouts[ctx->swapchain_img_count]; for (unsigned i = 0; i < ctx->swapchain_img_count; ++i) desc_set_layouts[i] = ctx->desc_set_layout; @@ -1054,7 +1122,7 @@ void gpu_model_load( vkMapMemory( ctx->dev, out->bone_mem, 0, bone_size, 0, (void **)&out->bone_ptr); - // Configure descriptor sets to use transform and bone matrix buffers + // Write to descriptor sets for (unsigned i = 0; i < ctx->swapchain_img_count; ++i) { const VkWriteDescriptorSet desc_writes[] = { { @@ -1083,6 +1151,19 @@ void gpu_model_load( .range = model->bone_count * sizeof(mat4_t), }, }, + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = out->desc_sets[i], + .dstBinding = 2, + .dstArrayElement = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 1, + .pImageInfo = &(VkDescriptorImageInfo) { + .sampler = ctx->shadow_sampler, + .imageView = ctx->shadow_view, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }, + }, }; vkUpdateDescriptorSets( ctx->dev, NELEMS(desc_writes), desc_writes, 0, nullptr); @@ -1217,6 +1298,10 @@ void gpu_render( vkCmdPushConstants( ctx->cmd_buf, ctx->model_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(push_t), &push); + vkCmdBindDescriptorSets( + ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, + ctx->floor_pipeline_layout, 0, 1, ctx->floor_desc_sets + curr_img, 0, + nullptr); vkCmdDraw(ctx->cmd_buf, 4, 1, 0, 0); // Draw models @@ -1231,7 +1316,6 @@ void gpu_render( &(VkDeviceSize) { 0 }); vkCmdBindIndexBuffer( ctx->cmd_buf, models[i].index_buf, 0, VK_INDEX_TYPE_UINT16); - vkCmdBindDescriptorSets( ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->model_pipeline_layout, 0, 1, models[i].desc_sets + curr_img, diff --git a/gpu.h b/gpu.h index 4eeea03..7552219 100644 --- a/gpu.h +++ b/gpu.h @@ -31,10 +31,12 @@ typedef struct { VkShaderModule floor_vert_shader; VkShaderModule model_vert_shader; VkShaderModule frag_shader; + VkDescriptorSetLayout floor_desc_set_layout; VkDescriptorSetLayout desc_set_layout; VkDescriptorPool desc_pool; VkRenderPass shadow_pass; VkRenderPass render_pass; + VkDescriptorSet floor_desc_sets[MAX_FRAMES_IN_FLIGHT]; VkPipelineLayout floor_pipeline_layout; VkPipeline floor_pipeline; VkPipelineLayout model_pipeline_layout;