mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-07-11 01:34:17 +02:00
GS/DX12: Copy constant buffers to default heap
This commit is contained in:
committed by
lightningterror
parent
12940f2e1b
commit
0e667a9b0f
@@ -20,7 +20,7 @@ D3D12StreamBuffer::~D3D12StreamBuffer()
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool D3D12StreamBuffer::Create(u32 size)
|
||||
bool D3D12StreamBuffer::Create(u32 size, bool gpu_backed_buffer)
|
||||
{
|
||||
const GSDevice12::D3D12_RESOURCE_DESCU resource_desc = {{D3D12_RESOURCE_DIMENSION_BUFFER, 0, size, 1, 1, 1, DXGI_FORMAT_UNKNOWN,
|
||||
{1, 0}, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, D3D12_RESOURCE_FLAG_NONE}};
|
||||
@@ -51,11 +51,32 @@ bool D3D12StreamBuffer::Create(u32 size)
|
||||
|
||||
Destroy(true);
|
||||
|
||||
m_buffer = std::move(buffer);
|
||||
m_allocation = std::move(allocation);
|
||||
m_buffer_upload = std::move(buffer);
|
||||
m_allocation_upload = std::move(allocation);
|
||||
m_host_pointer = host_pointer;
|
||||
m_size = size;
|
||||
m_gpu_pointer = m_buffer->GetGPUVirtualAddress();
|
||||
|
||||
if (gpu_backed_buffer)
|
||||
{
|
||||
allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
|
||||
|
||||
if (GSDevice12::GetInstance()->UseEnhancedBarriers())
|
||||
hr = GSDevice12::GetInstance()->GetAllocator()->CreateResource3(&allocationDesc, &resource_desc.desc1,
|
||||
D3D12_BARRIER_LAYOUT_UNDEFINED, nullptr, 0, nullptr, allocation.put(), IID_PPV_ARGS(buffer.put()));
|
||||
else
|
||||
hr = GSDevice12::GetInstance()->GetAllocator()->CreateResource(&allocationDesc, &resource_desc.desc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, allocation.put(), IID_PPV_ARGS(buffer.put()));
|
||||
pxAssertMsg(SUCCEEDED(hr), "Allocate buffer");
|
||||
if (FAILED(hr))
|
||||
return false;
|
||||
|
||||
m_buffer_default = std::move(buffer);
|
||||
m_allocation_default = std::move(allocation);
|
||||
m_gpu_pointer = m_buffer_default->GetGPUVirtualAddress();
|
||||
}
|
||||
else
|
||||
m_gpu_pointer = m_buffer_upload->GetGPUVirtualAddress();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -136,21 +157,50 @@ void D3D12StreamBuffer::CommitMemory(u32 final_num_bytes)
|
||||
m_current_space -= final_num_bytes;
|
||||
}
|
||||
|
||||
void D3D12StreamBuffer::FlushMemory()
|
||||
{
|
||||
if (m_buffer_default &&
|
||||
m_current_space != m_size)
|
||||
{
|
||||
if (m_current_copy_offset < m_current_offset)
|
||||
{
|
||||
const u32 size = m_current_offset - m_current_copy_offset;
|
||||
GSDevice12::GetInstance()->GetInitCommandList().list4->CopyBufferRegion(m_buffer_default.get(), m_current_copy_offset,
|
||||
m_buffer_upload.get(), m_current_copy_offset, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
const u32 size = m_size - m_current_copy_offset;
|
||||
GSDevice12::GetInstance()->GetInitCommandList().list4->CopyBufferRegion(m_buffer_default.get(), m_current_copy_offset,
|
||||
m_buffer_upload.get(), m_current_copy_offset, size);
|
||||
GSDevice12::GetInstance()->GetInitCommandList().list4->CopyBufferRegion(m_buffer_default.get(), 0,
|
||||
m_buffer_upload.get(), 0, m_current_offset);
|
||||
}
|
||||
m_current_copy_offset = m_current_offset;
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12StreamBuffer::Destroy(bool defer)
|
||||
{
|
||||
if (m_host_pointer)
|
||||
{
|
||||
const D3D12_RANGE written_range = {0, m_size};
|
||||
m_buffer->Unmap(0, &written_range);
|
||||
m_buffer_upload->Unmap(0, &written_range);
|
||||
m_host_pointer = nullptr;
|
||||
}
|
||||
|
||||
if (m_buffer && defer)
|
||||
GSDevice12::GetInstance()->DeferResourceDestruction(m_allocation.get(), m_buffer.get());
|
||||
m_buffer.reset();
|
||||
m_allocation.reset();
|
||||
if (m_buffer_upload && defer)
|
||||
GSDevice12::GetInstance()->DeferResourceDestruction(m_allocation_upload.get(), m_buffer_upload.get());
|
||||
m_buffer_upload.reset();
|
||||
m_allocation_upload.reset();
|
||||
|
||||
if (m_buffer_default && defer)
|
||||
GSDevice12::GetInstance()->DeferResourceDestruction(m_allocation_default.get(), m_buffer_default.get());
|
||||
m_buffer_default.reset();
|
||||
m_allocation_default.reset();
|
||||
|
||||
m_current_offset = 0;
|
||||
m_current_copy_offset = 0;
|
||||
m_current_space = 0;
|
||||
m_current_gpu_position = 0;
|
||||
m_tracked_fences.clear();
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include "common/RedtapeWilCom.h"
|
||||
#include "common/Assertions.h"
|
||||
|
||||
#include <d3d12.h>
|
||||
#include <deque>
|
||||
@@ -22,10 +23,17 @@ public:
|
||||
D3D12StreamBuffer();
|
||||
~D3D12StreamBuffer();
|
||||
|
||||
bool Create(u32 size);
|
||||
// gpu_backed_buffer specifies if a second buffer should be created in the default heap.
|
||||
bool Create(u32 size, bool gpu_backed_buffer = false);
|
||||
|
||||
__fi bool IsValid() const { return static_cast<bool>(m_buffer); }
|
||||
__fi ID3D12Resource* GetBuffer() const { return m_buffer.get(); }
|
||||
__fi bool IsValid() const { return static_cast<bool>(m_buffer_upload); }
|
||||
__fi ID3D12Resource* GetBuffer() const
|
||||
{
|
||||
// This function is currently only used for textures, which already need to bt copied to a texture resource.
|
||||
// For now, assert that gpu_backed_buffer was false.
|
||||
pxAssert(m_buffer_default == nullptr);
|
||||
return m_buffer_upload.get();
|
||||
}
|
||||
__fi D3D12_GPU_VIRTUAL_ADDRESS GetGPUPointer() const { return m_gpu_pointer; }
|
||||
__fi void* GetHostPointer() const { return m_host_pointer; }
|
||||
__fi void* GetCurrentHostPointer() const { return m_host_pointer + m_current_offset; }
|
||||
@@ -36,6 +44,8 @@ public:
|
||||
|
||||
bool ReserveMemory(u32 num_bytes, u32 alignment);
|
||||
void CommitMemory(u32 final_num_bytes);
|
||||
// Queues copy to default heap if gpu_backed_buffer was true.
|
||||
void FlushMemory();
|
||||
|
||||
void Destroy(bool defer = true);
|
||||
|
||||
@@ -48,11 +58,14 @@ private:
|
||||
|
||||
u32 m_size = 0;
|
||||
u32 m_current_offset = 0;
|
||||
u32 m_current_copy_offset = 0;
|
||||
u32 m_current_space = 0;
|
||||
u32 m_current_gpu_position = 0;
|
||||
|
||||
wil::com_ptr_nothrow<ID3D12Resource> m_buffer;
|
||||
wil::com_ptr_nothrow<D3D12MA::Allocation> m_allocation;
|
||||
wil::com_ptr_nothrow<ID3D12Resource> m_buffer_upload;
|
||||
wil::com_ptr_nothrow<ID3D12Resource> m_buffer_default;
|
||||
wil::com_ptr_nothrow<D3D12MA::Allocation> m_allocation_upload;
|
||||
wil::com_ptr_nothrow<D3D12MA::Allocation> m_allocation_default;
|
||||
D3D12_GPU_VIRTUAL_ADDRESS m_gpu_pointer = {};
|
||||
u8* m_host_pointer = nullptr;
|
||||
|
||||
|
||||
@@ -546,6 +546,12 @@ bool GSDevice12::ExecuteCommandList(WaitType wait_for_completion)
|
||||
CommandListResources& res = m_command_lists[m_current_command_list];
|
||||
HRESULT hr;
|
||||
|
||||
// Flush stream buffers to GPU memory
|
||||
m_vertex_stream_buffer.FlushMemory();
|
||||
m_index_stream_buffer.FlushMemory();
|
||||
m_vertex_constant_buffer.FlushMemory();
|
||||
m_pixel_constant_buffer.FlushMemory();
|
||||
|
||||
if (res.has_timestamp_query)
|
||||
{
|
||||
// write the timestamp back at the end of the cmdlist
|
||||
@@ -576,7 +582,11 @@ bool GSDevice12::ExecuteCommandList(WaitType wait_for_completion)
|
||||
|
||||
if (res.init_command_list_used)
|
||||
{
|
||||
const std::array<ID3D12CommandList*, 2> execute_lists{res.command_lists[0].list4.get(), res.command_lists[1].list4.get()};
|
||||
// Call as seperate ExecuteCommandLists to ensure constant buffer copies are completed.
|
||||
// This ends up being faster then using barriers on each buffer.
|
||||
std::array<ID3D12CommandList*, 1> execute_lists{res.command_lists[0].list4.get()};
|
||||
m_command_queue->ExecuteCommandLists(static_cast<UINT>(execute_lists.size()), execute_lists.data());
|
||||
execute_lists[0] = res.command_lists[1].list4.get();
|
||||
m_command_queue->ExecuteCommandLists(static_cast<UINT>(execute_lists.size()), execute_lists.data());
|
||||
}
|
||||
else
|
||||
@@ -2569,25 +2579,25 @@ bool GSDevice12::CreateNullTexture()
|
||||
|
||||
bool GSDevice12::CreateBuffers()
|
||||
{
|
||||
if (!m_vertex_stream_buffer.Create(VERTEX_BUFFER_SIZE))
|
||||
if (!m_vertex_stream_buffer.Create(VERTEX_BUFFER_SIZE, false))
|
||||
{
|
||||
Host::ReportErrorAsync("GS", "Failed to allocate vertex buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_index_stream_buffer.Create(INDEX_BUFFER_SIZE))
|
||||
if (!m_index_stream_buffer.Create(INDEX_BUFFER_SIZE, false))
|
||||
{
|
||||
Host::ReportErrorAsync("GS", "Failed to allocate index buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_vertex_constant_buffer.Create(VERTEX_UNIFORM_BUFFER_SIZE))
|
||||
if (!m_vertex_constant_buffer.Create(VERTEX_UNIFORM_BUFFER_SIZE, !m_uma))
|
||||
{
|
||||
Host::ReportErrorAsync("GS", "Failed to allocate vertex uniform buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_pixel_constant_buffer.Create(FRAGMENT_UNIFORM_BUFFER_SIZE))
|
||||
if (!m_pixel_constant_buffer.Create(FRAGMENT_UNIFORM_BUFFER_SIZE, !m_uma))
|
||||
{
|
||||
Host::ReportErrorAsync("GS", "Failed to allocate fragment uniform buffer");
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user