mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +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->vkGetBufferMemoryRequirements(
|
||||||
m_vkd->device(), m_buffer, &memReq);
|
m_vkd->device(), m_buffer, &memReq);
|
||||||
m_memory = memAlloc.alloc(memReq, memFlags);
|
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(
|
DxvkCommandList::DxvkCommandList(
|
||||||
const Rc<vk::DeviceFn>& vkd,
|
const Rc<vk::DeviceFn>& vkd,
|
||||||
uint32_t queueFamily)
|
uint32_t queueFamily)
|
||||||
: m_vkd(vkd) {
|
: m_vkd(vkd), m_descAlloc(vkd) {
|
||||||
TRACE(this, queueFamily);
|
TRACE(this, queueFamily);
|
||||||
|
|
||||||
VkCommandPoolCreateInfo poolInfo;
|
VkCommandPoolCreateInfo poolInfo;
|
||||||
@ -71,10 +71,46 @@ namespace dxvk {
|
|||||||
|
|
||||||
void DxvkCommandList::reset() {
|
void DxvkCommandList::reset() {
|
||||||
TRACE(this);
|
TRACE(this);
|
||||||
|
|
||||||
|
m_descAlloc.reset();
|
||||||
m_resources.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(
|
void DxvkCommandList::cmdBeginRenderPass(
|
||||||
const VkRenderPassBeginInfo* pRenderPassBegin,
|
const VkRenderPassBeginInfo* pRenderPassBegin,
|
||||||
VkSubpassContents contents) {
|
VkSubpassContents contents) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include "dxvk_descriptor.h"
|
||||||
#include "dxvk_lifetime.h"
|
#include "dxvk_lifetime.h"
|
||||||
#include "dxvk_recorder.h"
|
#include "dxvk_recorder.h"
|
||||||
|
|
||||||
@ -70,6 +71,13 @@ namespace dxvk {
|
|||||||
*/
|
*/
|
||||||
void reset() final;
|
void reset() final;
|
||||||
|
|
||||||
|
void bindShaderResources(
|
||||||
|
VkPipelineBindPoint pipeline,
|
||||||
|
VkPipelineLayout pipelineLayout,
|
||||||
|
VkDescriptorSetLayout descriptorLayout,
|
||||||
|
uint32_t bindingCount,
|
||||||
|
const DxvkResourceBinding* bindings) final;
|
||||||
|
|
||||||
void cmdBeginRenderPass(
|
void cmdBeginRenderPass(
|
||||||
const VkRenderPassBeginInfo* pRenderPassBegin,
|
const VkRenderPassBeginInfo* pRenderPassBegin,
|
||||||
VkSubpassContents contents) final;
|
VkSubpassContents contents) final;
|
||||||
@ -123,6 +131,9 @@ namespace dxvk {
|
|||||||
VkCommandBuffer m_buffer;
|
VkCommandBuffer m_buffer;
|
||||||
|
|
||||||
DxvkLifetimeTracker m_resources;
|
DxvkLifetimeTracker m_resources;
|
||||||
|
DxvkDescriptorAlloc m_descAlloc;
|
||||||
|
|
||||||
|
std::vector<VkWriteDescriptorSet> m_descriptorSetWrites;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,6 +33,17 @@ namespace dxvk {
|
|||||||
return m_descriptorSetLayout;
|
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
|
* \brief Pipeline handle
|
||||||
* \returns Pipeline handle
|
* \returns Pipeline handle
|
||||||
|
@ -127,6 +127,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_cmd->cmdDispatch(
|
m_cmd->cmdDispatch(
|
||||||
wgCountX, wgCountY, wgCountZ);
|
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(
|
m_state.c.flags.clr(
|
||||||
DxvkComputePipelineBit::PipelineDirty,
|
DxvkComputePipelineBit::PipelineDirty,
|
||||||
DxvkComputePipelineBit::DirtyResources);
|
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(
|
DxvkShaderState* getShaderState(
|
||||||
VkShaderStageFlagBits stage);
|
VkShaderStageFlagBits stage);
|
||||||
|
|
||||||
VkPipelineStageFlags pipelineStage(
|
uint32_t addResourceBindingInfo(
|
||||||
VkShaderStageFlags shaderStage) const;
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include "dxvk_descriptor.h"
|
||||||
#include "dxvk_lifetime.h"
|
#include "dxvk_lifetime.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
@ -27,6 +28,13 @@ namespace dxvk {
|
|||||||
|
|
||||||
virtual void reset() = 0;
|
virtual void reset() = 0;
|
||||||
|
|
||||||
|
virtual void bindShaderResources(
|
||||||
|
VkPipelineBindPoint pipeline,
|
||||||
|
VkPipelineLayout pipelineLayout,
|
||||||
|
VkDescriptorSetLayout descriptorLayout,
|
||||||
|
uint32_t bindingCount,
|
||||||
|
const DxvkResourceBinding* bindings) = 0;
|
||||||
|
|
||||||
virtual void cmdBeginRenderPass(
|
virtual void cmdBeginRenderPass(
|
||||||
const VkRenderPassBeginInfo* pRenderPassBegin,
|
const VkRenderPassBeginInfo* pRenderPassBegin,
|
||||||
VkSubpassContents contents) = 0;
|
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_compute.cpp',
|
||||||
'dxvk_context.cpp',
|
'dxvk_context.cpp',
|
||||||
'dxvk_deferred.cpp',
|
'dxvk_deferred.cpp',
|
||||||
|
'dxvk_descriptor.cpp',
|
||||||
'dxvk_device.cpp',
|
'dxvk_device.cpp',
|
||||||
'dxvk_framebuffer.cpp',
|
'dxvk_framebuffer.cpp',
|
||||||
'dxvk_graphics.cpp',
|
'dxvk_graphics.cpp',
|
||||||
|
@ -105,6 +105,9 @@ public:
|
|||||||
m_dxvkCommandList, sync1, sync2);
|
m_dxvkCommandList, sync1, sync2);
|
||||||
m_dxvkSwapchain->present(sync2);
|
m_dxvkSwapchain->present(sync2);
|
||||||
m_dxvkDevice->waitForIdle();
|
m_dxvkDevice->waitForIdle();
|
||||||
|
|
||||||
|
std::memcpy(m_testData, m_testBuffer->mapPtr(), sizeof(m_testData));
|
||||||
|
std::cout << m_testData[0] << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user