Switch to using push constants for scene data

main
noah metz 2024-01-12 21:12:31 -07:00
parent ed034b39ab
commit 8dea83ca37
4 changed files with 61 additions and 31 deletions

@ -57,7 +57,7 @@ debug: spacegame
%.vert.spv: %.vert %.vert.spv: %.vert
glslc $< -o $@ glslangValidator -V -o $@ $<
%.frag.spv: %.frag %.frag.spv: %.frag
glslc $< -o $@ glslangValidator -V -o $@ $<

@ -1,10 +1,14 @@
#version 450 #version 450
layout(set = 0, binding = 0) uniform SceneUniform { layout( push_constant ) uniform constants {
mat4 view; mat4 view;
mat4 proj; mat4 proj;
} scene; } scene;
layout(set = 0, binding = 0) uniform SceneUniform {
mat4 test;
} scene_ubo;
layout(set = 2, binding = 0) uniform ModelUniform { layout(set = 2, binding = 0) uniform ModelUniform {
mat4 model; mat4 model;
} model_ubo; } model_ubo;

@ -1,8 +1,12 @@
#version 450 #version 450
layout(set = 0, binding = 0) uniform SceneUniformBuffer { layout( push_constant ) uniform constants {
mat4 view; mat4 view;
mat4 proj; mat4 proj;
} scene_pc;
layout(set = 0, binding = 0) uniform SceneUniformBuffer {
mat4 test;
} scene_ubo; } scene_ubo;
layout(set = 2, binding = 1) uniform ObjectUniformBuffer { layout(set = 2, binding = 1) uniform ObjectUniformBuffer {
@ -17,7 +21,7 @@ layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTex; layout(location = 1) out vec2 fragTex;
void main() { 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; fragColor = inColor;
fragTex = inTex; fragTex = inTex;
} }

@ -190,6 +190,7 @@ typedef struct SceneContextStruct {
VkDescriptorSet* descriptors; VkDescriptorSet* descriptors;
GPUBuffer* ubos; GPUBuffer* ubos;
void** ubo_ptrs; void** ubo_ptrs;
VkPushConstantRange pcr;
} SceneContext; } SceneContext;
struct TextureVertex { struct TextureVertex {
@ -208,6 +209,10 @@ struct ModelUBO {
}; };
struct SceneUBO { struct SceneUBO {
mat4 test;
};
struct ScenePC {
mat4 view; mat4 view;
mat4 proj; mat4 proj;
}; };
@ -895,13 +900,25 @@ VkShaderModule create_shader_module(VkDevice device, const char * code, uint32_t
return shader; 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* file;
file = fopen(path, "r"); file = fopen(path, "rb");
if(file == 0) { if(file == 0) {
return VK_NULL_HANDLE; 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); char * buffer = malloc(buffer_size);
if(buffer == 0) { if(buffer == 0) {
return VK_NULL_HANDLE; 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); 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); 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); vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 0, 1, &scene_descriptors[frame_num], 0, 0);
if(material.material_descriptors != 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); 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 = { VkCommandBufferBeginInfo begin_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = 0, .flags = 0,
@ -1625,7 +1643,7 @@ VkResult command_draw_scene(uint32_t materials_count, Material* materials, uint3
vkCmdSetScissor(command_buffer, 0, 1, &scissor); vkCmdSetScissor(command_buffer, 0, 1, &scissor);
for(uint i = 0; i < materials_count; i++) { 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); vkCmdEndRenderPass(command_buffer);
@ -1762,6 +1780,7 @@ Material create_material(
uint32_t shader_stage_count, uint32_t shader_stage_count,
VkPipelineShaderStageCreateInfo* shader_stages, VkPipelineShaderStageCreateInfo* shader_stages,
VkDescriptorSetLayout scene_ubo_layout, VkDescriptorSetLayout scene_ubo_layout,
VkPushConstantRange scene_pcr,
PipelineLayout pipeline_layout, PipelineLayout pipeline_layout,
MeshType mesh_type, MeshType mesh_type,
uint32_t max_frames_in_flight, uint32_t max_frames_in_flight,
@ -1862,8 +1881,8 @@ Material create_material(
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 3, .setLayoutCount = 3,
.pSetLayouts = all_layouts, .pSetLayouts = all_layouts,
.pushConstantRangeCount = 0, .pushConstantRangeCount = 1,
.pPushConstantRanges = 0, .pPushConstantRanges = &scene_pcr,
}; };
result = vkCreatePipelineLayout(device, &layout_info, 0, &layout); result = vkCreatePipelineLayout(device, &layout_info, 0, &layout);
@ -1892,9 +1911,9 @@ Material create_material(
return 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) { 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(2048, "shader_src/basic.vert.spv", device); VkShaderModule vert_shader = load_shader_file("shader_src/basic.vert.spv", device);
VkShaderModule frag_shader = load_shader_file(2048, "shader_src/basic.frag.spv", device); VkShaderModule frag_shader = load_shader_file("shader_src/basic.frag.spv", device);
VkPipelineShaderStageCreateInfo shader_stages[2] = { VkPipelineShaderStageCreateInfo shader_stages[2] = {
{ {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .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 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) { 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(2048, "shader_src/texture.vert.spv", device); VkShaderModule vert_shader = load_shader_file("shader_src/texture.vert.spv", device);
if(vert_shader == VK_NULL_HANDLE) { if(vert_shader == VK_NULL_HANDLE) {
Material tmp = {}; Material tmp = {};
return 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) { if(frag_shader == VK_NULL_HANDLE) {
Material tmp = {}; Material tmp = {};
return tmp; return tmp;
@ -2090,7 +2109,7 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend
return tmp; 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) { 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, .descriptors = sets,
.ubos = ubos, .ubos = ubos,
.ubo_ptrs = ubo_ptrs, .ubo_ptrs = ubo_ptrs,
.pcr = {
.offset = 0,
.size = sizeof(struct ScenePC),
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
},
}; };
return scene; 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}; vec3 world_position = {0.0f, 0.0f, 0.0f};
versor world_rotation = {-1.0f, 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}; vec3 movement_sum = {0.0f, 0.0f, 0.0f};
if(key_flags.forward) { 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_quat_rotatev(world_rotation, movement_sum, movement_rot);
glm_vec3_add(movement_rot, world_position, world_position); glm_vec3_add(movement_rot, world_position, world_position);
struct SceneUBO ubo = {}; struct ScenePC constants = {};
glm_perspective(1.5708f, aspect_ratio, 0.01, 1000, ubo.proj);
glm_quat_look(world_position, world_rotation, ubo.view);
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) { 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; VkResult result;
result = vkWaitForFences(context->device, 1, &context->in_flight_fences[context->current_frame], VK_TRUE, UINT64_MAX); 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; 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) { if(result != VK_SUCCESS) {
return result; return result;
} }
@ -3080,7 +3102,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) {
return; 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) { if(simple_mesh_material.pipeline == VK_NULL_HANDLE) {
fprintf(stderr, "failed to create simple mesh material\n"); fprintf(stderr, "failed to create simple mesh material\n");
return; return;
@ -3113,7 +3135,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) {
return; 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) { if(texture_mesh_material.pipeline == VK_NULL_HANDLE) {
fprintf(stderr, "failed to create texture mesh material\n"); fprintf(stderr, "failed to create texture mesh material\n");
return; return;