X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbackends%2Fvulkan%2Fpipelinestate_backend.cpp;h=65c98b94ffe69c485980c91f1528529bb5797ff5;hb=3122f36e64694f5e3f536fa1cca57bf5a3db5c2f;hp=aa44ba08569a463f4ae1fa1ae629c484732a8602;hpb=f201f2e73eb400b4d61ee8729ce8d392ee98a4fb;p=libs%2Fgl.git diff --git a/source/backends/vulkan/pipelinestate_backend.cpp b/source/backends/vulkan/pipelinestate_backend.cpp index aa44ba08..65c98b94 100644 --- a/source/backends/vulkan/pipelinestate_backend.cpp +++ b/source/backends/vulkan/pipelinestate_backend.cpp @@ -35,20 +35,36 @@ void VulkanPipelineState::update() const { const PipelineState &self = *static_cast(this); + if(self.changes&PipelineState::VERTEX_SETUP) + self.vertex_setup->refresh(); + constexpr unsigned pipeline_mask = PipelineState::SHPROG|PipelineState::VERTEX_SETUP|PipelineState::FACE_CULL| PipelineState::DEPTH_TEST|PipelineState::STENCIL_TEST|PipelineState::BLEND|PipelineState::PRIMITIVE_TYPE; if(self.changes&pipeline_mask) handle = device.get_pipeline_cache().get_pipeline(self); - if(self.changes&(PipelineState::UNIFORMS|PipelineState::TEXTURES)) + if(self.changes&(PipelineState::SHPROG|PipelineState::UNIFORMS|PipelineState::TEXTURES)) { - unsigned changed_sets = 0; + 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_uniform_block_binding(u.binding); + if(u.binding>=0) + changed_sets |= 1<<(u.binding>>20); u.changed = false; } + for(const PipelineState::BoundTexture &t: self.textures) + if(t.changed || changed_sets==~0U) + { + t.used = self.shprog->uses_texture_binding(t.binding); + changed_sets |= 1<<(t.binding>>20); + if(t.texture && t.level>=0) + t.texture->refresh_mip_views(); + if(t.sampler) + t.sampler->refresh(); + t.changed = false; + } descriptor_set_handles.resize(self.shprog->get_n_descriptor_sets()); for(unsigned i=0; i &buffer) const } if(self.vertex_setup) - { - self.vertex_setup->refresh(); pipeline_info->pVertexInputState = reinterpret_cast(self.vertex_setup->creation_info.data()); - } } uint64_t VulkanPipelineState::compute_descriptor_set_hash(unsigned index) const @@ -258,10 +271,19 @@ 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)); + result = hash_update<64>(result, reinterpret_cast(b.buffer->handle)); + } + for(const PipelineState::BoundTexture &t: self.textures) + if(t.used && (t.binding>>20)==index) + { + result = hash_update<64>(result, t.binding); + result = hash_update<64>(result, reinterpret_cast(t.texture->handle)); + result = hash_update<64>(result, reinterpret_cast(t.sampler->handle)); + result = hash_update<64>(result, t.level); } return result; @@ -278,37 +300,64 @@ 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); - VkWriteDescriptorSet *&writes = sb.add(n_buffers); + unsigned n_images = 0; + for(const PipelineState::BoundTexture &t: self.textures) + if(t.used && (t.binding>>20)==index) + ++n_images; + unsigned n_writes = n_buffers+n_images; + + StructureBuilder sb(buffer, 3); + VkWriteDescriptorSet *&writes = sb.add(n_writes); VkDescriptorBufferInfo *&buffers = sb.add(n_buffers); + VkDescriptorImageInfo *&images = sb.add(n_images); VkWriteDescriptorSet *write_ptr = writes; VkDescriptorBufferInfo *buffer_ptr = buffers; + VkDescriptorImageInfo *image_ptr = images; for(const PipelineState::BoundUniformBlock &u: self.uniform_blocks) - if(u.block && u.binding>=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->buffer = handle_cast<::VkBuffer>(u.buffer->handle); buffer_ptr->offset = u.block->get_offset(); buffer_ptr->range = u.block->get_data_size(); write_ptr->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write_ptr->dstBinding = u.binding&0xFFFFF; write_ptr->descriptorCount = 1; - write_ptr->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + write_ptr->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; write_ptr->pBufferInfo = buffer_ptr; ++buffer_ptr; ++write_ptr; } - return n_buffers; + for(const PipelineState::BoundTexture &t: self.textures) + if(t.used && (t.binding>>20)==index) + { + image_ptr->sampler = handle_cast<::VkSampler>(t.sampler->handle); + if(t.level<0) + image_ptr->imageView = handle_cast<::VkImageView>(t.texture->view_handle); + else + image_ptr->imageView = handle_cast<::VkImageView>(t.texture->mip_view_handles[t.level]); + image_ptr->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + write_ptr->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_ptr->dstBinding = t.binding&0xFFFFF; + write_ptr->descriptorCount = 1; + write_ptr->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write_ptr->pImageInfo = image_ptr; + + ++image_ptr; + ++write_ptr; + } + + return n_writes; } -void VulkanPipelineState::apply(VkCommandBuffer command_buffer) const +void VulkanPipelineState::apply(VkCommandBuffer command_buffer, unsigned frame, bool negative_viewport) const { const PipelineState &self = *static_cast(this); const VulkanFunctions &vk = device.get_functions(); @@ -324,21 +373,36 @@ 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) { const UniformBlock &pc_block = *first_block.block; - vk.CmdPushConstants(command_buffer, self.shprog->layout_handle, VK_SHADER_STAGE_ALL, + vk.CmdPushConstants(command_buffer, self.shprog->layout_handle, self.shprog->stage_flags, pc_block.get_offset(), pc_block.get_data_size(), pc_block.get_data_pointer()); } } - vk.CmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, self.shprog->layout_handle, 0, descriptor_set_handles.size(), descriptor_set_handles.data(), 0, 0); + if(!descriptor_set_handles.empty()) + { + vector dynamic_offsets; + dynamic_offsets.reserve(self.uniform_blocks.size()); + for(const PipelineState::BoundUniformBlock &u: self.uniform_blocks) + if(u.used && u.binding>=0) + { + if(u.buffer->get_usage()==STREAMING) + dynamic_offsets.push_back(frame*u.buffer->get_size()); + else + dynamic_offsets.push_back(0); + } + + vk.CmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, self.shprog->layout_handle, + 0, descriptor_set_handles.size(), descriptor_set_handles.data(), dynamic_offsets.size(), dynamic_offsets.data()); + } VkViewport viewport = { }; if(self.viewport) { viewport.x = self.viewport->left; - viewport.y = self.framebuffer->get_height()-(self.viewport->bottom+self.viewport->height); + viewport.y = self.viewport->bottom; viewport.width = self.viewport->width; viewport.height = self.viewport->height; } @@ -349,6 +413,11 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer) const viewport.width = self.framebuffer->get_width(); viewport.height = self.framebuffer->get_height(); } + if(negative_viewport) + { + viewport.y += viewport.height; + viewport.height = -viewport.height; + } viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; vk.CmdSetViewport(command_buffer, 0, 1, &viewport); @@ -357,7 +426,7 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer) const if(self.scissor) { scissor.offset.x = self.scissor->left; - scissor.offset.y = self.framebuffer->get_height()-(self.scissor->bottom+self.scissor->height); + scissor.offset.y = self.scissor->bottom; scissor.extent.width = self.scissor->width; scissor.extent.height = self.scissor->height; }