mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-11-29 01:24:11 +01:00
[dxvk] Implemented proper resource binding
This commit is contained in:
parent
e433c01ad4
commit
2c3674190a
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
101
src/dxvk/dxvk_descriptor.cpp
Normal file
101
src/dxvk/dxvk_descriptor.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
62
src/dxvk/dxvk_descriptor.h
Normal file
62
src/dxvk/dxvk_descriptor.h
Normal 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;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -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;
|
||||
|
0
src/dxvk/dxvk_sampler.cpp
Normal file
0
src/dxvk/dxvk_sampler.cpp
Normal file
0
src/dxvk/dxvk_sampler.h
Normal file
0
src/dxvk/dxvk_sampler.h
Normal 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',
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user