diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp index 5018f5ab..50bc387b 100644 --- a/src/dxvk/dxvk_cmdlist.cpp +++ b/src/dxvk/dxvk_cmdlist.cpp @@ -94,33 +94,36 @@ namespace dxvk { VkDescriptorSetLayout descriptorLayout, uint32_t descriptorCount, const DxvkDescriptorSlot* descriptorSlots, - const DxvkDescriptorInfo* descriptorInfos) { + const DxvkDescriptorInfo* descriptorInfos, + const DxvkBindingState& bindingState) { // Allocate a new descriptor set VkDescriptorSet dset = m_descAlloc.alloc(descriptorLayout); // Write data to the descriptor set std::array descriptorWrites; + uint32_t writeId = 0; for (uint32_t i = 0; i < descriptorCount; i++) { - auto& curr = descriptorWrites[i]; - auto& binding = descriptorSlots[i]; - - curr.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - curr.pNext = nullptr; - curr.dstSet = dset; - curr.dstBinding = i; - curr.dstArrayElement = 0; - curr.descriptorCount = 1; - curr.descriptorType = binding.type; - curr.pImageInfo = &descriptorInfos[i].image; - curr.pBufferInfo = &descriptorInfos[i].buffer; - curr.pTexelBufferView = &descriptorInfos[i].texelBuffer; + if (bindingState.isBound(i)) { + auto& curr = descriptorWrites[writeId++]; + auto& binding = descriptorSlots[i]; + + curr.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + curr.pNext = nullptr; + curr.dstSet = dset; + curr.dstBinding = i; + curr.dstArrayElement = 0; + curr.descriptorCount = 1; + curr.descriptorType = binding.type; + curr.pImageInfo = &descriptorInfos[i].image; + curr.pBufferInfo = &descriptorInfos[i].buffer; + curr.pTexelBufferView = &descriptorInfos[i].texelBuffer; + } } m_vkd->vkUpdateDescriptorSets( - m_vkd->device(), - descriptorCount, + m_vkd->device(), writeId, descriptorWrites.data(), 0, nullptr); diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index 390cbb43..4f6611a5 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -2,6 +2,7 @@ #include +#include "dxvk_binding.h" #include "dxvk_descriptor.h" #include "dxvk_lifetime.h" #include "dxvk_limits.h" @@ -87,7 +88,8 @@ namespace dxvk { VkDescriptorSetLayout descriptorLayout, uint32_t descriptorCount, const DxvkDescriptorSlot* descriptorSlots, - const DxvkDescriptorInfo* descriptorInfos); + const DxvkDescriptorInfo* descriptorInfos, + const DxvkBindingState& bindingState); void cmdBeginRenderPass( const VkRenderPassBeginInfo* pRenderPassBegin, diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 75fb83d0..d12489a1 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -142,10 +142,12 @@ namespace dxvk { if (stage == VK_SHADER_STAGE_COMPUTE_BIT) { m_flags.set( DxvkContextFlag::CpDirtyPipeline, + DxvkContextFlag::CpDirtyPipelineState, DxvkContextFlag::CpDirtyResources); } else { m_flags.set( DxvkContextFlag::GpDirtyPipeline, + DxvkContextFlag::GpDirtyPipelineState, DxvkContextFlag::GpDirtyResources); } } @@ -920,17 +922,22 @@ namespace dxvk { void DxvkContext::updateGraphicsPipeline() { - if (m_flags.any(DxvkContextFlag::GpDirtyPipeline, DxvkContextFlag::GpDirtyPipelineState)) { - m_flags.clr(DxvkContextFlag::GpDirtyPipelineState); + if (m_flags.test(DxvkContextFlag::GpDirtyPipeline)) { + m_flags.clr(DxvkContextFlag::GpDirtyPipeline); - if (m_flags.test(DxvkContextFlag::GpDirtyPipeline)) { - m_flags.clr(DxvkContextFlag::GpDirtyPipeline); - - m_state.gp.bs.clear(); - m_state.gp.pipeline = m_device->createGraphicsPipeline( - m_state.gp.vs.shader, m_state.gp.tcs.shader, m_state.gp.tes.shader, - m_state.gp.gs.shader, m_state.gp.fs.shader); - } + m_state.gp.bs.clear(); + m_state.gp.pipeline = m_device->createGraphicsPipeline( + m_state.gp.vs.shader, m_state.gp.tcs.shader, m_state.gp.tes.shader, + m_state.gp.gs.shader, m_state.gp.fs.shader); + + m_cmd->trackResource(m_state.gp.pipeline); + } + } + + + void DxvkContext::updateGraphicsPipelineState() { + if (m_flags.test(DxvkContextFlag::GpDirtyPipelineState)) { + m_flags.clr(DxvkContextFlag::GpDirtyPipelineState); DxvkGraphicsPipelineStateInfo gpState; gpState.bsBindingState = m_state.gp.bs; @@ -1005,15 +1012,12 @@ namespace dxvk { m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, m_state.gp.pipeline->getPipelineHandle(gpState)); - m_cmd->trackResource(m_state.gp.pipeline); } } void DxvkContext::updateComputeShaderResources() { if (m_flags.test(DxvkContextFlag::CpDirtyResources)) { - m_flags.clr(DxvkContextFlag::CpDirtyResources); - this->updateShaderResources( VK_PIPELINE_BIND_POINT_COMPUTE, m_state.cp.pipeline->layout()); @@ -1021,12 +1025,34 @@ namespace dxvk { } + void DxvkContext::updateComputeShaderDescriptors() { + if (m_flags.test(DxvkContextFlag::CpDirtyResources)) { + m_flags.clr(DxvkContextFlag::CpDirtyResources); + + this->updateShaderDescriptors( + VK_PIPELINE_BIND_POINT_COMPUTE, + m_state.cp.bs, + m_state.cp.pipeline->layout()); + } + } + + void DxvkContext::updateGraphicsShaderResources() { + if (m_flags.test(DxvkContextFlag::GpDirtyResources)) { + this->updateShaderResources( + VK_PIPELINE_BIND_POINT_GRAPHICS, + m_state.gp.pipeline->layout()); + } + } + + + void DxvkContext::updateGraphicsShaderDescriptors() { if (m_flags.test(DxvkContextFlag::GpDirtyResources)) { m_flags.clr(DxvkContextFlag::GpDirtyResources); - this->updateShaderResources( + this->updateShaderDescriptors( VK_PIPELINE_BIND_POINT_GRAPHICS, + m_state.gp.bs, m_state.gp.pipeline->layout()); } } @@ -1059,7 +1085,6 @@ namespace dxvk { m_cmd->trackResource(res.sampler); } else { - Logger::err("DxvkContext: Unbound sampler descriptor"); updatePipelineState |= bs.setUnbound(i); m_descriptors[i].image.sampler = VK_NULL_HANDLE; @@ -1069,7 +1094,7 @@ namespace dxvk { case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: - if (res.imageView != nullptr/* && res.imageView->type() != binding.view*/) { + if (res.imageView != nullptr && res.imageView->type() != binding.view) { updatePipelineState |= bs.setBound(i); m_descriptors[i].image.sampler = VK_NULL_HANDLE; @@ -1079,7 +1104,6 @@ namespace dxvk { m_cmd->trackResource(res.imageView); m_cmd->trackResource(res.imageView->image()); } else { - Logger::err("DxvkContext: Unbound or incompatible image descriptor"); updatePipelineState |= bs.setUnbound(i); m_descriptors[i].image.sampler = VK_NULL_HANDLE; @@ -1097,7 +1121,6 @@ namespace dxvk { m_cmd->trackResource(res.bufferView); m_cmd->trackResource(res.bufferView->buffer()->resource()); } else { - Logger::err("DxvkContext: Unbound texel buffer"); updatePipelineState |= bs.setUnbound(i); m_descriptors[i].texelBuffer = VK_NULL_HANDLE; @@ -1111,7 +1134,6 @@ namespace dxvk { m_descriptors[i].buffer = res.bufferSlice.descriptorInfo(); m_cmd->trackResource(res.bufferSlice.resource()); } else { - Logger::err("DxvkContext: Unbound buffer"); updatePipelineState |= bs.setUnbound(i); m_descriptors[i].buffer.buffer = VK_NULL_HANDLE; @@ -1124,19 +1146,26 @@ namespace dxvk { } } + if (updatePipelineState) { + m_flags.set(bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS + ? DxvkContextFlag::GpDirtyPipelineState + : DxvkContextFlag::CpDirtyPipelineState); + } + } + + + void DxvkContext::updateShaderDescriptors( + VkPipelineBindPoint bindPoint, + const DxvkBindingState& bindingState, + const Rc& layout) { m_cmd->bindResourceDescriptors( bindPoint, layout->pipelineLayout(), layout->descriptorSetLayout(), layout->bindingCount(), layout->bindings(), - m_descriptors.data()); - - if (updatePipelineState) { - m_flags.set(bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS - ? DxvkContextFlag::GpDirtyPipelineState - : DxvkContextFlag::CpDirtyPipelineState); - } + m_descriptors.data(), + bindingState); } @@ -1213,6 +1242,7 @@ namespace dxvk { this->renderPassEnd(); this->updateComputePipeline(); this->updateComputeShaderResources(); + this->updateComputeShaderDescriptors(); } @@ -1223,6 +1253,8 @@ namespace dxvk { this->updateIndexBufferBinding(); this->updateVertexBufferBindings(); this->updateGraphicsShaderResources(); + this->updateGraphicsPipelineState(); + this->updateGraphicsShaderDescriptors(); } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index ba903b41..fbb2a143 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -492,15 +492,25 @@ namespace dxvk { void renderPassEnd(); void updateComputePipeline(); + void updateGraphicsPipeline(); + void updateGraphicsPipelineState(); void updateComputeShaderResources(); + void updateComputeShaderDescriptors(); + void updateGraphicsShaderResources(); + void updateGraphicsShaderDescriptors(); void updateShaderResources( VkPipelineBindPoint bindPoint, const Rc& layout); + void updateShaderDescriptors( + VkPipelineBindPoint bindPoint, + const DxvkBindingState& bindingState, + const Rc& layout); + void updateDynamicState(); void updateViewports(); void updateBlendConstants();