mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-14 22:29:15 +01:00
[dxvk] Implementing unbound resource handling (2/4)
Refactored pipeline binding and descriptor set updates so that no descriptor info gets written for unbound resources.
This commit is contained in:
parent
c64103c73f
commit
b22d56ac06
@ -94,33 +94,36 @@ namespace dxvk {
|
|||||||
VkDescriptorSetLayout descriptorLayout,
|
VkDescriptorSetLayout descriptorLayout,
|
||||||
uint32_t descriptorCount,
|
uint32_t descriptorCount,
|
||||||
const DxvkDescriptorSlot* descriptorSlots,
|
const DxvkDescriptorSlot* descriptorSlots,
|
||||||
const DxvkDescriptorInfo* descriptorInfos) {
|
const DxvkDescriptorInfo* descriptorInfos,
|
||||||
|
const DxvkBindingState& bindingState) {
|
||||||
|
|
||||||
// Allocate a new descriptor set
|
// Allocate a new descriptor set
|
||||||
VkDescriptorSet dset = m_descAlloc.alloc(descriptorLayout);
|
VkDescriptorSet dset = m_descAlloc.alloc(descriptorLayout);
|
||||||
|
|
||||||
// Write data to the descriptor set
|
// Write data to the descriptor set
|
||||||
std::array<VkWriteDescriptorSet, MaxNumResourceSlots> descriptorWrites;
|
std::array<VkWriteDescriptorSet, MaxNumResourceSlots> descriptorWrites;
|
||||||
|
uint32_t writeId = 0;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < descriptorCount; i++) {
|
for (uint32_t i = 0; i < descriptorCount; i++) {
|
||||||
auto& curr = descriptorWrites[i];
|
if (bindingState.isBound(i)) {
|
||||||
auto& binding = descriptorSlots[i];
|
auto& curr = descriptorWrites[writeId++];
|
||||||
|
auto& binding = descriptorSlots[i];
|
||||||
curr.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
||||||
curr.pNext = nullptr;
|
curr.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
curr.dstSet = dset;
|
curr.pNext = nullptr;
|
||||||
curr.dstBinding = i;
|
curr.dstSet = dset;
|
||||||
curr.dstArrayElement = 0;
|
curr.dstBinding = i;
|
||||||
curr.descriptorCount = 1;
|
curr.dstArrayElement = 0;
|
||||||
curr.descriptorType = binding.type;
|
curr.descriptorCount = 1;
|
||||||
curr.pImageInfo = &descriptorInfos[i].image;
|
curr.descriptorType = binding.type;
|
||||||
curr.pBufferInfo = &descriptorInfos[i].buffer;
|
curr.pImageInfo = &descriptorInfos[i].image;
|
||||||
curr.pTexelBufferView = &descriptorInfos[i].texelBuffer;
|
curr.pBufferInfo = &descriptorInfos[i].buffer;
|
||||||
|
curr.pTexelBufferView = &descriptorInfos[i].texelBuffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vkd->vkUpdateDescriptorSets(
|
m_vkd->vkUpdateDescriptorSets(
|
||||||
m_vkd->device(),
|
m_vkd->device(), writeId,
|
||||||
descriptorCount,
|
|
||||||
descriptorWrites.data(),
|
descriptorWrites.data(),
|
||||||
0, nullptr);
|
0, nullptr);
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include "dxvk_binding.h"
|
||||||
#include "dxvk_descriptor.h"
|
#include "dxvk_descriptor.h"
|
||||||
#include "dxvk_lifetime.h"
|
#include "dxvk_lifetime.h"
|
||||||
#include "dxvk_limits.h"
|
#include "dxvk_limits.h"
|
||||||
@ -87,7 +88,8 @@ namespace dxvk {
|
|||||||
VkDescriptorSetLayout descriptorLayout,
|
VkDescriptorSetLayout descriptorLayout,
|
||||||
uint32_t descriptorCount,
|
uint32_t descriptorCount,
|
||||||
const DxvkDescriptorSlot* descriptorSlots,
|
const DxvkDescriptorSlot* descriptorSlots,
|
||||||
const DxvkDescriptorInfo* descriptorInfos);
|
const DxvkDescriptorInfo* descriptorInfos,
|
||||||
|
const DxvkBindingState& bindingState);
|
||||||
|
|
||||||
void cmdBeginRenderPass(
|
void cmdBeginRenderPass(
|
||||||
const VkRenderPassBeginInfo* pRenderPassBegin,
|
const VkRenderPassBeginInfo* pRenderPassBegin,
|
||||||
|
@ -142,10 +142,12 @@ namespace dxvk {
|
|||||||
if (stage == VK_SHADER_STAGE_COMPUTE_BIT) {
|
if (stage == VK_SHADER_STAGE_COMPUTE_BIT) {
|
||||||
m_flags.set(
|
m_flags.set(
|
||||||
DxvkContextFlag::CpDirtyPipeline,
|
DxvkContextFlag::CpDirtyPipeline,
|
||||||
|
DxvkContextFlag::CpDirtyPipelineState,
|
||||||
DxvkContextFlag::CpDirtyResources);
|
DxvkContextFlag::CpDirtyResources);
|
||||||
} else {
|
} else {
|
||||||
m_flags.set(
|
m_flags.set(
|
||||||
DxvkContextFlag::GpDirtyPipeline,
|
DxvkContextFlag::GpDirtyPipeline,
|
||||||
|
DxvkContextFlag::GpDirtyPipelineState,
|
||||||
DxvkContextFlag::GpDirtyResources);
|
DxvkContextFlag::GpDirtyResources);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -920,17 +922,22 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void DxvkContext::updateGraphicsPipeline() {
|
void DxvkContext::updateGraphicsPipeline() {
|
||||||
if (m_flags.any(DxvkContextFlag::GpDirtyPipeline, DxvkContextFlag::GpDirtyPipelineState)) {
|
if (m_flags.test(DxvkContextFlag::GpDirtyPipeline)) {
|
||||||
m_flags.clr(DxvkContextFlag::GpDirtyPipelineState);
|
m_flags.clr(DxvkContextFlag::GpDirtyPipeline);
|
||||||
|
|
||||||
if (m_flags.test(DxvkContextFlag::GpDirtyPipeline)) {
|
m_state.gp.bs.clear();
|
||||||
m_flags.clr(DxvkContextFlag::GpDirtyPipeline);
|
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.bs.clear();
|
m_state.gp.gs.shader, m_state.gp.fs.shader);
|
||||||
m_state.gp.pipeline = m_device->createGraphicsPipeline(
|
|
||||||
m_state.gp.vs.shader, m_state.gp.tcs.shader, m_state.gp.tes.shader,
|
m_cmd->trackResource(m_state.gp.pipeline);
|
||||||
m_state.gp.gs.shader, m_state.gp.fs.shader);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::updateGraphicsPipelineState() {
|
||||||
|
if (m_flags.test(DxvkContextFlag::GpDirtyPipelineState)) {
|
||||||
|
m_flags.clr(DxvkContextFlag::GpDirtyPipelineState);
|
||||||
|
|
||||||
DxvkGraphicsPipelineStateInfo gpState;
|
DxvkGraphicsPipelineStateInfo gpState;
|
||||||
gpState.bsBindingState = m_state.gp.bs;
|
gpState.bsBindingState = m_state.gp.bs;
|
||||||
@ -1005,15 +1012,12 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
m_state.gp.pipeline->getPipelineHandle(gpState));
|
m_state.gp.pipeline->getPipelineHandle(gpState));
|
||||||
m_cmd->trackResource(m_state.gp.pipeline);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::updateComputeShaderResources() {
|
void DxvkContext::updateComputeShaderResources() {
|
||||||
if (m_flags.test(DxvkContextFlag::CpDirtyResources)) {
|
if (m_flags.test(DxvkContextFlag::CpDirtyResources)) {
|
||||||
m_flags.clr(DxvkContextFlag::CpDirtyResources);
|
|
||||||
|
|
||||||
this->updateShaderResources(
|
this->updateShaderResources(
|
||||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||||
m_state.cp.pipeline->layout());
|
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() {
|
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)) {
|
if (m_flags.test(DxvkContextFlag::GpDirtyResources)) {
|
||||||
m_flags.clr(DxvkContextFlag::GpDirtyResources);
|
m_flags.clr(DxvkContextFlag::GpDirtyResources);
|
||||||
|
|
||||||
this->updateShaderResources(
|
this->updateShaderDescriptors(
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
m_state.gp.bs,
|
||||||
m_state.gp.pipeline->layout());
|
m_state.gp.pipeline->layout());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1059,7 +1085,6 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_cmd->trackResource(res.sampler);
|
m_cmd->trackResource(res.sampler);
|
||||||
} else {
|
} else {
|
||||||
Logger::err("DxvkContext: Unbound sampler descriptor");
|
|
||||||
updatePipelineState |= bs.setUnbound(i);
|
updatePipelineState |= bs.setUnbound(i);
|
||||||
|
|
||||||
m_descriptors[i].image.sampler = VK_NULL_HANDLE;
|
m_descriptors[i].image.sampler = VK_NULL_HANDLE;
|
||||||
@ -1069,7 +1094,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||||
case VK_DESCRIPTOR_TYPE_STORAGE_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);
|
updatePipelineState |= bs.setBound(i);
|
||||||
|
|
||||||
m_descriptors[i].image.sampler = VK_NULL_HANDLE;
|
m_descriptors[i].image.sampler = VK_NULL_HANDLE;
|
||||||
@ -1079,7 +1104,6 @@ namespace dxvk {
|
|||||||
m_cmd->trackResource(res.imageView);
|
m_cmd->trackResource(res.imageView);
|
||||||
m_cmd->trackResource(res.imageView->image());
|
m_cmd->trackResource(res.imageView->image());
|
||||||
} else {
|
} else {
|
||||||
Logger::err("DxvkContext: Unbound or incompatible image descriptor");
|
|
||||||
updatePipelineState |= bs.setUnbound(i);
|
updatePipelineState |= bs.setUnbound(i);
|
||||||
|
|
||||||
m_descriptors[i].image.sampler = VK_NULL_HANDLE;
|
m_descriptors[i].image.sampler = VK_NULL_HANDLE;
|
||||||
@ -1097,7 +1121,6 @@ namespace dxvk {
|
|||||||
m_cmd->trackResource(res.bufferView);
|
m_cmd->trackResource(res.bufferView);
|
||||||
m_cmd->trackResource(res.bufferView->buffer()->resource());
|
m_cmd->trackResource(res.bufferView->buffer()->resource());
|
||||||
} else {
|
} else {
|
||||||
Logger::err("DxvkContext: Unbound texel buffer");
|
|
||||||
updatePipelineState |= bs.setUnbound(i);
|
updatePipelineState |= bs.setUnbound(i);
|
||||||
|
|
||||||
m_descriptors[i].texelBuffer = VK_NULL_HANDLE;
|
m_descriptors[i].texelBuffer = VK_NULL_HANDLE;
|
||||||
@ -1111,7 +1134,6 @@ namespace dxvk {
|
|||||||
m_descriptors[i].buffer = res.bufferSlice.descriptorInfo();
|
m_descriptors[i].buffer = res.bufferSlice.descriptorInfo();
|
||||||
m_cmd->trackResource(res.bufferSlice.resource());
|
m_cmd->trackResource(res.bufferSlice.resource());
|
||||||
} else {
|
} else {
|
||||||
Logger::err("DxvkContext: Unbound buffer");
|
|
||||||
updatePipelineState |= bs.setUnbound(i);
|
updatePipelineState |= bs.setUnbound(i);
|
||||||
|
|
||||||
m_descriptors[i].buffer.buffer = VK_NULL_HANDLE;
|
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<DxvkBindingLayout>& layout) {
|
||||||
m_cmd->bindResourceDescriptors(
|
m_cmd->bindResourceDescriptors(
|
||||||
bindPoint,
|
bindPoint,
|
||||||
layout->pipelineLayout(),
|
layout->pipelineLayout(),
|
||||||
layout->descriptorSetLayout(),
|
layout->descriptorSetLayout(),
|
||||||
layout->bindingCount(),
|
layout->bindingCount(),
|
||||||
layout->bindings(),
|
layout->bindings(),
|
||||||
m_descriptors.data());
|
m_descriptors.data(),
|
||||||
|
bindingState);
|
||||||
if (updatePipelineState) {
|
|
||||||
m_flags.set(bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
|
|
||||||
? DxvkContextFlag::GpDirtyPipelineState
|
|
||||||
: DxvkContextFlag::CpDirtyPipelineState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1213,6 +1242,7 @@ namespace dxvk {
|
|||||||
this->renderPassEnd();
|
this->renderPassEnd();
|
||||||
this->updateComputePipeline();
|
this->updateComputePipeline();
|
||||||
this->updateComputeShaderResources();
|
this->updateComputeShaderResources();
|
||||||
|
this->updateComputeShaderDescriptors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1223,6 +1253,8 @@ namespace dxvk {
|
|||||||
this->updateIndexBufferBinding();
|
this->updateIndexBufferBinding();
|
||||||
this->updateVertexBufferBindings();
|
this->updateVertexBufferBindings();
|
||||||
this->updateGraphicsShaderResources();
|
this->updateGraphicsShaderResources();
|
||||||
|
this->updateGraphicsPipelineState();
|
||||||
|
this->updateGraphicsShaderDescriptors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -492,15 +492,25 @@ namespace dxvk {
|
|||||||
void renderPassEnd();
|
void renderPassEnd();
|
||||||
|
|
||||||
void updateComputePipeline();
|
void updateComputePipeline();
|
||||||
|
|
||||||
void updateGraphicsPipeline();
|
void updateGraphicsPipeline();
|
||||||
|
void updateGraphicsPipelineState();
|
||||||
|
|
||||||
void updateComputeShaderResources();
|
void updateComputeShaderResources();
|
||||||
|
void updateComputeShaderDescriptors();
|
||||||
|
|
||||||
void updateGraphicsShaderResources();
|
void updateGraphicsShaderResources();
|
||||||
|
void updateGraphicsShaderDescriptors();
|
||||||
|
|
||||||
void updateShaderResources(
|
void updateShaderResources(
|
||||||
VkPipelineBindPoint bindPoint,
|
VkPipelineBindPoint bindPoint,
|
||||||
const Rc<DxvkBindingLayout>& layout);
|
const Rc<DxvkBindingLayout>& layout);
|
||||||
|
|
||||||
|
void updateShaderDescriptors(
|
||||||
|
VkPipelineBindPoint bindPoint,
|
||||||
|
const DxvkBindingState& bindingState,
|
||||||
|
const Rc<DxvkBindingLayout>& layout);
|
||||||
|
|
||||||
void updateDynamicState();
|
void updateDynamicState();
|
||||||
void updateViewports();
|
void updateViewports();
|
||||||
void updateBlendConstants();
|
void updateBlendConstants();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user