mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-16 03:38:38 +12:00
d3d12: First attempt at read color buffer using dma address change
If address of m_context_dma_color_a change, copy the RTT in a texture that can be used for drawing. Currently a bit broken, the rtt is used for others textures too...
This commit is contained in:
parent
3e11598941
commit
595392428d
4 changed files with 156 additions and 90 deletions
|
@ -36,7 +36,6 @@ void D3D12GSRender::ResourceStorage::Reset()
|
||||||
|
|
||||||
void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
|
void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
|
||||||
{
|
{
|
||||||
m_queueCompletion = 0;
|
|
||||||
// Create a global command allocator
|
// Create a global command allocator
|
||||||
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator));
|
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator));
|
||||||
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_textureUploadCommandAllocator));
|
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_textureUploadCommandAllocator));
|
||||||
|
@ -345,6 +344,57 @@ void D3D12GSRender::Close()
|
||||||
|
|
||||||
void D3D12GSRender::InitDrawBuffers()
|
void D3D12GSRender::InitDrawBuffers()
|
||||||
{
|
{
|
||||||
|
// FBO location has changed, previous data might be copied
|
||||||
|
if (m_fbo != nullptr)
|
||||||
|
{
|
||||||
|
// TODO : move to texture heap
|
||||||
|
u32 address_a = GetAddress(m_surface_offset_a, m_context_dma_color_a - 0xfeed0000);
|
||||||
|
if (m_fbo->m_address_color_a != address_a)
|
||||||
|
{
|
||||||
|
LOG_WARNING(RSX, "Copy draw buffer A");
|
||||||
|
Microsoft::WRL::ComPtr<ID3D12Resource> Texture;
|
||||||
|
D3D12_HEAP_PROPERTIES hp = {};
|
||||||
|
hp.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||||
|
check(
|
||||||
|
m_device->CreateCommittedResource(
|
||||||
|
&hp,
|
||||||
|
D3D12_HEAP_FLAG_NONE,
|
||||||
|
&getTexture2DResourceDesc(RSXThread::m_width, RSXThread::m_height, DXGI_FORMAT_R8G8B8A8_UNORM),
|
||||||
|
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
|
nullptr,
|
||||||
|
IID_PPV_ARGS(&Texture)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
ID3D12GraphicsCommandList *copycmdlist;
|
||||||
|
check(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_perFrameStorage.m_commandAllocator, nullptr, IID_PPV_ARGS(©cmdlist)));
|
||||||
|
|
||||||
|
copycmdlist->ResourceBarrier(1, &getResourceBarrierTransition(m_fbo->getRenderTargetTexture(0), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE));
|
||||||
|
|
||||||
|
D3D12_TEXTURE_COPY_LOCATION dst = {}, src = {};
|
||||||
|
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||||
|
dst.pResource = Texture.Get();
|
||||||
|
src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||||
|
src.pResource = m_fbo->getRenderTargetTexture(0);
|
||||||
|
|
||||||
|
copycmdlist->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
|
||||||
|
|
||||||
|
D3D12_RESOURCE_BARRIER barriers[2] =
|
||||||
|
{
|
||||||
|
getResourceBarrierTransition(m_fbo->getRenderTargetTexture(0), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET),
|
||||||
|
getResourceBarrierTransition(Texture.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ),
|
||||||
|
};
|
||||||
|
copycmdlist->ResourceBarrier(2, barriers);
|
||||||
|
check(copycmdlist->Close());
|
||||||
|
|
||||||
|
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)©cmdlist);
|
||||||
|
|
||||||
|
m_texturesRTTs[address_a] = Texture;
|
||||||
|
m_fbo->m_address_color_a = address_a;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (m_fbo == nullptr || RSXThread::m_width != m_lastWidth || RSXThread::m_height != m_lastHeight || m_lastDepth != m_surface_depth_format)
|
if (m_fbo == nullptr || RSXThread::m_width != m_lastWidth || RSXThread::m_height != m_lastHeight || m_lastDepth != m_surface_depth_format)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -361,6 +411,11 @@ void D3D12GSRender::InitDrawBuffers()
|
||||||
};
|
};
|
||||||
|
|
||||||
m_fbo = new D3D12RenderTargetSets(m_device, (u8)m_lastDepth, m_lastWidth, m_lastHeight, clearColor, 1.f);
|
m_fbo = new D3D12RenderTargetSets(m_device, (u8)m_lastDepth, m_lastWidth, m_lastHeight, clearColor, 1.f);
|
||||||
|
m_fbo->m_address_color_a = GetAddress(m_surface_offset_a, m_context_dma_color_a - 0xfeed0000);
|
||||||
|
m_fbo->m_address_color_b = GetAddress(m_surface_offset_b, m_context_dma_color_b - 0xfeed0000);
|
||||||
|
m_fbo->m_address_color_c = GetAddress(m_surface_offset_c, m_context_dma_color_c - 0xfeed0000);
|
||||||
|
m_fbo->m_address_color_d = GetAddress(m_surface_offset_d, m_context_dma_color_d - 0xfeed0000);
|
||||||
|
m_fbo->m_address_z = GetAddress(m_surface_offset_z, m_context_dma_z - 0xfeed0000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,6 +657,8 @@ bool D3D12GSRender::LoadProgram()
|
||||||
|
|
||||||
void D3D12GSRender::ExecCMD()
|
void D3D12GSRender::ExecCMD()
|
||||||
{
|
{
|
||||||
|
InitDrawBuffers();
|
||||||
|
|
||||||
ID3D12GraphicsCommandList *commandList;
|
ID3D12GraphicsCommandList *commandList;
|
||||||
m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_perFrameStorage.m_commandAllocator, nullptr, IID_PPV_ARGS(&commandList));
|
m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_perFrameStorage.m_commandAllocator, nullptr, IID_PPV_ARGS(&commandList));
|
||||||
m_perFrameStorage.m_inflightCommandList.push_back(commandList);
|
m_perFrameStorage.m_inflightCommandList.push_back(commandList);
|
||||||
|
@ -681,8 +738,6 @@ void D3D12GSRender::ExecCMD()
|
||||||
|
|
||||||
m_perFrameStorage.m_currentTextureIndex += usedTexture;
|
m_perFrameStorage.m_currentTextureIndex += usedTexture;
|
||||||
|
|
||||||
InitDrawBuffers();
|
|
||||||
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE *DepthStencilHandle = &m_fbo->getDSVCPUHandle();
|
D3D12_CPU_DESCRIPTOR_HANDLE *DepthStencilHandle = &m_fbo->getDSVCPUHandle();
|
||||||
switch (m_surface_color_target)
|
switch (m_surface_color_target)
|
||||||
{
|
{
|
||||||
|
@ -1123,6 +1178,7 @@ void D3D12GSRender::Flip()
|
||||||
WaitForSingleObject(handle, INFINITE);
|
WaitForSingleObject(handle, INFINITE);
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
m_perFrameStorage.Reset();
|
m_perFrameStorage.Reset();
|
||||||
|
m_texturesRTTs.clear();
|
||||||
|
|
||||||
m_frame->Flip(nullptr);
|
m_frame->Flip(nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,8 @@ void SetGetD3DGSFrameCallback(GetGSFrameCb2 value);
|
||||||
class D3D12GSRender : public GSRender
|
class D3D12GSRender : public GSRender
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
// Copy of RTT to be used as texture
|
||||||
|
std::unordered_map<u32, Microsoft::WRL::ComPtr<ID3D12Resource> > m_texturesRTTs;
|
||||||
// std::vector<PostDrawObj> m_post_draw_objs;
|
// std::vector<PostDrawObj> m_post_draw_objs;
|
||||||
|
|
||||||
PipelineStateObjectCache m_cachePSO;
|
PipelineStateObjectCache m_cachePSO;
|
||||||
|
@ -85,9 +86,6 @@ private:
|
||||||
ID3D12DescriptorHeap *m_samplerDescriptorHeap;
|
ID3D12DescriptorHeap *m_samplerDescriptorHeap;
|
||||||
size_t m_currentTextureIndex;
|
size_t m_currentTextureIndex;
|
||||||
|
|
||||||
// Fence
|
|
||||||
HANDLE m_queueCompletion;
|
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
void Init(ID3D12Device *device);
|
void Init(ID3D12Device *device);
|
||||||
void Release();
|
void Release();
|
||||||
|
|
|
@ -25,5 +25,7 @@ public:
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE getDSVCPUHandle() const;
|
D3D12_CPU_DESCRIPTOR_HANDLE getDSVCPUHandle() const;
|
||||||
ID3D12Resource *getRenderTargetTexture(u8 Id) const;
|
ID3D12Resource *getRenderTargetTexture(u8 Id) const;
|
||||||
ID3D12Resource *getDepthStencilTexture() const;
|
ID3D12Resource *getDepthStencilTexture() const;
|
||||||
|
|
||||||
|
u32 m_address_color_a, m_address_color_b, m_address_color_c, m_address_color_d, m_address_z;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -90,13 +90,13 @@ size_t D3D12GSRender::UploadTextures()
|
||||||
if (!m_textures[i].IsEnabled()) continue;
|
if (!m_textures[i].IsEnabled()) continue;
|
||||||
size_t w = m_textures[i].GetWidth(), h = m_textures[i].GetHeight();
|
size_t w = m_textures[i].GetWidth(), h = m_textures[i].GetHeight();
|
||||||
|
|
||||||
// Upload at each iteration to take advantage of overlapping transfer
|
const u32 texaddr = GetAddress(m_textures[i].GetOffset(), m_textures[i].GetLocation());
|
||||||
ID3D12GraphicsCommandList *commandList;
|
u32 address = GetAddress(m_surface_offset_a, m_context_dma_color_a - 0xfeed0000);
|
||||||
check(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_perFrameStorage.m_textureUploadCommandAllocator, nullptr, IID_PPV_ARGS(&commandList)));
|
|
||||||
|
|
||||||
DXGI_FORMAT dxgiFormat;
|
DXGI_FORMAT dxgiFormat;
|
||||||
size_t blockSizeInByte, blockWidthInPixel, blockHeightInPixel;
|
size_t blockSizeInByte, blockWidthInPixel, blockHeightInPixel;
|
||||||
int format = m_textures[i].GetFormat() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
int format = m_textures[i].GetFormat() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||||
|
|
||||||
bool is_swizzled = !(m_textures[i].GetFormat() & CELL_GCM_TEXTURE_LN);
|
bool is_swizzled = !(m_textures[i].GetFormat() & CELL_GCM_TEXTURE_LN);
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
|
@ -146,14 +146,25 @@ size_t D3D12GSRender::UploadTextures()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ID3D12Resource *vramTexture;
|
||||||
|
std::unordered_map<u32, Microsoft::WRL::ComPtr<ID3D12Resource> >::const_iterator It = m_texturesRTTs.find(address);
|
||||||
|
if (It != m_texturesRTTs.end())
|
||||||
|
{
|
||||||
|
vramTexture = It->second.Get();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Upload at each iteration to take advantage of overlapping transfer
|
||||||
|
ID3D12GraphicsCommandList *commandList;
|
||||||
|
check(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_perFrameStorage.m_textureUploadCommandAllocator, nullptr, IID_PPV_ARGS(&commandList)));
|
||||||
|
|
||||||
size_t heightInBlocks = (m_textures[i].GetHeight() + blockHeightInPixel - 1) / blockHeightInPixel;
|
size_t heightInBlocks = (m_textures[i].GetHeight() + blockHeightInPixel - 1) / blockHeightInPixel;
|
||||||
size_t widthInBlocks = (m_textures[i].GetWidth() + blockWidthInPixel - 1) / blockWidthInPixel;
|
size_t widthInBlocks = (m_textures[i].GetWidth() + blockWidthInPixel - 1) / blockWidthInPixel;
|
||||||
// Multiple of 256
|
// Multiple of 256
|
||||||
size_t rowPitch = blockSizeInByte * widthInBlocks;
|
size_t rowPitch = blockSizeInByte * widthInBlocks;
|
||||||
rowPitch = (rowPitch + 255) & ~255;
|
rowPitch = (rowPitch + 255) & ~255;
|
||||||
|
|
||||||
|
ID3D12Resource *Texture;
|
||||||
ID3D12Resource *Texture, *vramTexture;
|
|
||||||
size_t textureSize = rowPitch * heightInBlocks;
|
size_t textureSize = rowPitch * heightInBlocks;
|
||||||
|
|
||||||
check(m_device->CreatePlacedResource(
|
check(m_device->CreatePlacedResource(
|
||||||
|
@ -165,7 +176,6 @@ size_t D3D12GSRender::UploadTextures()
|
||||||
IID_PPV_ARGS(&Texture)
|
IID_PPV_ARGS(&Texture)
|
||||||
));
|
));
|
||||||
|
|
||||||
const u32 texaddr = GetAddress(m_textures[i].GetOffset(), m_textures[i].GetLocation());
|
|
||||||
auto pixels = vm::get_ptr<const u8>(texaddr);
|
auto pixels = vm::get_ptr<const u8>(texaddr);
|
||||||
void *textureData;
|
void *textureData;
|
||||||
check(Texture->Map(0, nullptr, (void**)&textureData));
|
check(Texture->Map(0, nullptr, (void**)&textureData));
|
||||||
|
@ -210,7 +220,6 @@ size_t D3D12GSRender::UploadTextures()
|
||||||
m_perFrameStorage.m_inflightResources.push_back(Texture);
|
m_perFrameStorage.m_inflightResources.push_back(Texture);
|
||||||
m_perFrameStorage.m_inflightResources.push_back(vramTexture);
|
m_perFrameStorage.m_inflightResources.push_back(vramTexture);
|
||||||
|
|
||||||
|
|
||||||
D3D12_TEXTURE_COPY_LOCATION dst = {}, src = {};
|
D3D12_TEXTURE_COPY_LOCATION dst = {}, src = {};
|
||||||
dst.pResource = vramTexture;
|
dst.pResource = vramTexture;
|
||||||
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||||
|
@ -231,6 +240,11 @@ size_t D3D12GSRender::UploadTextures()
|
||||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_GENERIC_READ;
|
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||||
commandList->ResourceBarrier(1, &barrier);
|
commandList->ResourceBarrier(1, &barrier);
|
||||||
|
|
||||||
|
commandList->Close();
|
||||||
|
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList);
|
||||||
|
m_perFrameStorage.m_inflightCommandList.push_back(commandList);
|
||||||
|
}
|
||||||
|
|
||||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
||||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||||
srvDesc.Format = dxgiFormat;
|
srvDesc.Format = dxgiFormat;
|
||||||
|
@ -274,10 +288,6 @@ size_t D3D12GSRender::UploadTextures()
|
||||||
Handle.ptr += (m_perFrameStorage.m_currentTextureIndex + usedTexture) * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
Handle.ptr += (m_perFrameStorage.m_currentTextureIndex + usedTexture) * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||||
m_device->CreateSampler(&samplerDesc, Handle);
|
m_device->CreateSampler(&samplerDesc, Handle);
|
||||||
|
|
||||||
commandList->Close();
|
|
||||||
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList);
|
|
||||||
m_perFrameStorage.m_inflightCommandList.push_back(commandList);
|
|
||||||
|
|
||||||
usedTexture++;
|
usedTexture++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue