Replace MVP uniform buffer with push constants
UBO should be used for large data. MVP should be push constants, since it's a small amount of data updated every frame Signed-off-by: Piotr Krygier <piotrkrygier@everyonecancode@xyz>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(binding = 0) uniform UniformBufferObject {
|
layout(push_constant) uniform pc {
|
||||||
mat4 model;
|
mat4 model;
|
||||||
mat4 view;
|
mat4 view;
|
||||||
mat4 proj;
|
mat4 proj;
|
||||||
@@ -16,7 +16,7 @@ struct InstanceData
|
|||||||
uint texture_id;
|
uint texture_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(binding = 1) uniform InstanceUniformBuffer {
|
layout(binding = 0) uniform InstanceUniformBuffer {
|
||||||
InstanceData instances[MAX_INSTANCES];
|
InstanceData instances[MAX_INSTANCES];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#version 450
|
#version 450
|
||||||
#extension GL_EXT_nonuniform_qualifier : enable
|
#extension GL_EXT_nonuniform_qualifier : enable
|
||||||
|
|
||||||
layout(set = 0, binding = 2) uniform sampler2D texSampler[];
|
layout(set = 0, binding = 1) uniform sampler2D texSampler[];
|
||||||
|
|
||||||
layout(location = 0) in vec3 fragColor;
|
layout(location = 0) in vec3 fragColor;
|
||||||
layout(location = 1) in vec2 fragTexCoord;
|
layout(location = 1) in vec2 fragTexCoord;
|
||||||
|
|||||||
@@ -281,6 +281,7 @@ struct graphics_context_t
|
|||||||
uint32_t current_frame;
|
uint32_t current_frame;
|
||||||
uint32_t swapchain_images_count;
|
uint32_t swapchain_images_count;
|
||||||
SDL_Window* window_handle;
|
SDL_Window* window_handle;
|
||||||
|
struct mvp_data_t mvp_data;
|
||||||
struct renderer_data_t renderer_data;
|
struct renderer_data_t renderer_data;
|
||||||
struct debug_overlay_t debug_overlay;
|
struct debug_overlay_t debug_overlay;
|
||||||
struct vulkan_handles vulkan_handles;
|
struct vulkan_handles vulkan_handles;
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ rse_err_t pipeline_add_vertex_input_attribute(struct pipeline_t* pipeline,
|
|||||||
return RSE_ERROR_NO_ERROR;
|
return RSE_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rse_err_t pipeline_addd_push_constants(struct pipeline_t* pipeline,
|
rse_err_t pipeline_add_push_constants(struct pipeline_t* pipeline,
|
||||||
VkShaderStageFlagBits shader_stage,
|
VkShaderStageFlagBits shader_stage,
|
||||||
uint32_t offset,
|
uint32_t offset,
|
||||||
uint32_t size)
|
uint32_t size)
|
||||||
|
|||||||
@@ -92,6 +92,18 @@ rse_err_t pipeline_add_dynamic_state(struct pipeline_t* pipeline, const VkDynami
|
|||||||
rse_err_t pipeline_add_descriptor_sets(struct graphics_context_t* context,
|
rse_err_t pipeline_add_descriptor_sets(struct graphics_context_t* context,
|
||||||
struct pipeline_t* pipeline,
|
struct pipeline_t* pipeline,
|
||||||
uint32_t descriptor_set_id);
|
uint32_t descriptor_set_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add push constants to pipeline
|
||||||
|
*
|
||||||
|
* @return RSE_ERROR_NO_ERROR on success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
rse_err_t pipeline_add_push_constants(struct pipeline_t* pipeline,
|
||||||
|
VkShaderStageFlagBits shader_stage,
|
||||||
|
uint32_t offset,
|
||||||
|
uint32_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Build pipeline from added components. This function should be called after adding all necessary components.
|
* @brief Build pipeline from added components. This function should be called after adding all necessary components.
|
||||||
* After call, pipeline is ready to be used and all added components are cleared, ready for next pipeline to be built.
|
* After call, pipeline is ready to be used and all added components are cleared, ready for next pipeline to be built.
|
||||||
|
|||||||
+88
-66
@@ -7,7 +7,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
#include "descriptor_builder.h"
|
#include "descriptor_builder.h"
|
||||||
@@ -29,15 +28,62 @@ struct rse_graphics_context_t
|
|||||||
struct graphics_context_t* context;
|
struct graphics_context_t* context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void model_view_projection_update(struct graphics_context_t* context)
|
||||||
|
{
|
||||||
|
vec3 eye = {0};
|
||||||
|
vec3 center = {0};
|
||||||
|
vec3 up = {0};
|
||||||
|
vec3 rotation_vec = {1.0f, 0.0f, 0.0f};
|
||||||
|
float fovy;
|
||||||
|
float z_near;
|
||||||
|
float z_far;
|
||||||
|
|
||||||
|
eye[2] = -5.0f;
|
||||||
|
|
||||||
|
up[1] = 1.0f;
|
||||||
|
|
||||||
|
fovy = glm_rad(45.0f);
|
||||||
|
z_near = 0.1f;
|
||||||
|
z_far = 20.0f;
|
||||||
|
|
||||||
|
glm_mat4_identity(context->mvp_data.model);
|
||||||
|
|
||||||
|
glm_rotate(context->mvp_data.model, glm_rad(0.0f), rotation_vec);
|
||||||
|
glm_lookat(eye, center, up, context->mvp_data.view);
|
||||||
|
glm_perspective(
|
||||||
|
fovy,
|
||||||
|
context->swapchain_data.swapchain_extent.width / (float)context->swapchain_data.swapchain_extent.height,
|
||||||
|
z_near,
|
||||||
|
z_far,
|
||||||
|
context->mvp_data.proj);
|
||||||
|
}
|
||||||
|
|
||||||
static rse_err_t render_static_mesh(struct graphics_context_t* context, uint32_t renderer_id)
|
static rse_err_t render_static_mesh(struct graphics_context_t* context, uint32_t renderer_id)
|
||||||
{
|
{
|
||||||
VkCommandBuffer command_buffer = context->vulkan_handles.command_buffers[context->current_frame];
|
VkCommandBuffer command_buffer = context->vulkan_handles.command_buffers[context->current_frame];
|
||||||
VkDeviceSize offsets[] = {0};
|
VkDeviceSize offsets[] = {0};
|
||||||
|
uint32_t mvp_offset = 0;
|
||||||
|
uint32_t mvp_size = sizeof(struct mvp_data_t);
|
||||||
|
|
||||||
(void)renderer_id;
|
(void)renderer_id;
|
||||||
|
|
||||||
|
vkCmdPushConstants(command_buffer,
|
||||||
|
context->pipelines_data.pipeline_layouts[0],
|
||||||
|
VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
mvp_offset,
|
||||||
|
mvp_size,
|
||||||
|
&context->mvp_data);
|
||||||
|
model_view_projection_update(context);
|
||||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, context->pipelines_data.pipelines[0]);
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, context->pipelines_data.pipelines[0]);
|
||||||
vkCmdBindIndexBuffer(command_buffer, context->render_targets[RENDER_TARGET_3D].index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
vkCmdBindIndexBuffer(command_buffer,
|
||||||
vkCmdBindVertexBuffers(command_buffer, 0, 1, &context->render_targets[RENDER_TARGET_3D].vertex_buffer.buffer, offsets);
|
context->render_targets[RENDER_TARGET_3D].index_buffer.buffer,
|
||||||
|
0,
|
||||||
|
VK_INDEX_TYPE_UINT16);
|
||||||
|
vkCmdBindVertexBuffers(command_buffer,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
&context->render_targets[RENDER_TARGET_3D].vertex_buffer.buffer,
|
||||||
|
offsets);
|
||||||
/* FIXME: Currently we can only bind one descriptor set */
|
/* FIXME: Currently we can only bind one descriptor set */
|
||||||
vkCmdBindDescriptorSets(command_buffer,
|
vkCmdBindDescriptorSets(command_buffer,
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
@@ -57,38 +103,6 @@ static rse_err_t render_static_mesh(struct graphics_context_t* context, uint32_t
|
|||||||
return RSE_ERROR_NO_ERROR;
|
return RSE_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void model_view_projection_update(struct graphics_context_t* context, const struct vulkan_buffer_t* buffer)
|
|
||||||
{
|
|
||||||
struct uniform_buffer_object_t ubo = {0};
|
|
||||||
vec3 eye = {0};
|
|
||||||
vec3 center = {0};
|
|
||||||
vec3 up = {0};
|
|
||||||
vec3 rotation_vec = {1.0f, 0.0f, 0.0f};
|
|
||||||
float fovy;
|
|
||||||
float z_near;
|
|
||||||
float z_far;
|
|
||||||
|
|
||||||
eye[2] = -5.0f;
|
|
||||||
|
|
||||||
up[1] = 1.0f;
|
|
||||||
|
|
||||||
fovy = glm_rad(45.0f);
|
|
||||||
z_near = 0.1f;
|
|
||||||
z_far = 20.0f;
|
|
||||||
|
|
||||||
glm_mat4_identity(ubo.model);
|
|
||||||
|
|
||||||
glm_rotate(ubo.model, glm_rad(0.0f), rotation_vec);
|
|
||||||
glm_lookat(eye, center, up, ubo.view);
|
|
||||||
glm_perspective(
|
|
||||||
fovy,
|
|
||||||
context->swapchain_data.swapchain_extent.width / (float)context->swapchain_data.swapchain_extent.height,
|
|
||||||
z_near,
|
|
||||||
z_far,
|
|
||||||
ubo.proj);
|
|
||||||
memcpy(buffer->allocation_info.pMappedData, &ubo, sizeof(ubo));
|
|
||||||
}
|
|
||||||
|
|
||||||
rse_err_t rse_graphics_init(struct rse_graphics_context_t** context)
|
rse_err_t rse_graphics_init(struct rse_graphics_context_t** context)
|
||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
@@ -110,23 +124,23 @@ rse_err_t rse_graphics_init(struct rse_graphics_context_t** context)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TEXTURES_COUNT (2U)
|
||||||
rse_err_t rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
rse_err_t rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
struct graphics_context_t* context = rse_context->context;
|
struct graphics_context_t* context = rse_context->context;
|
||||||
rse_id_t textures[2] = {0};
|
rse_id_t textures[TEXTURES_COUNT] = {0};
|
||||||
struct pipeline_t pipeline;
|
struct pipeline_t pipeline;
|
||||||
rse_id_t descriptor_set_handle = 0;
|
rse_id_t descriptor_set_handle = 0;
|
||||||
struct descriptor_set_layout_bindings_t layout_bindings = {0};
|
struct descriptor_set_layout_bindings_t layout_bindings = {0};
|
||||||
struct pipeline_infos_t pipeline_infos = {0};
|
struct pipeline_infos_t pipeline_infos = {0};
|
||||||
struct vulkan_buffer_t model_view_projection_buffer = {0};
|
|
||||||
rse_id_t mesh_id_1, mesh_id_2 = 0;
|
rse_id_t mesh_id_1, mesh_id_2 = 0;
|
||||||
rse_id_t font_id = 0;
|
rse_id_t font_id = 0;
|
||||||
rse_id_t static_mesh_renderer = 0U;
|
rse_id_t static_mesh_renderer = 0U;
|
||||||
rse_id_t vertex_shader_id, fragment_shader_id;
|
rse_id_t vertex_shader_id, fragment_shader_id;
|
||||||
|
|
||||||
texture_load_from_file(context, "../../test_image.jpg", &textures[0]);
|
STATUS_CHECK(texture_load_from_file(context, "../../test_image.jpg", &textures[0]));
|
||||||
texture_load_from_file(context, "../../test_image_2.jpg", &textures[1]);
|
STATUS_CHECK(texture_load_from_file(context, "../../test_image_2.jpg", &textures[1]));
|
||||||
|
|
||||||
STATUS_CHECK(fonts_init());
|
STATUS_CHECK(fonts_init());
|
||||||
STATUS_CHECK(fonts_load_from_file(context, "../../NotoSansMono-Regular.ttf", &font_id));
|
STATUS_CHECK(fonts_load_from_file(context, "../../NotoSansMono-Regular.ttf", &font_id));
|
||||||
@@ -146,7 +160,7 @@ rse_err_t rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
|||||||
// FIXME: Temporary array of vertices, for testing purposes
|
// FIXME: Temporary array of vertices, for testing purposes
|
||||||
uint16_t indices[] = {0, 1, 2, 2, 3, 0};
|
uint16_t indices[] = {0, 1, 2, 2, 3, 0};
|
||||||
|
|
||||||
mesh_create(context, vertices, indices, 4, 6, &mesh_id_1);
|
STATUS_CHECK(mesh_create(context, vertices, indices, 4, 6, &mesh_id_1));
|
||||||
if (RSE_ERROR_NO_ERROR !=
|
if (RSE_ERROR_NO_ERROR !=
|
||||||
mesh_create_instance(context,
|
mesh_create_instance(context,
|
||||||
mesh_id_1,
|
mesh_id_1,
|
||||||
@@ -162,7 +176,7 @@ rse_err_t rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh_create(context, vertices2, indices, 4, 6, &mesh_id_2);
|
STATUS_CHECK(mesh_create(context, vertices2, indices, 4, 6, &mesh_id_2));
|
||||||
|
|
||||||
if (RSE_ERROR_NO_ERROR !=
|
if (RSE_ERROR_NO_ERROR !=
|
||||||
mesh_create_instance(
|
mesh_create_instance(
|
||||||
@@ -172,36 +186,38 @@ rse_err_t rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_create_uniform(context, &model_view_projection_buffer, sizeof(struct uniform_buffer_object_t));
|
STATUS_CHECK(buffers_update(context));
|
||||||
model_view_projection_update(context, &model_view_projection_buffer);
|
|
||||||
buffers_update(context);
|
|
||||||
|
|
||||||
sampler_create(context, &context->vulkan_handles.sampler);
|
STATUS_CHECK(sampler_create(context, &context->vulkan_handles.sampler));
|
||||||
|
|
||||||
descriptor_pool_add_type(context, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2);
|
STATUS_CHECK(descriptor_pool_add_type(context, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1));
|
||||||
descriptor_pool_add_type(context, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2);
|
STATUS_CHECK(descriptor_pool_add_type(context, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, TEXTURES_COUNT));
|
||||||
descriptor_pool_initialize(context);
|
STATUS_CHECK(descriptor_pool_initialize(context));
|
||||||
|
|
||||||
/* Normal rendering */
|
/* Normal rendering */
|
||||||
descriptor_create_new_set(context, &descriptor_set_handle);
|
STATUS_CHECK(descriptor_create_new_set(context, &descriptor_set_handle));
|
||||||
descriptor_add_layout(&layout_bindings, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT);
|
STATUS_CHECK(
|
||||||
descriptor_add_layout(&layout_bindings, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT);
|
descriptor_add_layout(&layout_bindings, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT));
|
||||||
descriptor_add_layout(&layout_bindings, 2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, VK_SHADER_STAGE_FRAGMENT_BIT);
|
STATUS_CHECK(descriptor_add_layout(&layout_bindings,
|
||||||
descriptor_set_finish(context, &layout_bindings, descriptor_set_handle);
|
1,
|
||||||
descriptor_build_sets(context);
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
TEXTURES_COUNT,
|
||||||
|
VK_SHADER_STAGE_FRAGMENT_BIT));
|
||||||
|
STATUS_CHECK(descriptor_set_finish(context, &layout_bindings, descriptor_set_handle));
|
||||||
|
STATUS_CHECK(descriptor_build_sets(context));
|
||||||
|
|
||||||
descriptor_attach_buffer(context,
|
STATUS_CHECK(descriptor_attach_buffer(context,
|
||||||
descriptor_set_handle,
|
descriptor_set_handle,
|
||||||
&model_view_projection_buffer,
|
&context->render_targets[RENDER_TARGET_3D].instance_buffer,
|
||||||
0,
|
0,
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER));
|
||||||
descriptor_attach_buffer(context,
|
|
||||||
descriptor_set_handle,
|
|
||||||
&context->render_targets[RENDER_TARGET_3D].instance_buffer,
|
|
||||||
1,
|
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
|
||||||
|
|
||||||
descriptor_attach_images(context, descriptor_set_handle, textures, 2, context->vulkan_handles.sampler, 2);
|
STATUS_CHECK(descriptor_attach_images(context,
|
||||||
|
descriptor_set_handle,
|
||||||
|
textures,
|
||||||
|
TEXTURES_COUNT,
|
||||||
|
context->vulkan_handles.sampler,
|
||||||
|
1));
|
||||||
|
|
||||||
/* Initialize pipeline */
|
/* Initialize pipeline */
|
||||||
pipeline_builder_init(&pipeline);
|
pipeline_builder_init(&pipeline);
|
||||||
@@ -215,12 +231,18 @@ rse_err_t rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
|||||||
|
|
||||||
pipeline_add_vertex_input_attribute(&pipeline, 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct vertex_t, pos));
|
pipeline_add_vertex_input_attribute(&pipeline, 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct vertex_t, pos));
|
||||||
pipeline_add_vertex_input_attribute(&pipeline, 0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct vertex_t, color));
|
pipeline_add_vertex_input_attribute(&pipeline, 0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct vertex_t, color));
|
||||||
pipeline_add_vertex_input_attribute(&pipeline, 0, 2, VK_FORMAT_R32G32_SFLOAT, offsetof(struct vertex_t, tex_coords));
|
pipeline_add_vertex_input_attribute(&pipeline,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
VK_FORMAT_R32G32_SFLOAT,
|
||||||
|
offsetof(struct vertex_t, tex_coords));
|
||||||
|
|
||||||
pipeline_add_dynamic_state(&pipeline, VK_DYNAMIC_STATE_VIEWPORT);
|
pipeline_add_dynamic_state(&pipeline, VK_DYNAMIC_STATE_VIEWPORT);
|
||||||
pipeline_add_dynamic_state(&pipeline, VK_DYNAMIC_STATE_SCISSOR);
|
pipeline_add_dynamic_state(&pipeline, VK_DYNAMIC_STATE_SCISSOR);
|
||||||
|
|
||||||
|
pipeline_add_push_constants(&pipeline, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(struct mvp_data_t));
|
||||||
pipeline_add_descriptor_sets(context, &pipeline, descriptor_set_handle);
|
pipeline_add_descriptor_sets(context, &pipeline, descriptor_set_handle);
|
||||||
|
|
||||||
pipeline_add(context, &pipeline, &pipeline_infos);
|
pipeline_add(context, &pipeline, &pipeline_infos);
|
||||||
|
|
||||||
pipelines_build(context, &pipeline_infos);
|
pipelines_build(context, &pipeline_infos);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ struct vulkan_buffer_t
|
|||||||
VmaAllocationInfo allocation_info;
|
VmaAllocationInfo allocation_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uniform_buffer_object_t
|
struct mvp_data_t
|
||||||
{
|
{
|
||||||
alignas(16) mat4 model;
|
alignas(16) mat4 model;
|
||||||
alignas(16) mat4 view;
|
alignas(16) mat4 view;
|
||||||
|
|||||||
Reference in New Issue
Block a user