Skip to content

Commit

Permalink
[d3d9] Optimize buffer usage/stages/access, general buffer refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
misyltoad committed May 11, 2019
1 parent 953cc44 commit 6573579
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 88 deletions.
110 changes: 67 additions & 43 deletions src/d3d9/d3d9_common_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,50 +8,11 @@ namespace dxvk {
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc)
: m_parent ( pDevice ), m_desc ( *pDesc ) {
DxvkBufferCreateInfo info;
info.size = m_desc.Size;
info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
| VK_BUFFER_USAGE_TRANSFER_DST_BIT;
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
info.access = VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_TRANSFER_WRITE_BIT;

if (pDesc->Type == D3DRTYPE_VERTEXBUFFER) {
info.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
info.stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
info.access |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
}
else if (pDesc->Type == D3DRTYPE_INDEXBUFFER) {
info.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
info.stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
info.access |= VK_ACCESS_INDEX_READ_BIT;
}

if (pDesc->Usage & D3DUSAGE_DYNAMIC) {
info.stages |= VK_PIPELINE_STAGE_HOST_BIT;
info.access |= VK_ACCESS_HOST_WRITE_BIT;

if (!(pDesc->Usage & D3DUSAGE_WRITEONLY))
info.access |= VK_ACCESS_HOST_READ_BIT;
}

VkMemoryPropertyFlags memoryFlags = GetMemoryFlagsForUsage(pDesc->Usage);
m_buffer = CreateBuffer(false);
if (GetMapMode() == D3D9_COMMON_BUFFER_MAP_MODE_BUFFER)
m_stagingBuffer = CreateBuffer(true);

// Create the buffer and set the entire buffer slice as mapped,
// so that we only have to update it when invalidating the buffer
m_buffer = m_parent->GetDXVKDevice()->createBuffer(info, memoryFlags);
m_mapped = m_buffer->getSliceHandle();

if (GetMapMode() == D3D9_COMMON_BUFFER_MAP_MODE_BUFFER) {
info.stages |= VK_PIPELINE_STAGE_HOST_BIT;
info.access |= VK_ACCESS_HOST_WRITE_BIT;

memoryFlags = GetMemoryFlagsForUsage(pDesc->Usage | D3DUSAGE_DYNAMIC);
memoryFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;

m_stagingBuffer = m_parent->GetDXVKDevice()->createBuffer(info, memoryFlags);
m_mapped = m_stagingBuffer->getSliceHandle();
}
m_sliceHandle = GetMapBuffer()->getSliceHandle();
}

HRESULT D3D9CommonBuffer::Lock(
Expand All @@ -76,4 +37,67 @@ namespace dxvk {
*pDesc = m_desc;
}

Rc<DxvkBuffer> D3D9CommonBuffer::CreateBuffer(bool staging) const {
DxvkBufferCreateInfo info;
info.size = m_desc.Size;
info.usage = 0;
info.stages = 0;
info.access = 0;

VkMemoryPropertyFlags memoryFlags = 0;

if (!staging) {
if (m_desc.Type == D3DRTYPE_VERTEXBUFFER) {
info.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
info.stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
info.access |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
}
else if (m_desc.Type == D3DRTYPE_INDEXBUFFER) {
info.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
info.stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
info.access |= VK_ACCESS_INDEX_READ_BIT;
}

if (m_desc.Usage & D3DUSAGE_DYNAMIC) {
info.stages |= VK_PIPELINE_STAGE_HOST_BIT;

info.access |= VK_ACCESS_HOST_WRITE_BIT;

if (!(m_desc.Usage & D3DUSAGE_WRITEONLY))
info.access |= VK_ACCESS_HOST_READ_BIT;

memoryFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
| VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
}
else {
info.stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;

info.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;

info.access |= VK_ACCESS_TRANSFER_WRITE_BIT;

memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
}
}
else {
info.stages |= VK_PIPELINE_STAGE_HOST_BIT
| VK_PIPELINE_STAGE_TRANSFER_BIT;

info.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;

info.access |= VK_ACCESS_HOST_WRITE_BIT
| VK_ACCESS_TRANSFER_READ_BIT;

if (!(m_desc.Usage & D3DUSAGE_WRITEONLY))
info.access |= VK_ACCESS_HOST_READ_BIT;

memoryFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
}

return m_parent->GetDXVKDevice()->createBuffer(info, memoryFlags);
}

}
38 changes: 22 additions & 16 deletions src/d3d9/d3d9_common_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,43 +55,47 @@ namespace dxvk {
D3D9_BUFFER_DESC* pDesc);

D3D9_COMMON_BUFFER_MAP_MODE GetMapMode() const {
return (m_buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
return m_desc.Usage & D3DUSAGE_DYNAMIC
? D3D9_COMMON_BUFFER_MAP_MODE_DIRECT
: D3D9_COMMON_BUFFER_MAP_MODE_BUFFER;
}

Rc<DxvkBuffer> GetBuffer(D3D9_COMMON_BUFFER_TYPE type) const {
if (type == D3D9_COMMON_BUFFER_TYPE_MAPPING)
template <D3D9_COMMON_BUFFER_TYPE Type>
Rc<DxvkBuffer> GetBuffer() const {
if constexpr (Type == D3D9_COMMON_BUFFER_TYPE_MAPPING)
return GetMapBuffer();
else if (type == D3D9_COMMON_BUFFER_TYPE_STAGING)
else if constexpr (Type == D3D9_COMMON_BUFFER_TYPE_STAGING)
return GetStagingBuffer();
else //if (type == D3D9_COMMON_BUFFER_TYPE_REAL)
else //if constexpr (Type == D3D9_COMMON_BUFFER_TYPE_REAL)
return GetRealBuffer();
}

DxvkBufferSlice GetBufferSlice(D3D9_COMMON_BUFFER_TYPE type) const {
return GetBufferSlice(type, 0, m_desc.Size);
template <D3D9_COMMON_BUFFER_TYPE Type>
DxvkBufferSlice GetBufferSlice() const {
return GetBufferSlice<Type>(0, m_desc.Size);
}

DxvkBufferSlice GetBufferSlice(D3D9_COMMON_BUFFER_TYPE type, VkDeviceSize offset) const {
return GetBufferSlice(type, offset, m_desc.Size - offset);
template <D3D9_COMMON_BUFFER_TYPE Type>
DxvkBufferSlice GetBufferSlice(VkDeviceSize offset) const {
return GetBufferSlice<Type>(offset, m_desc.Size - offset);
}

DxvkBufferSlice GetBufferSlice(D3D9_COMMON_BUFFER_TYPE type, VkDeviceSize offset, VkDeviceSize length) const {
return DxvkBufferSlice(GetBuffer(type), offset, length);
template <D3D9_COMMON_BUFFER_TYPE Type>
DxvkBufferSlice GetBufferSlice(VkDeviceSize offset, VkDeviceSize length) const {
return DxvkBufferSlice(GetBuffer<Type>(), offset, length);
}

DxvkBufferSliceHandle AllocMapSlice() {
return GetMapBuffer()->allocSlice();
}

DxvkBufferSliceHandle DiscardMapSlice() {
m_mapped = GetMapBuffer()->allocSlice();
return m_mapped;
m_sliceHandle = GetMapBuffer()->allocSlice();
return m_sliceHandle;
}

DxvkBufferSliceHandle GetMappedSlice() const {
return m_mapped;
return m_sliceHandle;
}

DWORD SetMapFlags(DWORD Flags) {
Expand All @@ -106,6 +110,8 @@ namespace dxvk {

private:

Rc<DxvkBuffer> CreateBuffer(bool staging) const;

Rc<DxvkBuffer> GetMapBuffer() const {
return m_stagingBuffer != nullptr ? m_stagingBuffer : m_buffer;
}
Expand All @@ -123,9 +129,9 @@ namespace dxvk {
DWORD m_mapFlags;

Rc<DxvkBuffer> m_buffer;

Rc<DxvkBuffer> m_stagingBuffer;
DxvkBufferSliceHandle m_mapped;

DxvkBufferSliceHandle m_sliceHandle;

};

Expand Down
15 changes: 7 additions & 8 deletions src/d3d9/d3d9_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3454,26 +3454,25 @@ namespace dxvk {
// it as the 'new' mapped slice. This assumes that the
// only way to invalidate a buffer is by mapping it.

// TODO: Investigate locking regions rather than the whole resource.
auto physSlice = pResource->DiscardMapSlice();
uint8_t* data = reinterpret_cast<uint8_t*>(physSlice.mapPtr);
data += OffsetToLock;

*ppbData = reinterpret_cast<void*>(data);

EmitCs([
cBuffer = pResource->GetBuffer(D3D9_COMMON_BUFFER_TYPE_MAPPING),
cBuffer = pResource->GetBuffer<D3D9_COMMON_BUFFER_TYPE_MAPPING>(),
cBufferSlice = physSlice
] (DxvkContext* ctx) {
ctx->invalidateBuffer(cBuffer, cBufferSlice);
ctx->invalidateBuffer(cBuffer, cBufferSlice);
});

return D3D_OK;
}
else {
// Wait until the resource is no longer in use
if (!(Flags & D3DLOCK_NOOVERWRITE) && pResource->GetMapMode() == D3D9_COMMON_BUFFER_MAP_MODE_DIRECT) {
if (!WaitForResource(pResource->GetBuffer(D3D9_COMMON_BUFFER_TYPE_REAL), Flags))
if (!WaitForResource(pResource->GetBuffer<D3D9_COMMON_BUFFER_TYPE_REAL>(), Flags))
return D3DERR_WASSTILLDRAWING;
}

Expand Down Expand Up @@ -3503,8 +3502,8 @@ namespace dxvk {

FlushImplicit(FALSE);

auto dstBuffer = pResource->GetBufferSlice(D3D9_COMMON_BUFFER_TYPE_REAL);
auto srcBuffer = pResource->GetBufferSlice(D3D9_COMMON_BUFFER_TYPE_STAGING);
auto dstBuffer = pResource->GetBufferSlice<D3D9_COMMON_BUFFER_TYPE_REAL>();
auto srcBuffer = pResource->GetBufferSlice<D3D9_COMMON_BUFFER_TYPE_STAGING>();

EmitCs([
cDstSlice = dstBuffer,
Expand Down Expand Up @@ -4310,7 +4309,7 @@ namespace dxvk {
EmitCs([
cSlotId = Slot,
cBufferSlice = pBuffer != nullptr ?
pBuffer->GetCommonBuffer()->GetBufferSlice(D3D9_COMMON_BUFFER_TYPE_REAL, Offset)
pBuffer->GetCommonBuffer()->GetBufferSlice<D3D9_COMMON_BUFFER_TYPE_REAL>(Offset)
: DxvkBufferSlice(),
cStride = pBuffer != nullptr ? Stride : 0
] (DxvkContext* ctx) {
Expand All @@ -4330,7 +4329,7 @@ namespace dxvk {
const VkIndexType indexType = DecodeIndexType(format);

EmitCs([
cBufferSlice = buffer != nullptr ? buffer->GetBufferSlice(D3D9_COMMON_BUFFER_TYPE_REAL) : DxvkBufferSlice(),
cBufferSlice = buffer != nullptr ? buffer->GetBufferSlice<D3D9_COMMON_BUFFER_TYPE_REAL>() : DxvkBufferSlice(),
cIndexType = indexType
](DxvkContext* ctx) {
ctx->bindIndexBuffer(cBufferSlice, cIndexType);
Expand Down
6 changes: 3 additions & 3 deletions src/d3d9/d3d9_initializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace dxvk {

void D3D9Initializer::InitBuffer(
D3D9CommonBuffer* pBuffer) {
VkMemoryPropertyFlags memFlags = pBuffer->GetBuffer(D3D9_COMMON_BUFFER_TYPE_REAL)->memFlags();
VkMemoryPropertyFlags memFlags = pBuffer->GetBuffer<D3D9_COMMON_BUFFER_TYPE_REAL>()->memFlags();

(memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
? InitHostVisibleBuffer(pBuffer)
Expand All @@ -51,7 +51,7 @@ namespace dxvk {
D3D9CommonBuffer* pBuffer) {
std::lock_guard<std::mutex> lock(m_mutex);

DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice(D3D9_COMMON_BUFFER_TYPE_REAL);
DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice<D3D9_COMMON_BUFFER_TYPE_REAL>();

m_transferCommands += 1;

Expand All @@ -70,7 +70,7 @@ namespace dxvk {
// If the buffer is mapped, we can write data directly
// to the mapped memory region instead of doing it on
// the GPU. Same goes for zero-initialization.
DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice(D3D9_COMMON_BUFFER_TYPE_REAL);
DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice<D3D9_COMMON_BUFFER_TYPE_REAL>();

std::memset(
bufferSlice.mapPtr(0), 0,
Expand Down
15 changes: 0 additions & 15 deletions src/d3d9/d3d9_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,21 +119,6 @@ namespace dxvk {
return usage;
}

VkMemoryPropertyFlags GetMemoryFlagsForUsage(
DWORD Usage) {
VkMemoryPropertyFlags memoryFlags = 0;

if (Usage & D3DUSAGE_DYNAMIC) {
memoryFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
}
else {
memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
}

return memoryFlags;
}

uint32_t VertexCount(D3DPRIMITIVETYPE type, UINT count) {
switch (type) {
default:
Expand Down
3 changes: 0 additions & 3 deletions src/d3d9/d3d9_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@ namespace dxvk {

VkImageUsageFlags GetImageUsageFlags(DWORD Usage);

VkMemoryPropertyFlags GetMemoryFlagsForUsage(
DWORD Usage);

template <typename T>
void changePrivate(T*& srcPtr, T* newPtr) {
if (srcPtr != nullptr)
Expand Down

0 comments on commit 6573579

Please sign in to comment.