mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-02 10:24:12 +01:00
[d3d11] Refactor UAV counter buffer allocator
- Fixes violation of the minStorageBufferOffsetAlignment limit - Allows allocation of multiple counter buffers if necessary
This commit is contained in:
parent
212bd56b93
commit
8044ce6c7e
@ -7,6 +7,7 @@
|
|||||||
#include "d3d11_annotation.h"
|
#include "d3d11_annotation.h"
|
||||||
#include "d3d11_context_state.h"
|
#include "d3d11_context_state.h"
|
||||||
#include "d3d11_device_child.h"
|
#include "d3d11_device_child.h"
|
||||||
|
#include "d3d11_uav_counter.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
|
@ -103,14 +103,14 @@ namespace dxvk {
|
|||||||
throw DxvkError("D3D11Device: Failed to query adapter");
|
throw DxvkError("D3D11Device: Failed to query adapter");
|
||||||
|
|
||||||
m_initializer = new D3D11Initializer(m_dxvkDevice);
|
m_initializer = new D3D11Initializer(m_dxvkDevice);
|
||||||
|
m_uavCounters = new D3D11UavCounterAllocator(this);
|
||||||
m_context = new D3D11ImmediateContext(this, m_dxvkDevice);
|
m_context = new D3D11ImmediateContext(this, m_dxvkDevice);
|
||||||
|
|
||||||
CreateCounterBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
D3D11Device::~D3D11Device() {
|
D3D11Device::~D3D11Device() {
|
||||||
delete m_context;
|
delete m_context;
|
||||||
|
delete m_uavCounters;
|
||||||
delete m_initializer;
|
delete m_initializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,7 +555,7 @@ namespace dxvk {
|
|||||||
DxvkBufferSlice counterSlice;
|
DxvkBufferSlice counterSlice;
|
||||||
|
|
||||||
if (desc.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))
|
if (desc.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))
|
||||||
counterSlice = AllocateCounterSlice();
|
counterSlice = AllocCounterSlice();
|
||||||
|
|
||||||
*ppUAView = ref(new D3D11UnorderedAccessView(
|
*ppUAView = ref(new D3D11UnorderedAccessView(
|
||||||
this, pResource, desc,
|
this, pResource, desc,
|
||||||
@ -1727,27 +1727,6 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DxvkBufferSlice D3D11Device::AllocateCounterSlice() {
|
|
||||||
std::lock_guard<std::mutex> lock(m_counterMutex);
|
|
||||||
|
|
||||||
if (m_counterSlices.size() == 0)
|
|
||||||
throw DxvkError("D3D11Device: Failed to allocate counter slice");
|
|
||||||
|
|
||||||
uint32_t sliceId = m_counterSlices.back();
|
|
||||||
m_counterSlices.pop_back();
|
|
||||||
|
|
||||||
return DxvkBufferSlice(m_counterBuffer,
|
|
||||||
sizeof(D3D11UavCounter) * sliceId,
|
|
||||||
sizeof(D3D11UavCounter));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void D3D11Device::FreeCounterSlice(const DxvkBufferSlice& Slice) {
|
|
||||||
std::lock_guard<std::mutex> lock(m_counterMutex);
|
|
||||||
m_counterSlices.push_back(Slice.offset() / sizeof(D3D11UavCounter));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void D3D11Device::FlushInitContext() {
|
void D3D11Device::FlushInitContext() {
|
||||||
m_initializer->Flush();
|
m_initializer->Flush();
|
||||||
}
|
}
|
||||||
@ -2022,32 +2001,6 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D11Device::CreateCounterBuffer() {
|
|
||||||
const uint32_t MaxCounterStructs = 1 << 16;
|
|
||||||
|
|
||||||
// The counter buffer is used as a storage buffer
|
|
||||||
DxvkBufferCreateInfo info;
|
|
||||||
info.size = MaxCounterStructs * sizeof(D3D11UavCounter);
|
|
||||||
info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
|
||||||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
|
||||||
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
|
||||||
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
|
|
||||||
| GetEnabledShaderStages();
|
|
||||||
info.access = VK_ACCESS_TRANSFER_READ_BIT
|
|
||||||
| VK_ACCESS_TRANSFER_WRITE_BIT
|
|
||||||
| VK_ACCESS_SHADER_READ_BIT
|
|
||||||
| VK_ACCESS_SHADER_WRITE_BIT;
|
|
||||||
m_counterBuffer = m_dxvkDevice->createBuffer(
|
|
||||||
info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
||||||
|
|
||||||
// Init the counter struct allocator as well
|
|
||||||
m_counterSlices.resize(MaxCounterStructs);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < MaxCounterStructs; i++)
|
|
||||||
m_counterSlices[i] = MaxCounterStructs - i - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
D3D_FEATURE_LEVEL D3D11Device::GetMaxFeatureLevel() {
|
D3D_FEATURE_LEVEL D3D11Device::GetMaxFeatureLevel() {
|
||||||
static const std::array<std::pair<std::string, D3D_FEATURE_LEVEL>, 7> s_featureLevels = {{
|
static const std::array<std::pair<std::string, D3D_FEATURE_LEVEL>, 7> s_featureLevels = {{
|
||||||
{ "11_1", D3D_FEATURE_LEVEL_11_1 },
|
{ "11_1", D3D_FEATURE_LEVEL_11_1 },
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "d3d11_options.h"
|
#include "d3d11_options.h"
|
||||||
#include "d3d11_shader.h"
|
#include "d3d11_shader.h"
|
||||||
#include "d3d11_state.h"
|
#include "d3d11_state.h"
|
||||||
|
#include "d3d11_uav_counter.h"
|
||||||
#include "d3d11_util.h"
|
#include "d3d11_util.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
@ -316,10 +317,6 @@ namespace dxvk {
|
|||||||
return m_dxvkDevice;
|
return m_dxvkDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
DxvkBufferSlice AllocateCounterSlice();
|
|
||||||
|
|
||||||
void FreeCounterSlice(const DxvkBufferSlice& Slice);
|
|
||||||
|
|
||||||
void FlushInitContext();
|
void FlushInitContext();
|
||||||
|
|
||||||
VkPipelineStageFlags GetEnabledShaderStages() const;
|
VkPipelineStageFlags GetEnabledShaderStages() const;
|
||||||
@ -332,6 +329,14 @@ namespace dxvk {
|
|||||||
DXGI_FORMAT Format,
|
DXGI_FORMAT Format,
|
||||||
DXGI_VK_FORMAT_MODE Mode) const;
|
DXGI_VK_FORMAT_MODE Mode) const;
|
||||||
|
|
||||||
|
DxvkBufferSlice AllocCounterSlice() {
|
||||||
|
return m_uavCounters->AllocSlice();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeCounterSlice(const DxvkBufferSlice& Slice) {
|
||||||
|
m_uavCounters->FreeSlice(Slice);
|
||||||
|
}
|
||||||
|
|
||||||
bool TestOption(D3D11Option Option) const {
|
bool TestOption(D3D11Option Option) const {
|
||||||
return m_d3d11Options.test(Option);
|
return m_d3d11Options.test(Option);
|
||||||
}
|
}
|
||||||
@ -359,12 +364,9 @@ namespace dxvk {
|
|||||||
const DxbcOptions m_dxbcOptions;
|
const DxbcOptions m_dxbcOptions;
|
||||||
|
|
||||||
D3D11Initializer* m_initializer = nullptr;
|
D3D11Initializer* m_initializer = nullptr;
|
||||||
|
D3D11UavCounterAllocator* m_uavCounters = nullptr;
|
||||||
D3D11ImmediateContext* m_context = nullptr;
|
D3D11ImmediateContext* m_context = nullptr;
|
||||||
|
|
||||||
std::mutex m_counterMutex;
|
|
||||||
std::vector<uint32_t> m_counterSlices;
|
|
||||||
Rc<DxvkBuffer> m_counterBuffer;
|
|
||||||
|
|
||||||
D3D11StateObjectSet<D3D11BlendState> m_bsStateObjects;
|
D3D11StateObjectSet<D3D11BlendState> m_bsStateObjects;
|
||||||
D3D11StateObjectSet<D3D11DepthStencilState> m_dsStateObjects;
|
D3D11StateObjectSet<D3D11DepthStencilState> m_dsStateObjects;
|
||||||
D3D11StateObjectSet<D3D11RasterizerState> m_rsStateObjects;
|
D3D11StateObjectSet<D3D11RasterizerState> m_rsStateObjects;
|
||||||
@ -388,8 +390,6 @@ namespace dxvk {
|
|||||||
VkFormat Format,
|
VkFormat Format,
|
||||||
VkImageType Type) const;
|
VkImageType Type) const;
|
||||||
|
|
||||||
void CreateCounterBuffer();
|
|
||||||
|
|
||||||
static D3D_FEATURE_LEVEL GetMaxFeatureLevel();
|
static D3D_FEATURE_LEVEL GetMaxFeatureLevel();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
67
src/d3d11/d3d11_uav_counter.cpp
Normal file
67
src/d3d11/d3d11_uav_counter.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include "d3d11_device.h"
|
||||||
|
#include "d3d11_uav_counter.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
constexpr VkDeviceSize D3D11UavCounterAllocator::SlicesPerBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
D3D11UavCounterAllocator::D3D11UavCounterAllocator(D3D11Device* pDevice)
|
||||||
|
: m_device (pDevice),
|
||||||
|
m_alignment (GetOffsetAlignment()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
D3D11UavCounterAllocator::~D3D11UavCounterAllocator() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkBufferSlice D3D11UavCounterAllocator::AllocSlice() {
|
||||||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
if (m_freeSlices.size() == 0)
|
||||||
|
CreateBuffer(SlicesPerBuffer);
|
||||||
|
|
||||||
|
DxvkBufferSlice slice = m_freeSlices.back();
|
||||||
|
m_freeSlices.pop_back();
|
||||||
|
return slice;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D11UavCounterAllocator::FreeSlice(const DxvkBufferSlice& Slice) {
|
||||||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
m_freeSlices.push_back(Slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D11UavCounterAllocator::CreateBuffer(VkDeviceSize SliceCount) {
|
||||||
|
DxvkBufferCreateInfo info;
|
||||||
|
info.size = SliceCount * m_alignment;
|
||||||
|
info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||||
|
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
||||||
|
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||||
|
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
|
||||||
|
| m_device->GetEnabledShaderStages();
|
||||||
|
info.access = VK_ACCESS_TRANSFER_READ_BIT
|
||||||
|
| VK_ACCESS_TRANSFER_WRITE_BIT
|
||||||
|
| VK_ACCESS_SHADER_READ_BIT
|
||||||
|
| VK_ACCESS_SHADER_WRITE_BIT;
|
||||||
|
|
||||||
|
Rc<DxvkBuffer> buffer = m_device->GetDXVKDevice()->createBuffer(
|
||||||
|
info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < SliceCount; i++) {
|
||||||
|
m_freeSlices.push_back(DxvkBufferSlice(
|
||||||
|
buffer, m_alignment * i, m_alignment));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VkDeviceSize D3D11UavCounterAllocator::GetOffsetAlignment() const {
|
||||||
|
const auto& devInfo = m_device->GetDXVKDevice()->adapter()->deviceProperties();
|
||||||
|
return align(sizeof(D3D11UavCounter), devInfo.limits.minStorageBufferOffsetAlignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
69
src/d3d11/d3d11_uav_counter.h
Normal file
69
src/d3d11/d3d11_uav_counter.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "d3d11_include.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
class D3D11Device;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief UAV counter structure
|
||||||
|
*
|
||||||
|
* Data structure passed to shaders that use
|
||||||
|
* append/consume buffer functionality.
|
||||||
|
*/
|
||||||
|
struct D3D11UavCounter {
|
||||||
|
uint32_t atomicCtr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief D3D11 UAV counter slice allocator
|
||||||
|
*
|
||||||
|
* Thread-safe allocator for UAV counter slices.
|
||||||
|
* The resulting slices are aligned to the device's
|
||||||
|
* \c minStorageBufferOffsetAlignment.
|
||||||
|
*/
|
||||||
|
class D3D11UavCounterAllocator {
|
||||||
|
constexpr static VkDeviceSize SlicesPerBuffer = 16384;
|
||||||
|
public:
|
||||||
|
|
||||||
|
D3D11UavCounterAllocator(
|
||||||
|
D3D11Device* pDevice);
|
||||||
|
|
||||||
|
~D3D11UavCounterAllocator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Allocates a counter slice
|
||||||
|
*
|
||||||
|
* Picks a slice from the free list or
|
||||||
|
* creates a new buffer if necessary.
|
||||||
|
* \returns The counter slice
|
||||||
|
*/
|
||||||
|
DxvkBufferSlice AllocSlice();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Frees a counter slice
|
||||||
|
*
|
||||||
|
* Adds the given slice back to the
|
||||||
|
* free list so that it can be reused.
|
||||||
|
* \param [in] Slice the slice to free
|
||||||
|
*/
|
||||||
|
void FreeSlice(
|
||||||
|
const DxvkBufferSlice& Slice);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
D3D11Device* m_device;
|
||||||
|
VkDeviceSize m_alignment;
|
||||||
|
|
||||||
|
std::mutex m_mutex;
|
||||||
|
std::vector<DxvkBufferSlice> m_freeSlices;
|
||||||
|
|
||||||
|
void CreateBuffer(VkDeviceSize SliceCount);
|
||||||
|
|
||||||
|
VkDeviceSize GetOffsetAlignment() const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -8,11 +8,6 @@ namespace dxvk {
|
|||||||
|
|
||||||
class D3D11Device;
|
class D3D11Device;
|
||||||
|
|
||||||
struct D3D11UavCounter {
|
|
||||||
uint32_t atomicCtr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Unordered access view
|
* \brief Unordered access view
|
||||||
*
|
*
|
||||||
|
@ -22,6 +22,7 @@ d3d11_src = [
|
|||||||
'd3d11_shader.cpp',
|
'd3d11_shader.cpp',
|
||||||
'd3d11_state.cpp',
|
'd3d11_state.cpp',
|
||||||
'd3d11_texture.cpp',
|
'd3d11_texture.cpp',
|
||||||
|
'd3d11_uav_counter.cpp',
|
||||||
'd3d11_util.cpp',
|
'd3d11_util.cpp',
|
||||||
'd3d11_view_dsv.cpp',
|
'd3d11_view_dsv.cpp',
|
||||||
'd3d11_view_rtv.cpp',
|
'd3d11_view_rtv.cpp',
|
||||||
|
Loading…
Reference in New Issue
Block a user