[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:
Philip Rebohle 2018-01-10 12:13:46 +01:00
parent c64103c73f
commit b22d56ac06
4 changed files with 90 additions and 43 deletions

View File

@ -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<VkWriteDescriptorSet, MaxNumResourceSlots> 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);

View File

@ -2,6 +2,7 @@
#include <unordered_set>
#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,

View File

@ -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<DxvkBindingLayout>& 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();
}

View File

@ -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<DxvkBindingLayout>& layout);
void updateShaderDescriptors(
VkPipelineBindPoint bindPoint,
const DxvkBindingState& bindingState,
const Rc<DxvkBindingLayout>& layout);
void updateDynamicState();
void updateViewports();
void updateBlendConstants();