diff --git a/Makefile b/Makefile index 229cffc..8792730 100644 --- a/Makefile +++ b/Makefile @@ -57,7 +57,7 @@ debug: spacegame %.vert.spv: %.vert - glslc $< -o $@ + glslangValidator -V -o $@ $< %.frag.spv: %.frag - glslc $< -o $@ + glslangValidator -V -o $@ $< diff --git a/shader_src/basic.vert b/shader_src/basic.vert index 36ee7e5..a665b19 100644 --- a/shader_src/basic.vert +++ b/shader_src/basic.vert @@ -1,10 +1,14 @@ #version 450 -layout(set = 0, binding = 0) uniform SceneUniform { +layout( push_constant ) uniform constants { mat4 view; mat4 proj; } scene; +layout(set = 0, binding = 0) uniform SceneUniform { + mat4 test; +} scene_ubo; + layout(set = 2, binding = 0) uniform ModelUniform { mat4 model; } model_ubo; diff --git a/shader_src/texture.vert b/shader_src/texture.vert index 69020ec..6270cf4 100644 --- a/shader_src/texture.vert +++ b/shader_src/texture.vert @@ -1,8 +1,12 @@ #version 450 -layout(set = 0, binding = 0) uniform SceneUniformBuffer { +layout( push_constant ) uniform constants { mat4 view; mat4 proj; +} scene_pc; + +layout(set = 0, binding = 0) uniform SceneUniformBuffer { + mat4 test; } scene_ubo; layout(set = 2, binding = 1) uniform ObjectUniformBuffer { @@ -17,7 +21,7 @@ layout(location = 0) out vec3 fragColor; layout(location = 1) out vec2 fragTex; void main() { - gl_Position = scene_ubo.proj * scene_ubo.view * object_ubo.model * vec4(inPosition, 1.0); + gl_Position = scene_pc.proj * scene_pc.view * object_ubo.model * vec4(inPosition, 1.0); fragColor = inColor; fragTex = inTex; } diff --git a/src/main.c b/src/main.c index 7f5e4e7..10fefdb 100644 --- a/src/main.c +++ b/src/main.c @@ -190,6 +190,7 @@ typedef struct SceneContextStruct { VkDescriptorSet* descriptors; GPUBuffer* ubos; void** ubo_ptrs; + VkPushConstantRange pcr; } SceneContext; struct TextureVertex { @@ -208,6 +209,10 @@ struct ModelUBO { }; struct SceneUBO { + mat4 test; +}; + +struct ScenePC { mat4 view; mat4 proj; }; @@ -895,13 +900,25 @@ VkShaderModule create_shader_module(VkDevice device, const char * code, uint32_t return shader; } -VkShaderModule load_shader_file(uint32_t buffer_size, const char* path, VkDevice device) { +VkShaderModule load_shader_file(const char* path, VkDevice device) { FILE* file; - file = fopen(path, "r"); + file = fopen(path, "rb"); if(file == 0) { return VK_NULL_HANDLE; } + int result = fseek(file, 0, SEEK_END); + if(result != 0) { + return VK_NULL_HANDLE; + } + + long buffer_size = ftell(file); + + result = fseek(file, 0, SEEK_SET); + if(result != 0) { + return VK_NULL_HANDLE; + } + char * buffer = malloc(buffer_size); if(buffer == 0) { return VK_NULL_HANDLE; @@ -1554,8 +1571,9 @@ void command_draw_object(Material material, Object object, uint32_t frame_num, V vkCmdDrawIndexed(command_buffer, mesh->index_count, 1, 0, 0, 0); } -void command_draw_material(Material material, uint32_t object_count, Object* objects, uint32_t frame_num, VkDescriptorSet* scene_descriptors, VkCommandBuffer command_buffer) { +void command_draw_material(Material material, uint32_t object_count, Object* objects, uint32_t frame_num, VkDescriptorSet* scene_descriptors, struct ScenePC* scene_constants, VkCommandBuffer command_buffer) { vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline); + vkCmdPushConstants(command_buffer, material.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(struct ScenePC), scene_constants); vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 0, 1, &scene_descriptors[frame_num], 0, 0); if(material.material_descriptors != 0) { vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 1, 1, &material.material_descriptors[frame_num], 0, 0); @@ -1565,7 +1583,7 @@ void command_draw_material(Material material, uint32_t object_count, Object* obj } } -VkResult command_draw_scene(uint32_t materials_count, Material* materials, uint32_t* object_counts, Object** objects, uint32_t frame_num, VkDescriptorSet* scene_descriptors, VkCommandBuffer command_buffer, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D extent) { +VkResult command_draw_scene(uint32_t materials_count, Material* materials, uint32_t* object_counts, Object** objects, uint32_t frame_num, VkDescriptorSet* scene_descriptors, struct ScenePC* scene_constants, VkCommandBuffer command_buffer, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D extent) { VkCommandBufferBeginInfo begin_info = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .flags = 0, @@ -1625,7 +1643,7 @@ VkResult command_draw_scene(uint32_t materials_count, Material* materials, uint3 vkCmdSetScissor(command_buffer, 0, 1, &scissor); for(uint i = 0; i < materials_count; i++) { - command_draw_material(materials[i], object_counts[i], objects[i], frame_num, scene_descriptors, command_buffer); + command_draw_material(materials[i], object_counts[i], objects[i], frame_num, scene_descriptors, scene_constants, command_buffer); } vkCmdEndRenderPass(command_buffer); @@ -1762,6 +1780,7 @@ Material create_material( uint32_t shader_stage_count, VkPipelineShaderStageCreateInfo* shader_stages, VkDescriptorSetLayout scene_ubo_layout, + VkPushConstantRange scene_pcr, PipelineLayout pipeline_layout, MeshType mesh_type, uint32_t max_frames_in_flight, @@ -1862,8 +1881,8 @@ Material create_material( .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .setLayoutCount = 3, .pSetLayouts = all_layouts, - .pushConstantRangeCount = 0, - .pPushConstantRanges = 0, + .pushConstantRangeCount = 1, + .pPushConstantRanges = &scene_pcr, }; result = vkCreatePipelineLayout(device, &layout_info, 0, &layout); @@ -1892,9 +1911,9 @@ Material create_material( return material; } -Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, uint32_t max_frames_in_flight) { - VkShaderModule vert_shader = load_shader_file(2048, "shader_src/basic.vert.spv", device); - VkShaderModule frag_shader = load_shader_file(2048, "shader_src/basic.frag.spv", device); +Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, VkPushConstantRange scene_pcr, uint32_t max_frames_in_flight) { + VkShaderModule vert_shader = load_shader_file("shader_src/basic.vert.spv", device); + VkShaderModule frag_shader = load_shader_file("shader_src/basic.frag.spv", device); VkPipelineShaderStageCreateInfo shader_stages[2] = { { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, @@ -1979,16 +1998,16 @@ Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRende return tmp; } - return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, simple_layout, simple_mesh_type, max_frames_in_flight, object_descriptor_mappings); + return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, scene_pcr, simple_layout, simple_mesh_type, max_frames_in_flight, object_descriptor_mappings); } -Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, uint32_t max_frames_in_flight) { - VkShaderModule vert_shader = load_shader_file(2048, "shader_src/texture.vert.spv", device); +Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, VkPushConstantRange scene_pcr, uint32_t max_frames_in_flight) { + VkShaderModule vert_shader = load_shader_file("shader_src/texture.vert.spv", device); if(vert_shader == VK_NULL_HANDLE) { Material tmp = {}; return tmp; } - VkShaderModule frag_shader = load_shader_file(2048, "shader_src/texture.frag.spv", device); + VkShaderModule frag_shader = load_shader_file("shader_src/texture.frag.spv", device); if(frag_shader == VK_NULL_HANDLE) { Material tmp = {}; return tmp; @@ -2090,7 +2109,7 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend return tmp; } - return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, texture_layout, textured_mesh_type, max_frames_in_flight, object_descriptor_mappings); + return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, scene_pcr, texture_layout, textured_mesh_type, max_frames_in_flight, object_descriptor_mappings); } VkResult command_copy_to_buffer(VkDevice device, GPUBuffer staging, VkBuffer destination, void* data, VkDeviceSize size, VkDeviceSize offset, VkCommandPool pool, VkQueue queue) { @@ -2502,6 +2521,11 @@ SceneContext create_scene_context(VkDevice device, VkPhysicalDeviceMemoryPropert .descriptors = sets, .ubos = ubos, .ubo_ptrs = ubo_ptrs, + .pcr = { + .offset = 0, + .size = sizeof(struct ScenePC), + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + }, }; return scene; @@ -2641,7 +2665,7 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod vec3 world_position = {0.0f, 0.0f, 0.0f}; versor world_rotation = {-1.0f, 0.0f, 0.0f, 0.0f}; -VkResult update_scene_descriptor(void** buffers, uint32_t frame_index, vec3 world_position, versor world_rotation, float aspect_ratio, float time_delta) { +struct ScenePC get_scene_constants(vec3 world_position, versor world_rotation, float aspect_ratio, float time_delta) { vec3 movement_sum = {0.0f, 0.0f, 0.0f}; if(key_flags.forward) { @@ -2718,18 +2742,16 @@ VkResult update_scene_descriptor(void** buffers, uint32_t frame_index, vec3 worl glm_quat_rotatev(world_rotation, movement_sum, movement_rot); glm_vec3_add(movement_rot, world_position, world_position); - struct SceneUBO ubo = {}; - - glm_perspective(1.5708f, aspect_ratio, 0.01, 1000, ubo.proj); - glm_quat_look(world_position, world_rotation, ubo.view); + struct ScenePC constants = {}; - memcpy(buffers[frame_index], (void*)&ubo, sizeof(ubo)); + glm_perspective(1.5708f, aspect_ratio, 0.01, 1000, constants.proj); + glm_quat_look(world_position, world_rotation, constants.view); - return VK_SUCCESS; + return constants; } VkResult draw_frame(VulkanContext* context, SceneContext* scene, uint32_t materials_count, Material* materials, uint32_t* objects_counts, Object** objects) { - update_scene_descriptor(scene->ubo_ptrs, context->current_frame, world_position, world_rotation, (float)context->swapchain_extent.width/(float)context->swapchain_extent.height, 0.01); + struct ScenePC scene_constants = get_scene_constants(world_position, world_rotation, (float)context->swapchain_extent.width/(float)context->swapchain_extent.height, 0.01); VkResult result; result = vkWaitForFences(context->device, 1, &context->in_flight_fences[context->current_frame], VK_TRUE, UINT64_MAX); @@ -2753,7 +2775,7 @@ VkResult draw_frame(VulkanContext* context, SceneContext* scene, uint32_t materi return result; } - result = command_draw_scene(materials_count, materials, objects_counts, objects, context->current_frame, scene->descriptors, context->swapchain_command_buffers[context->current_frame], context->render_pass, context->swapchain_framebuffers[image_index], context->swapchain_extent); + result = command_draw_scene(materials_count, materials, objects_counts, objects, context->current_frame, scene->descriptors, &scene_constants, context->swapchain_command_buffers[context->current_frame], context->render_pass, context->swapchain_framebuffers[image_index], context->swapchain_extent); if(result != VK_SUCCESS) { return result; } @@ -3080,7 +3102,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { return; } - Material simple_mesh_material = create_simple_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, context->max_frames_in_flight); + Material simple_mesh_material = create_simple_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, scene.pcr, context->max_frames_in_flight); if(simple_mesh_material.pipeline == VK_NULL_HANDLE) { fprintf(stderr, "failed to create simple mesh material\n"); return; @@ -3113,7 +3135,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { return; } - Material texture_mesh_material = create_texture_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, context->max_frames_in_flight); + Material texture_mesh_material = create_texture_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, scene.pcr, context->max_frames_in_flight); if(texture_mesh_material.pipeline == VK_NULL_HANDLE) { fprintf(stderr, "failed to create texture mesh material\n"); return;