From 58c5647c775e38dd08a64ad435dfe0673a62fcd1 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 21 Nov 2021 15:26:22 +0200 Subject: [PATCH] Track the in-use state of resource bindings in PipelineState --- source/backends/opengl/pipelinestate_backend.cpp | 4 ++-- source/backends/vulkan/pipelinestate_backend.cpp | 14 ++++++++------ source/core/pipelinestate.cpp | 2 ++ source/core/pipelinestate.h | 2 ++ source/core/program.cpp | 13 +++++++++++++ source/core/program.h | 1 + source/core/reflectdata.h | 1 + 7 files changed, 29 insertions(+), 8 deletions(-) diff --git a/source/backends/opengl/pipelinestate_backend.cpp b/source/backends/opengl/pipelinestate_backend.cpp index 9616b18b..78ba7978 100644 --- a/source/backends/opengl/pipelinestate_backend.cpp +++ b/source/backends/opengl/pipelinestate_backend.cpp @@ -108,7 +108,7 @@ void OpenGLPipelineState::apply() const for(const PipelineState::BoundUniformBlock &u: self.uniform_blocks) if(u.changed || mask==~0U) { - if(u.block) + if(u.used) { if(u.binding>=0) { @@ -132,7 +132,7 @@ void OpenGLPipelineState::apply() const for(const PipelineState::BoundTexture &t: self.textures) if(t.changed || mask==~0U) { - if(t.texture && t.sampler) + if(t.used) { if(ARB_direct_state_access) glBindTextureUnit(t.binding, t.texture->id); diff --git a/source/backends/vulkan/pipelinestate_backend.cpp b/source/backends/vulkan/pipelinestate_backend.cpp index 32672ec4..4a47b223 100644 --- a/source/backends/vulkan/pipelinestate_backend.cpp +++ b/source/backends/vulkan/pipelinestate_backend.cpp @@ -44,9 +44,11 @@ void VulkanPipelineState::update() const { unsigned changed_sets = (self.changes&PipelineState::SHPROG ? ~0U : 0U); for(const PipelineState::BoundUniformBlock &u: self.uniform_blocks) - if(u.changed && u.binding>=0) + if(u.changed || changed_sets==~0U) { - changed_sets |= 1<<(u.binding>>20); + u.used = self.shprog->uses_binding(u.binding); + if(u.binding>=0) + changed_sets |= 1<<(u.binding>>20); u.changed = false; } @@ -258,7 +260,7 @@ uint64_t VulkanPipelineState::compute_descriptor_set_hash(unsigned index) const uint64_t result = hash<64>(0, 0); for(const PipelineState::BoundUniformBlock &b: self.uniform_blocks) - if(b.block && b.binding>=0 && static_cast(b.binding>>20)==index) + if(b.used && b.binding>=0 && static_cast(b.binding>>20)==index) { result = hash_update<64>(result, b.binding); result = hash_update<64>(result, reinterpret_cast(b.block)); @@ -278,7 +280,7 @@ unsigned VulkanPipelineState::fill_descriptor_writes(unsigned index, vector=0 && static_cast(u.binding>>20)==index) + if(u.used && u.binding>=0 && static_cast(u.binding>>20)==index) ++n_buffers; StructureBuilder sb(buffer, 2); @@ -289,7 +291,7 @@ unsigned VulkanPipelineState::fill_descriptor_writes(unsigned index, vector=0 && static_cast(u.binding>>20)==index) + if(u.used && u.binding>=0 && static_cast(u.binding>>20)==index) { buffer_ptr->buffer = handle_cast<::VkBuffer>(u.block->get_buffer()->handle); buffer_ptr->offset = u.block->get_offset(); @@ -324,7 +326,7 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer) const if(!self.uniform_blocks.empty()) { const PipelineState::BoundUniformBlock &first_block = self.uniform_blocks.front(); - if(first_block.block && first_block.binding==ReflectData::PUSH_CONSTANT && first_block.changed) + if(first_block.used && first_block.binding==ReflectData::PUSH_CONSTANT && first_block.changed) { const UniformBlock &pc_block = *first_block.block; vk.CmdPushConstants(command_buffer, self.shprog->layout_handle, VK_SHADER_STAGE_ALL, diff --git a/source/core/pipelinestate.cpp b/source/core/pipelinestate.cpp index bc13d3ba..076eb333 100644 --- a/source/core/pipelinestate.cpp +++ b/source/core/pipelinestate.cpp @@ -42,6 +42,7 @@ void PipelineState::set_uniform_block(int binding, const UniformBlock *block) auto i = lower_bound_member(uniform_blocks, binding, &BoundUniformBlock::binding); if(i==uniform_blocks.end() || i->binding!=binding) i = uniform_blocks.insert(i, BoundUniformBlock(binding)); + i->used = block; if(block!=i->block || binding<0) { i->block = block; @@ -58,6 +59,7 @@ void PipelineState::set_texture(unsigned binding, const Texture *tex, const Samp auto i = lower_bound_member(textures, binding, &BoundTexture::binding); if(i==textures.end() || i->binding!=binding) i = textures.insert(i, BoundTexture(binding)); + i->used = (tex && samp); if(tex!=i->texture || samp!=i->sampler) { i->texture = tex; diff --git a/source/core/pipelinestate.h b/source/core/pipelinestate.h index 105003d1..89cf1cd7 100644 --- a/source/core/pipelinestate.h +++ b/source/core/pipelinestate.h @@ -35,6 +35,7 @@ private: { unsigned binding = 0; mutable bool changed = false; + mutable bool used = false; const Texture *texture = 0; const Sampler *sampler = 0; @@ -45,6 +46,7 @@ private: { int binding = 0; mutable bool changed = false; + mutable bool used = false; const UniformBlock *block = 0; BoundUniformBlock(int b): binding(b) { } diff --git a/source/core/program.cpp b/source/core/program.cpp index 471803c5..533dca61 100644 --- a/source/core/program.cpp +++ b/source/core/program.cpp @@ -63,6 +63,13 @@ void Program::add_stages(const Module &mod, const map &spec_values) finalize_uniforms(); + for(const ReflectData::UniformInfo &u: reflect_data.uniforms) + if(u.binding>=0) + reflect_data.used_bindings.push_back(u.binding); + for(const ReflectData::UniformBlockInfo &b: reflect_data.uniform_blocks) + reflect_data.used_bindings.push_back(b.bind_point); + sort(reflect_data.used_bindings); + for(const ReflectData::UniformInfo &u: reflect_data.uniforms) require_type(u.type); for(const ReflectData::AttributeInfo &a: reflect_data.attributes) @@ -252,6 +259,12 @@ int Program::get_uniform_binding(Tag tag) const return i!=reflect_data.uniforms.end() && i->tag==tag ? i->binding : -1; } +bool Program::uses_binding(int binding) const +{ + auto i = lower_bound(reflect_data.used_bindings, binding); + return i!=reflect_data.used_bindings.end() && *i==binding; +} + const ReflectData::AttributeInfo &Program::get_attribute_info(const string &name) const { auto i = lower_bound_member(reflect_data.attributes, name, &ReflectData::AttributeInfo::name); diff --git a/source/core/program.h b/source/core/program.h index b6b639bf..9d5b8b2b 100644 --- a/source/core/program.h +++ b/source/core/program.h @@ -82,6 +82,7 @@ public: int get_uniform_location(const std::string &) const; int get_uniform_location(Tag) const; int get_uniform_binding(Tag) const; + bool uses_binding(int) const; const std::vector &get_attributes() const { return reflect_data.attributes; } const ReflectData::AttributeInfo &get_attribute_info(const std::string &) const; int get_attribute_location(const std::string &) const; diff --git a/source/core/reflectdata.h b/source/core/reflectdata.h index a89e7fcf..cc360d04 100644 --- a/source/core/reflectdata.h +++ b/source/core/reflectdata.h @@ -66,6 +66,7 @@ struct ReflectData std::vector attributes; unsigned n_clip_distances = 0; unsigned n_descriptor_sets = 0; + std::vector used_bindings; void update_layout_hash(); }; -- 2.43.0