[dxvk] Implemented proper resource binding

This commit is contained in:
Philip Rebohle 2017-10-15 19:23:10 +02:00
parent e433c01ad4
commit 2c3674190a
13 changed files with 296 additions and 4 deletions

View File

@ -27,6 +27,10 @@ namespace dxvk {
m_vkd->vkGetBufferMemoryRequirements(
m_vkd->device(), m_buffer, &memReq);
m_memory = memAlloc.alloc(memReq, memFlags);
if (m_vkd->vkBindBufferMemory(m_vkd->device(),
m_buffer, m_memory.memory(), m_memory.offset()) != VK_SUCCESS)
throw DxvkError("DxvkBuffer::DxvkBuffer: Failed to bind device memory");
}

View File

@ -5,7 +5,7 @@ namespace dxvk {
DxvkCommandList::DxvkCommandList(
const Rc<vk::DeviceFn>& vkd,
uint32_t queueFamily)
: m_vkd(vkd) {
: m_vkd(vkd), m_descAlloc(vkd) {
TRACE(this, queueFamily);
VkCommandPoolCreateInfo poolInfo;
@ -71,10 +71,46 @@ namespace dxvk {
void DxvkCommandList::reset() {
TRACE(this);
m_descAlloc.reset();
m_resources.reset();
}
void DxvkCommandList::bindShaderResources(
VkPipelineBindPoint pipeline,
VkPipelineLayout pipelineLayout,
VkDescriptorSetLayout descriptorLayout,
uint32_t bindingCount,
const DxvkResourceBinding* bindings) {
VkDescriptorSet dset = m_descAlloc.alloc(descriptorLayout);
if (bindingCount > m_descriptorSetWrites.size())
m_descriptorSetWrites.resize(bindingCount);
for (uint32_t i = 0; i < bindingCount; i++) {
VkWriteDescriptorSet& info = m_descriptorSetWrites.at(i);
info.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
info.pNext = nullptr;
info.dstSet = dset;
info.dstBinding = i;
info.dstArrayElement = 0;
info.descriptorCount = 1;
info.descriptorType = bindings[i].type;
info.pImageInfo = &bindings[i].image;
info.pBufferInfo = &bindings[i].buffer;
info.pTexelBufferView = nullptr;
}
m_vkd->vkUpdateDescriptorSets(m_vkd->device(),
bindingCount, m_descriptorSetWrites.data(), 0, nullptr);
m_vkd->vkCmdBindDescriptorSets(m_buffer,
pipeline, pipelineLayout, 0, 1, &dset, 0, nullptr);
}
void DxvkCommandList::cmdBeginRenderPass(
const VkRenderPassBeginInfo* pRenderPassBegin,
VkSubpassContents contents) {

View File

@ -2,6 +2,7 @@
#include <unordered_set>
#include "dxvk_descriptor.h"
#include "dxvk_lifetime.h"
#include "dxvk_recorder.h"
@ -70,6 +71,13 @@ namespace dxvk {
*/
void reset() final;
void bindShaderResources(
VkPipelineBindPoint pipeline,
VkPipelineLayout pipelineLayout,
VkDescriptorSetLayout descriptorLayout,
uint32_t bindingCount,
const DxvkResourceBinding* bindings) final;
void cmdBeginRenderPass(
const VkRenderPassBeginInfo* pRenderPassBegin,
VkSubpassContents contents) final;
@ -123,6 +131,9 @@ namespace dxvk {
VkCommandBuffer m_buffer;
DxvkLifetimeTracker m_resources;
DxvkDescriptorAlloc m_descAlloc;
std::vector<VkWriteDescriptorSet> m_descriptorSetWrites;
};

View File

@ -33,6 +33,17 @@ namespace dxvk {
return m_descriptorSetLayout;
}
/**
* \brief Pipeline layout layout
*
* The pipeline layout for this pipeline.
* Use this to bind descriptor sets.
* \returns The descriptor set layout
*/
VkPipelineLayout pipelineLayout() const {
return m_pipelineLayout;
}
/**
* \brief Pipeline handle
* \returns Pipeline handle

View File

@ -127,6 +127,8 @@ namespace dxvk {
m_cmd->cmdDispatch(
wgCountX, wgCountY, wgCountZ);
// TODO resource barriers
}
@ -173,6 +175,18 @@ namespace dxvk {
}
}
if (m_state.c.flags.test(DxvkComputePipelineBit::DirtyResources)
&& m_state.c.pipeline != nullptr) {
std::vector<DxvkResourceBinding> bindings;
this->addResourceBindingInfo(bindings, m_state.c.cs);
m_cmd->bindShaderResources(
VK_PIPELINE_BIND_POINT_COMPUTE,
m_state.c.pipeline->pipelineLayout(),
m_state.c.pipeline->descriptorSetLayout(),
bindings.size(), bindings.data());
}
m_state.c.flags.clr(
DxvkComputePipelineBit::PipelineDirty,
DxvkComputePipelineBit::DirtyResources);
@ -259,4 +273,44 @@ namespace dxvk {
}
}
uint32_t DxvkContext::addResourceBindingInfo(
std::vector<DxvkResourceBinding>& bindings,
const DxvkShaderState& stageInfo) const {
const uint32_t slotCount = stageInfo.shader->slotCount();
for (uint32_t i = 0; i < slotCount; i++) {
DxvkResourceSlot slot = stageInfo.shader->slot(i);
DxvkResourceBinding binding;
switch (slot.type) {
case DxvkResourceType::ImageSampler:
binding.type = VK_DESCRIPTOR_TYPE_SAMPLER;
break;
case DxvkResourceType::SampledImage:
binding.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
break;
case DxvkResourceType::StorageImage:
binding.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
break;
case DxvkResourceType::UniformBuffer:
binding.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
binding.buffer = stageInfo.boundUniformBuffers.at(slot.slot).descriptorInfo();
break;
case DxvkResourceType::StorageBuffer:
binding.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
binding.buffer = stageInfo.boundStorageBuffers.at(slot.slot).descriptorInfo();
break;
}
bindings.push_back(binding);
}
return slotCount;
}
}

View File

@ -165,9 +165,10 @@ namespace dxvk {
DxvkShaderState* getShaderState(
VkShaderStageFlagBits stage);
VkPipelineStageFlags pipelineStage(
VkShaderStageFlags shaderStage) const;
uint32_t addResourceBindingInfo(
std::vector<DxvkResourceBinding>& bindings,
const DxvkShaderState& stageInfo) const;
};

View File

@ -0,0 +1,101 @@
#include "dxvk_descriptor.h"
namespace dxvk {
DxvkDescriptorAlloc::DxvkDescriptorAlloc(
const Rc<vk::DeviceFn>& vkd)
: m_vkd(vkd) {
TRACE(this);
}
DxvkDescriptorAlloc::~DxvkDescriptorAlloc() {
TRACE(this);
for (auto p : m_pools) {
m_vkd->vkDestroyDescriptorPool(
m_vkd->device(), p, nullptr);
}
}
VkDescriptorSet DxvkDescriptorAlloc::alloc(VkDescriptorSetLayout layout) {
TRACE(this, layout);
VkDescriptorSet set = VK_NULL_HANDLE;
if (m_poolId < m_pools.size())
set = this->allocFrom(m_pools.at(m_poolId), layout);
if (set == VK_NULL_HANDLE) {
VkDescriptorPool pool = this->createDescriptorPool();
set = this->allocFrom(pool, layout);
if (set == VK_NULL_HANDLE)
throw DxvkError("DxvkDescriptorAlloc::alloc: Failed to allocate descriptor set");
m_pools.push_back(pool);
m_poolId += 1;
}
return set;
}
void DxvkDescriptorAlloc::reset() {
for (auto p : m_pools) {
m_vkd->vkResetDescriptorPool(
m_vkd->device(), p, 0);
}
m_poolId = 0;
}
VkDescriptorPool DxvkDescriptorAlloc::createDescriptorPool() {
TRACE(this);
// TODO tune these values, if necessary
constexpr uint32_t MaxSets = 256;
constexpr uint32_t MaxDesc = 256;
std::array<VkDescriptorPoolSize, 5> pools = {{
{ VK_DESCRIPTOR_TYPE_SAMPLER, MaxDesc },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MaxDesc },
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, MaxDesc },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, MaxDesc },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, MaxDesc } }};
VkDescriptorPoolCreateInfo info;
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
info.pNext = nullptr;
info.flags = 0;
info.maxSets = MaxSets;
info.poolSizeCount = pools.size();
info.pPoolSizes = pools.data();
VkDescriptorPool pool = VK_NULL_HANDLE;
if (m_vkd->vkCreateDescriptorPool(m_vkd->device(),
&info, nullptr, &pool) != VK_SUCCESS)
throw DxvkError("DxvkDescriptorAlloc::createDescriptorPool: Failed to create descriptor pool");
return pool;
}
VkDescriptorSet DxvkDescriptorAlloc::allocFrom(
VkDescriptorPool pool,
VkDescriptorSetLayout layout) const {
VkDescriptorSetAllocateInfo info;
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
info.pNext = nullptr;
info.descriptorPool = pool;
info.descriptorSetCount = 1;
info.pSetLayouts = &layout;
VkDescriptorSet set = VK_NULL_HANDLE;
if (m_vkd->vkAllocateDescriptorSets(m_vkd->device(), &info, &set) != VK_SUCCESS)
return VK_NULL_HANDLE;
return set;
}
}

View File

@ -0,0 +1,62 @@
#pragma once
#include "dxvk_include.h"
namespace dxvk {
struct DxvkResourceBinding {
VkDescriptorType type;
VkDescriptorImageInfo image;
VkDescriptorBufferInfo buffer;
};
/**
* \brief Descriptor set allocator
*
* Creates descriptor pools on demand and
* allocates descriptor sets from those pools.
*/
class DxvkDescriptorAlloc {
public:
DxvkDescriptorAlloc(
const Rc<vk::DeviceFn>& vkd);
~DxvkDescriptorAlloc();
DxvkDescriptorAlloc (const DxvkDescriptorAlloc&) = delete;
DxvkDescriptorAlloc& operator = (const DxvkDescriptorAlloc&) = delete;
/**
* \brief Allocates a descriptor set
*
* \param [in] layout Descriptor set layout
* \returns The descriptor set
*/
VkDescriptorSet alloc(
VkDescriptorSetLayout layout);
/**
* \brief Resets descriptor set allocator
*
* Destroys all descriptor sets and
* resets the Vulkan descriptor pools.
*/
void reset();
private:
Rc<vk::DeviceFn> m_vkd;
std::vector<VkDescriptorPool> m_pools;
size_t m_poolId = 0;
VkDescriptorPool createDescriptorPool();
VkDescriptorSet allocFrom(
VkDescriptorPool pool,
VkDescriptorSetLayout layout) const;
};
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "dxvk_descriptor.h"
#include "dxvk_lifetime.h"
namespace dxvk {
@ -27,6 +28,13 @@ namespace dxvk {
virtual void reset() = 0;
virtual void bindShaderResources(
VkPipelineBindPoint pipeline,
VkPipelineLayout pipelineLayout,
VkDescriptorSetLayout descriptorLayout,
uint32_t bindingCount,
const DxvkResourceBinding* bindings) = 0;
virtual void cmdBeginRenderPass(
const VkRenderPassBeginInfo* pRenderPassBegin,
VkSubpassContents contents) = 0;

View File

0
src/dxvk/dxvk_sampler.h Normal file
View File

View File

@ -6,6 +6,7 @@ dxvk_src = files([
'dxvk_compute.cpp',
'dxvk_context.cpp',
'dxvk_deferred.cpp',
'dxvk_descriptor.cpp',
'dxvk_device.cpp',
'dxvk_framebuffer.cpp',
'dxvk_graphics.cpp',

View File

@ -105,6 +105,9 @@ public:
m_dxvkCommandList, sync1, sync2);
m_dxvkSwapchain->present(sync2);
m_dxvkDevice->waitForIdle();
std::memcpy(m_testData, m_testBuffer->mapPtr(), sizeof(m_testData));
std::cout << m_testData[0] << std::endl;
}
private: