From e6675e19adf5396f9ca151a40f041e2fbd4eea94 Mon Sep 17 00:00:00 2001 From: korenkonder Date: Wed, 28 Aug 2024 20:19:16 +0300 Subject: [PATCH] Vulkan: Added `Push Constants` for `Common Scene` include --- src/CRE/Vulkan/DescriptorPipeline.cpp | 7 +- src/CRE/Vulkan/DescriptorPipeline.hpp | 3 +- src/CRE/Vulkan/gl_wrap.cpp | 73 ++++++----------- src/CRE/Vulkan/gl_wrap.hpp | 23 ++++++ src/CRE/Vulkan/manager.cpp | 15 ++-- src/CRE/Vulkan/manager.hpp | 3 +- src/CRE/shader.cpp | 108 ++++++++++++++++++++++++-- src/CRE/shader_ft.cpp | 2 +- 8 files changed, 169 insertions(+), 65 deletions(-) diff --git a/src/CRE/Vulkan/DescriptorPipeline.cpp b/src/CRE/Vulkan/DescriptorPipeline.cpp index 19de5b24..e42630c7 100644 --- a/src/CRE/Vulkan/DescriptorPipeline.cpp +++ b/src/CRE/Vulkan/DescriptorPipeline.cpp @@ -32,7 +32,8 @@ namespace Vulkan { DescriptorPipeline::DescriptorPipeline(VkDevice device, VkDescriptorPool descriptor_pool, uint32_t sampler_count, uint32_t uniform_count, uint32_t storage_count, - const VkDescriptorSetLayoutBinding* bindings) { + const VkDescriptorSetLayoutBinding* bindings, + uint32_t push_constant_range_count, VkPushConstantRange* push_constant_ranges) { this->device = device; this->descriptor_pool = descriptor_pool; @@ -92,8 +93,8 @@ namespace Vulkan { pipeline_layout_create_info.flags = 0; pipeline_layout_create_info.setLayoutCount = set_layout_count; pipeline_layout_create_info.pSetLayouts = descriptor_set_layouts; - pipeline_layout_create_info.pushConstantRangeCount = 0; - pipeline_layout_create_info.pPushConstantRanges = 0; + pipeline_layout_create_info.pushConstantRangeCount = push_constant_range_count; + pipeline_layout_create_info.pPushConstantRanges = push_constant_ranges; if (vkCreatePipelineLayout(device, &pipeline_layout_create_info, 0, &pipeline_layout) == VK_SUCCESS) return; diff --git a/src/CRE/Vulkan/DescriptorPipeline.hpp b/src/CRE/Vulkan/DescriptorPipeline.hpp index 7c36ec68..3ea990ed 100644 --- a/src/CRE/Vulkan/DescriptorPipeline.hpp +++ b/src/CRE/Vulkan/DescriptorPipeline.hpp @@ -34,7 +34,8 @@ namespace Vulkan { public: DescriptorPipeline(VkDevice device, VkDescriptorPool descriptor_pool, uint32_t sampler_count, uint32_t uniform_count, uint32_t storage_count, - const VkDescriptorSetLayoutBinding* bindings); + const VkDescriptorSetLayoutBinding* bindings, + uint32_t push_constant_range_count, VkPushConstantRange* push_constant_ranges); ~DescriptorPipeline(); DescriptorSetCollection* GetDescriptorSetCollection(uint32_t frame, uint64_t hash); diff --git a/src/CRE/Vulkan/gl_wrap.cpp b/src/CRE/Vulkan/gl_wrap.cpp index f35a189d..1df969e9 100644 --- a/src/CRE/Vulkan/gl_wrap.cpp +++ b/src/CRE/Vulkan/gl_wrap.cpp @@ -14,29 +14,6 @@ #include namespace Vulkan { - enum gl_buffer_flags { - GL_BUFFER_FLAG_NONE = 0x00, - GL_BUFFER_FLAG_MAPPED = 0x01, - GL_BUFFER_FLAG_IMMUTABLE_STORAGE = 0x02, - GL_BUFFER_FLAG_UPDATE_DATA = 0x04, - GL_BUFFER_FLAG_MAP_READ_BIT = 0x08, - GL_BUFFER_FLAG_MAP_WRITE_BIT = 0x10, - GL_BUFFER_FLAG_DYNAMIC_STORAGE_BIT = 0x20, - }; - - struct gl_buffer { - GLenum target; - gl_buffer_flags flags; - std::vector data; - - gl_buffer(); - ~gl_buffer(); - - gl_buffer& operator=(const gl_buffer& other); - - static gl_buffer* get(GLuint buffer); - }; - struct gl_texture_data { struct tex_data { std::vector data; @@ -229,6 +206,31 @@ namespace Vulkan { static void gl_wrap_manager_vertex_attrib_pointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); + gl_buffer::gl_buffer() : target(), flags() { + + } + + gl_buffer::~gl_buffer() { + + } + + gl_buffer& gl_buffer::operator=(const gl_buffer& other) { + target = other.target; + flags = other.flags; + data.assign(other.data.begin(), other.data.end()); + return *this; + } + + gl_buffer* gl_buffer::get(GLuint buffer) { + if (!buffer) + return 0; + + auto elem = gl_wrap_manager_ptr->gl_buffers.find(buffer); + if (elem != gl_wrap_manager_ptr->gl_buffers.end()) + return &elem->second; + return 0; + } + gl_framebuffer::gl_framebuffer() : render_pass(), color_attachments(), color_attachment_levels(), depth_attachment(), depth_attachment_level(), draw_buffers(), update_color_attachment(), update_depth_attachment(), update_framebuffer() { @@ -1286,31 +1288,6 @@ namespace Vulkan { } } - gl_buffer::gl_buffer() : target(), flags() { - - } - - gl_buffer::~gl_buffer() { - - } - - gl_buffer& gl_buffer::operator=(const gl_buffer& other) { - target = other.target; - flags = other.flags; - data.assign(other.data.begin(), other.data.end()); - return *this; - } - - gl_buffer* gl_buffer::get(GLuint buffer) { - if (!buffer) - return 0; - - auto elem = gl_wrap_manager_ptr->gl_buffers.find(buffer); - if (elem != gl_wrap_manager_ptr->gl_buffers.end()) - return &elem->second; - return 0; - } - gl_texture_data::tex_data::tex_data() { } diff --git a/src/CRE/Vulkan/gl_wrap.hpp b/src/CRE/Vulkan/gl_wrap.hpp index ffb4bac1..5be5cb50 100644 --- a/src/CRE/Vulkan/gl_wrap.hpp +++ b/src/CRE/Vulkan/gl_wrap.hpp @@ -27,6 +27,29 @@ namespace Vulkan { constexpr uint32_t MAX_COLOR_ATTACHMENTS = 8; constexpr uint32_t MAX_DRAW_BUFFERS = 8; constexpr uint32_t MAX_VERTEX_ATTRIB_COUNT = 16; + + enum gl_buffer_flags { + GL_BUFFER_FLAG_NONE = 0x00, + GL_BUFFER_FLAG_MAPPED = 0x01, + GL_BUFFER_FLAG_IMMUTABLE_STORAGE = 0x02, + GL_BUFFER_FLAG_UPDATE_DATA = 0x04, + GL_BUFFER_FLAG_MAP_READ_BIT = 0x08, + GL_BUFFER_FLAG_MAP_WRITE_BIT = 0x10, + GL_BUFFER_FLAG_DYNAMIC_STORAGE_BIT = 0x20, + }; + + struct gl_buffer { + GLenum target; + gl_buffer_flags flags; + std::vector data; + + gl_buffer(); + ~gl_buffer(); + + gl_buffer& operator=(const gl_buffer& other); + + static gl_buffer* get(GLuint buffer); + }; struct gl_framebuffer { Vulkan::Framebuffer framebuffer; diff --git a/src/CRE/Vulkan/manager.cpp b/src/CRE/Vulkan/manager.cpp index 29793d07..822da59c 100644 --- a/src/CRE/Vulkan/manager.cpp +++ b/src/CRE/Vulkan/manager.cpp @@ -201,7 +201,8 @@ namespace Vulkan { prj::shared_ptr get_descriptor_pipeline( uint64_t vp_desc_hash, uint64_t fp_desc_hash, uint64_t unival_hash, uint32_t sampler_count, uint32_t uniform_count, uint32_t storage_count, - const VkDescriptorSetLayoutBinding* bindings); + const VkDescriptorSetLayoutBinding* bindings, + uint32_t push_constant_range_count, VkPushConstantRange* push_constant_ranges); frame_data& get_frame_data(); prj::shared_ptr get_pipeline(uint32_t stage_count, const VkPipelineShaderStageCreateInfo* stages, @@ -265,9 +266,11 @@ namespace Vulkan { prj::shared_ptr manager_get_descriptor_pipeline( uint64_t vp_desc_hash, uint64_t fp_desc_hash, uint64_t unival_hash, uint32_t sampler_count, uint32_t uniform_count, uint32_t storage_count, - const VkDescriptorSetLayoutBinding* bindings) { + const VkDescriptorSetLayoutBinding* bindings, + uint32_t push_constant_range_count, VkPushConstantRange* push_constant_ranges) { return manager_ptr->get_descriptor_pipeline(vp_desc_hash, fp_desc_hash, unival_hash, - sampler_count, uniform_count, storage_count, bindings); + sampler_count, uniform_count, storage_count, bindings, + push_constant_range_count, push_constant_ranges); } uint32_t manager_get_frame() { @@ -427,14 +430,16 @@ namespace Vulkan { prj::shared_ptr manager::get_descriptor_pipeline( uint64_t vp_desc_hash, uint64_t fp_desc_hash, uint64_t unival_hash, uint32_t sampler_count, uint32_t uniform_count, uint32_t storage_count, - const VkDescriptorSetLayoutBinding* bindings) { + const VkDescriptorSetLayoutBinding* bindings, + uint32_t push_constant_range_count, VkPushConstantRange* push_constant_ranges) { auto elem = descriptor_pipelines.find({ vp_desc_hash, fp_desc_hash, unival_hash }); if (elem != descriptor_pipelines.end()) return elem->second; prj::shared_ptr descriptor_pipeline( new Vulkan::DescriptorPipeline(Vulkan::current_device, Vulkan::current_descriptor_pool, - sampler_count, uniform_count, storage_count, bindings)); + sampler_count, uniform_count, storage_count, + bindings, push_constant_range_count, push_constant_ranges)); descriptor_pipelines.insert({ { vp_desc_hash, fp_desc_hash, unival_hash }, descriptor_pipeline }); return descriptor_pipeline; } diff --git a/src/CRE/Vulkan/manager.hpp b/src/CRE/Vulkan/manager.hpp index f26a0e3c..f36883fb 100644 --- a/src/CRE/Vulkan/manager.hpp +++ b/src/CRE/Vulkan/manager.hpp @@ -27,7 +27,8 @@ namespace Vulkan { extern prj::shared_ptr manager_get_descriptor_pipeline( uint64_t vp_desc_hash, uint64_t fp_desc_hash, uint64_t unival_hash, uint32_t sampler_count, uint32_t uniform_count, uint32_t storage_count, - const VkDescriptorSetLayoutBinding* bindings); + const VkDescriptorSetLayoutBinding* bindings, + uint32_t push_constant_range_count, VkPushConstantRange* push_constant_ranges); extern uint32_t manager_get_frame(); extern prj::shared_ptr manager_get_pipeline(uint32_t stage_count, const VkPipelineShaderStageCreateInfo* stages, diff --git a/src/CRE/shader.cpp b/src/CRE/shader.cpp index 481ebc23..17216e12 100644 --- a/src/CRE/shader.cpp +++ b/src/CRE/shader.cpp @@ -123,6 +123,16 @@ static void parse_define_inner(std::string& temp, bool vulkan) { temp.replace(pos, 11, "gl_VertexIndex"); off = pos + 14; } + + off = 0; + while (true) { + size_t pos = temp.find("layout(set = 1, binding = 0) uniform Shader", off); + if (pos == -1) + break; + + temp.replace(pos, 43, "layout(push_constant) uniform Shader"); + off = pos + 36; + } } } @@ -1373,6 +1383,7 @@ static bool shader_update_data(shader_set_data* set, GLenum mode, GLenum type, c uint32_t sampler_count = 0; uint32_t uniform_count = 0; uint32_t storage_count = 0; + uint32_t push_constant_range_count = 0; uint32_t fragment_output_count = 0; bool enabled_attributes[Vulkan::MAX_VERTEX_ATTRIB_COUNT] = {}; @@ -1394,7 +1405,10 @@ static bool shader_update_data(shader_set_data* set, GLenum mode, GLenum type, c sampler_count++; break; case SHADER_DESCRIPTION_UNIFORM: - uniform_count++; + if (desc->binding == -1) + push_constant_range_count++; + else + uniform_count++; break; case SHADER_DESCRIPTION_STORAGE: storage_count++; @@ -1414,7 +1428,10 @@ static bool shader_update_data(shader_set_data* set, GLenum mode, GLenum type, c sampler_count++; break; case SHADER_DESCRIPTION_UNIFORM: - uniform_count++; + if (desc->binding == -1) + push_constant_range_count++; + else + uniform_count++; break; case SHADER_DESCRIPTION_STORAGE: storage_count++; @@ -1440,13 +1457,16 @@ static bool shader_update_data(shader_set_data* set, GLenum mode, GLenum type, c const uint32_t storage_max_count = storage_count; VkDescriptorSetLayoutBinding* bindings = force_malloc( - (size_t)sampler_max_count + uniform_max_count + storage_max_count); + (size_t)sampler_max_count + uniform_max_count + storage_max_count + push_constant_range_count); VkDescriptorSetLayoutBinding* sampler_bindings = bindings; - VkDescriptorSetLayoutBinding* uniform_bindings = bindings + sampler_max_count; + VkDescriptorSetLayoutBinding* uniform_bindings = sampler_bindings + sampler_max_count; VkDescriptorSetLayoutBinding* storage_bindings = bindings + sampler_max_count + uniform_max_count; + VkPushConstantRange* push_constant_ranges = (VkPushConstantRange*)(bindings + + sampler_max_count + uniform_max_count + storage_max_count); VkDescriptorSetLayoutBinding* sampler_binding = sampler_bindings; VkDescriptorSetLayoutBinding* uniform_binding = uniform_bindings; VkDescriptorSetLayoutBinding* storage_binding = storage_bindings; + VkPushConstantRange* push_constant_range = push_constant_ranges; vp_desc = set->vp_desc; while (vp_desc->type != SHADER_DESCRIPTION_NONE && vp_desc->type != SHADER_DESCRIPTION_END @@ -1476,6 +1496,24 @@ static bool shader_update_data(shader_set_data* set, GLenum mode, GLenum type, c } break; case SHADER_DESCRIPTION_UNIFORM: + if (desc->binding == -1) { + push_constant_range_count = (uint32_t)(push_constant_range - push_constant_ranges); + for (uint32_t i = 0; i < push_constant_range_count; i++) + if (push_constant_ranges[i].size == desc->data) { + push_constant_ranges[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + found = true; + break; + } + + if (!found && !push_constant_range_count) { + push_constant_range->stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constant_range->offset = 0; + push_constant_range->size = desc->data; + push_constant_range++; + } + break; + } + uniform_count = (uint32_t)(uniform_binding - uniform_bindings); for (uint32_t i = 0; i < uniform_count; i++) if (uniform_bindings[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER @@ -1543,6 +1581,24 @@ static bool shader_update_data(shader_set_data* set, GLenum mode, GLenum type, c } break; case SHADER_DESCRIPTION_UNIFORM: + if (desc->binding == -1) { + push_constant_range_count = (uint32_t)(push_constant_range - push_constant_ranges); + for (uint32_t i = 0; i < push_constant_range_count; i++) + if (push_constant_ranges[i].size == desc->data) { + push_constant_ranges[i].stageFlags |= VK_SHADER_STAGE_FRAGMENT_BIT; + found = true; + break; + } + + if (!found && !push_constant_range_count) { + push_constant_range->stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + push_constant_range->offset = 0; + push_constant_range->size = desc->data; + push_constant_range++; + } + break; + } + uniform_count = (uint32_t)(uniform_binding - uniform_bindings); for (uint32_t i = 0; i < uniform_count; i++) if (uniform_bindings[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER @@ -1586,6 +1642,7 @@ static bool shader_update_data(shader_set_data* set, GLenum mode, GLenum type, c sampler_count = (uint32_t)(sampler_binding - sampler_bindings); uniform_count = (uint32_t)(uniform_binding - uniform_bindings); storage_count = (uint32_t)(storage_binding - storage_bindings); + push_constant_range_count = (uint32_t)(push_constant_range - push_constant_ranges); if (uniform_count) memmove(bindings + sampler_count, @@ -1595,10 +1652,15 @@ static bool shader_update_data(shader_set_data* set, GLenum mode, GLenum type, c memmove(bindings + sampler_count + uniform_count, bindings + sampler_max_count + uniform_max_count, storage_count * sizeof(VkDescriptorSetLayoutBinding)); + if (push_constant_range_count) + memmove(bindings + sampler_count + uniform_count + storage_count, + bindings + sampler_max_count + uniform_max_count + storage_max_count, + push_constant_range_count * sizeof(VkPushConstantRange)); descriptor_pipeline = Vulkan::manager_get_descriptor_pipeline(vp_desc_hash, fp_desc_hash, unival_hash, - sampler_count, uniform_count, storage_count, bindings); + sampler_count, uniform_count, storage_count, + bindings, push_constant_range_count, push_constant_ranges); free_def(bindings); } @@ -1781,7 +1843,7 @@ static bool shader_update_data(shader_set_data* set, GLenum mode, GLenum type, c free_def(color_blend_attachments); - if (sampler_count + uniform_count + storage_count) { + if (sampler_count + uniform_count + storage_count + push_constant_range_count) { size_t descriptor_infos_size = sizeof(VkDescriptorImageInfo) * sampler_count + sizeof(VkDescriptorBufferInfo) * ((size_t)uniform_count + storage_count) + sizeof(uint32_t) * ((size_t)sampler_count + uniform_count + storage_count); @@ -1805,6 +1867,10 @@ static bool shader_update_data(shader_set_data* set, GLenum mode, GLenum type, c uint32_t* storage_info_bindings = (uint32_t*)(uniform_info_bindings + uniform_count); uint32_t* storage_info_binding = storage_info_bindings; + uint8_t* push_constant_data = 0; + uint32_t push_constant_data_size = 0; + VkShaderStageFlags push_constant_stage_flags = 0; + vp_desc = set->vp_desc; while (vp_desc->type != SHADER_DESCRIPTION_NONE && vp_desc->type != SHADER_DESCRIPTION_END && vp_desc->type != SHADER_DESCRIPTION_MAX) { @@ -1860,6 +1926,19 @@ static bool shader_update_data(shader_set_data* set, GLenum mode, GLenum type, c } break; case SHADER_DESCRIPTION_UNIFORM: + if (desc->binding == -1) { + Vulkan::gl_buffer* vk_buf = Vulkan::gl_buffer::get(gl_state.uniform_buffer_bindings[0]); + if (!vk_buf) + break; + + if (!push_constant_data) { + push_constant_data = vk_buf->data.data(); + push_constant_data_size = (uint32_t)vk_buf->data.size(); + } + push_constant_stage_flags |= VK_SHADER_STAGE_VERTEX_BIT; + break; + } + uniform_count = (uint32_t)(uniform_info - uniform_infos); for (uint32_t i = 0; i < uniform_count; i++) if (uniform_info_bindings[i] == desc->binding) { @@ -1965,6 +2044,19 @@ static bool shader_update_data(shader_set_data* set, GLenum mode, GLenum type, c } break; case SHADER_DESCRIPTION_UNIFORM: + if (desc->binding == -1) { + Vulkan::gl_buffer* vk_buf = Vulkan::gl_buffer::get(gl_state.uniform_buffer_bindings[0]); + if (!vk_buf) + break; + + if (!push_constant_data) { + push_constant_data = vk_buf->data.data(); + push_constant_data_size = (uint32_t)vk_buf->data.size(); + } + push_constant_stage_flags |= VK_SHADER_STAGE_FRAGMENT_BIT; + break; + } + uniform_count = (uint32_t)(uniform_info - uniform_infos); for (uint32_t i = 0; i < uniform_count; i++) if (uniform_info_bindings[i] == desc->binding) { @@ -2108,6 +2200,10 @@ static bool shader_update_data(shader_set_data* set, GLenum mode, GLenum type, c free_def(descriptor_writes); } + if (push_constant_stage_flags && push_constant_data_size) + vkCmdPushConstants(Vulkan::current_command_buffer, pipeline_layout, + push_constant_stage_flags, 0, push_constant_data_size, push_constant_data); + free_def(descriptor_infos); vkCmdBindDescriptorSets(Vulkan::current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, diff --git a/src/CRE/shader_ft.cpp b/src/CRE/shader_ft.cpp index 7d8f88d4..3c03fe5d 100644 --- a/src/CRE/shader_ft.cpp +++ b/src/CRE/shader_ft.cpp @@ -708,7 +708,7 @@ static const int32_t transparency_fpt_unival_max[] = { { SHADER_DESCRIPTION_SAMPLER, 14, 0, U_INVALID, } #define SHADER_DESCRIPTION_COMMON_SCENE \ - { SHADER_DESCRIPTION_UNIFORM, 0, sizeof(obj_shader_shader_data), U_INVALID, }, \ + { SHADER_DESCRIPTION_UNIFORM, -1, sizeof(obj_shader_shader_data), U_INVALID, }, \ { SHADER_DESCRIPTION_UNIFORM, 1, sizeof(obj_scene_shader_data), U_INVALID, }, \ { SHADER_DESCRIPTION_UNIFORM, 2, sizeof(obj_batch_shader_data), U_INVALID, }