From 97d776cc00cf910dfb08bd2d31e3d4bcb16f3ccb Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 30 Aug 2018 15:56:51 +0200 Subject: [PATCH] [d3d11] Allocate counter for stream output buffers --- src/d3d11/d3d11_buffer.cpp | 172 +++++++++++++++++------------------ src/d3d11/d3d11_buffer.h | 23 ++++- src/d3d11/d3d11_device.cpp | 22 +++++ src/d3d11/d3d11_device.h | 16 ++-- src/d3d11/d3d11_view_uav.cpp | 4 +- 5 files changed, 138 insertions(+), 99 deletions(-) diff --git a/src/d3d11/d3d11_buffer.cpp b/src/d3d11/d3d11_buffer.cpp index c34b57fa..a67df242 100644 --- a/src/d3d11/d3d11_buffer.cpp +++ b/src/d3d11/d3d11_buffer.cpp @@ -11,92 +11,7 @@ namespace dxvk { const D3D11_BUFFER_DESC* pDesc) : m_device (pDevice), m_desc (*pDesc), - m_buffer (CreateBuffer(pDesc)), - m_mappedSlice (m_buffer->slice()), m_d3d10 (this) { - - } - - - D3D11Buffer::~D3D11Buffer() { - - } - - - HRESULT STDMETHODCALLTYPE D3D11Buffer::QueryInterface(REFIID riid, void** ppvObject) { - *ppvObject = nullptr; - - if (riid == __uuidof(IUnknown) - || riid == __uuidof(ID3D11DeviceChild) - || riid == __uuidof(ID3D11Resource) - || riid == __uuidof(ID3D11Buffer)) { - *ppvObject = ref(this); - return S_OK; - } - - if (riid == __uuidof(ID3D10DeviceChild) - || riid == __uuidof(ID3D10Resource) - || riid == __uuidof(ID3D10Buffer)) { - *ppvObject = ref(&m_d3d10); - return S_OK; - } - - Logger::warn("D3D11Buffer::QueryInterface: Unknown interface query"); - Logger::warn(str::format(riid)); - return E_NOINTERFACE; - } - - - void STDMETHODCALLTYPE D3D11Buffer::GetDevice(ID3D11Device** ppDevice) { - *ppDevice = m_device.ref(); - } - - - UINT STDMETHODCALLTYPE D3D11Buffer::GetEvictionPriority() { - Logger::warn("D3D11Buffer::GetEvictionPriority: Stub"); - return DXGI_RESOURCE_PRIORITY_NORMAL; - } - - - void STDMETHODCALLTYPE D3D11Buffer::SetEvictionPriority(UINT EvictionPriority) { - Logger::warn("D3D11Buffer::SetEvictionPriority: Stub"); - } - - - void STDMETHODCALLTYPE D3D11Buffer::GetType(D3D11_RESOURCE_DIMENSION* pResourceDimension) { - *pResourceDimension = D3D11_RESOURCE_DIMENSION_BUFFER; - } - - - void STDMETHODCALLTYPE D3D11Buffer::GetDesc(D3D11_BUFFER_DESC* pDesc) { - *pDesc = m_desc; - } - - - bool D3D11Buffer::CheckViewCompatibility( - UINT BindFlags, - DXGI_FORMAT Format) const { - // Check whether the given bind flags are supported - VkBufferUsageFlags usage = GetBufferUsageFlags(BindFlags); - - if ((m_buffer->info().usage & usage) != usage) - return false; - - // Structured buffer views use no format - if (Format == DXGI_FORMAT_UNKNOWN) - return (m_desc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) != 0; - - // Check whether the given combination of buffer view - // type and view format is supported by the device - DXGI_VK_FORMAT_INFO viewFormat = m_device->LookupFormat(Format, DXGI_VK_FORMAT_MODE_ANY); - VkFormatFeatureFlags features = GetBufferFormatFeatures(BindFlags); - - return CheckFormatFeatureSupport(viewFormat.Format, features); - } - - - Rc D3D11Buffer::CreateBuffer( - const D3D11_BUFFER_DESC* pDesc) const { DxvkBufferCreateInfo info; info.size = pDesc->ByteWidth; info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT @@ -175,7 +90,92 @@ namespace dxvk { if (pDesc->Usage == D3D11_USAGE_DYNAMIC && pDesc->BindFlags) memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - return m_device->GetDXVKDevice()->createBuffer(info, memoryFlags); + // Create the buffer and set the entire buffer slice as mapped, + // so that we only have to update it when invalidating th buffer + m_buffer = m_device->GetDXVKDevice()->createBuffer(info, memoryFlags); + m_mapped = m_buffer->slice(); + + // For Stream Output buffers we need a counter + if (pDesc->BindFlags & D3D11_BIND_STREAM_OUTPUT) + m_soCounter = m_device->AllocXfbCounterSlice(); + } + + + D3D11Buffer::~D3D11Buffer() { + if (m_soCounter.defined()) + m_device->FreeXfbCounterSlice(m_soCounter); + } + + + HRESULT STDMETHODCALLTYPE D3D11Buffer::QueryInterface(REFIID riid, void** ppvObject) { + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11Resource) + || riid == __uuidof(ID3D11Buffer)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10Resource) + || riid == __uuidof(ID3D10Buffer)) { + *ppvObject = ref(&m_d3d10); + return S_OK; + } + + Logger::warn("D3D11Buffer::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11Buffer::GetDevice(ID3D11Device** ppDevice) { + *ppDevice = m_device.ref(); + } + + + UINT STDMETHODCALLTYPE D3D11Buffer::GetEvictionPriority() { + Logger::warn("D3D11Buffer::GetEvictionPriority: Stub"); + return DXGI_RESOURCE_PRIORITY_NORMAL; + } + + + void STDMETHODCALLTYPE D3D11Buffer::SetEvictionPriority(UINT EvictionPriority) { + Logger::warn("D3D11Buffer::SetEvictionPriority: Stub"); + } + + + void STDMETHODCALLTYPE D3D11Buffer::GetType(D3D11_RESOURCE_DIMENSION* pResourceDimension) { + *pResourceDimension = D3D11_RESOURCE_DIMENSION_BUFFER; + } + + + void STDMETHODCALLTYPE D3D11Buffer::GetDesc(D3D11_BUFFER_DESC* pDesc) { + *pDesc = m_desc; + } + + + bool D3D11Buffer::CheckViewCompatibility( + UINT BindFlags, + DXGI_FORMAT Format) const { + // Check whether the given bind flags are supported + VkBufferUsageFlags usage = GetBufferUsageFlags(BindFlags); + + if ((m_buffer->info().usage & usage) != usage) + return false; + + // Structured buffer views use no format + if (Format == DXGI_FORMAT_UNKNOWN) + return (m_desc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) != 0; + + // Check whether the given combination of buffer view + // type and view format is supported by the device + DXGI_VK_FORMAT_INFO viewFormat = m_device->LookupFormat(Format, DXGI_VK_FORMAT_MODE_ANY); + VkFormatFeatureFlags features = GetBufferFormatFeatures(BindFlags); + + return CheckFormatFeatureSupport(viewFormat.Format, features); } diff --git a/src/d3d11/d3d11_buffer.h b/src/d3d11/d3d11_buffer.h index 2d567dd3..bdb23137 100644 --- a/src/d3d11/d3d11_buffer.h +++ b/src/d3d11/d3d11_buffer.h @@ -11,6 +11,18 @@ namespace dxvk { class D3D11Device; class D3D11DeviceContext; + + + /** + * \brief Stream output buffer offset + * + * A byte offset into the buffer that + * stores the byte offset where new + * data will be written to. + */ + struct D3D11SOCounter { + uint32_t byteOffset; + }; class D3D11Buffer : public D3D11DeviceChild { @@ -62,17 +74,21 @@ namespace dxvk { DxvkBufferSlice GetBufferSlice(VkDeviceSize offset, VkDeviceSize length) const { return DxvkBufferSlice(m_buffer, offset, length); } + + DxvkBufferSlice GetSOCounter() { + return m_soCounter; + } VkDeviceSize GetSize() const { return m_buffer->info().size; } DxvkPhysicalBufferSlice GetMappedSlice() const { - return m_mappedSlice; + return m_mapped; } void SetMappedSlice(const DxvkPhysicalBufferSlice& slice) { - m_mappedSlice = slice; + m_mapped = slice; } D3D10Buffer* GetD3D10Iface() { @@ -85,7 +101,8 @@ namespace dxvk { const D3D11_BUFFER_DESC m_desc; Rc m_buffer; - DxvkPhysicalBufferSlice m_mappedSlice; + DxvkBufferSlice m_soCounter; + DxvkPhysicalBufferSlice m_mapped; D3D10Buffer m_d3d10; diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 71f05886..aa5065da 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -117,6 +117,7 @@ namespace dxvk { m_d3d10Device = new D3D10Device(this, m_context); m_uavCounters = CreateUAVCounterBuffer(); + m_xfbCounters = CreateXFBCounterBuffer(); } @@ -1496,6 +1497,27 @@ namespace dxvk { return new D3D11CounterBuffer(m_dxvkDevice, uavCounterInfo, uavCounterSliceLength); } + + + Rc D3D11Device::CreateXFBCounterBuffer() { + DxvkBufferCreateInfo xfbCounterInfo; + xfbCounterInfo.size = 4096 * sizeof(D3D11SOCounter); + xfbCounterInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_TRANSFER_SRC_BIT + | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT; + xfbCounterInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT + | VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT; + xfbCounterInfo.access = VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_INDIRECT_COMMAND_READ_BIT + | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT + | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT; + + return new D3D11CounterBuffer(m_dxvkDevice, + xfbCounterInfo, sizeof(D3D11SOCounter)); + } HRESULT D3D11Device::CreateShaderModule( diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index 9b257325..eb1d28f3 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -333,14 +333,6 @@ namespace dxvk { DXGI_FORMAT Format, DXGI_VK_FORMAT_MODE Mode) const; - DxvkBufferSlice AllocCounterSlice() { - return m_uavCounters->AllocSlice(); - } - - void FreeCounterSlice(const DxvkBufferSlice& Slice) { - m_uavCounters->FreeSlice(Slice); - } - DxvkCsChunkRef AllocCsChunk() { DxvkCsChunk* chunk = m_csChunkPool.allocChunk(); return DxvkCsChunkRef(chunk, &m_csChunkPool); @@ -354,6 +346,12 @@ namespace dxvk { return m_d3d10Device; } + DxvkBufferSlice AllocUavCounterSlice() { return m_uavCounters->AllocSlice(); } + DxvkBufferSlice AllocXfbCounterSlice() { return m_xfbCounters->AllocSlice(); } + + void FreeUavCounterSlice(const DxvkBufferSlice& Slice) { m_uavCounters->FreeSlice(Slice); } + void FreeXfbCounterSlice(const DxvkBufferSlice& Slice) { m_xfbCounters->FreeSlice(Slice); } + static bool CheckFeatureLevelSupport( const Rc& adapter, D3D_FEATURE_LEVEL featureLevel); @@ -383,6 +381,7 @@ namespace dxvk { D3D10Device* m_d3d10Device = nullptr; Rc m_uavCounters; + Rc m_xfbCounters; D3D11StateObjectSet m_bsStateObjects; D3D11StateObjectSet m_dsStateObjects; @@ -391,6 +390,7 @@ namespace dxvk { D3D11ShaderModuleSet m_shaderModules; Rc CreateUAVCounterBuffer(); + Rc CreateXFBCounterBuffer(); HRESULT CreateShaderModule( D3D11CommonShader* pShaderModule, diff --git a/src/d3d11/d3d11_view_uav.cpp b/src/d3d11/d3d11_view_uav.cpp index 1078fce1..2f5d1355 100644 --- a/src/d3d11/d3d11_view_uav.cpp +++ b/src/d3d11/d3d11_view_uav.cpp @@ -38,7 +38,7 @@ namespace dxvk { } if (pDesc->Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER)) - m_counterSlice = pDevice->AllocCounterSlice(); + m_counterSlice = pDevice->AllocUavCounterSlice(); m_bufferView = pDevice->GetDXVKDevice()->createBufferView( buffer->GetBuffer(), viewInfo); @@ -109,7 +109,7 @@ namespace dxvk { ResourceReleasePrivate(m_resource); if (m_counterSlice.defined()) - m_device->FreeCounterSlice(m_counterSlice); + m_device->FreeUavCounterSlice(m_counterSlice); }