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:
vlj 2015-05-29 16:56:46 +02:00 committed by Vincent Lejeune
parent 3e11598941
commit 595392428d
4 changed files with 156 additions and 90 deletions

View file

@ -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(&copycmdlist)));
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**)&copycmdlist);
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);
} }

View file

@ -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();

View file

@ -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

View file

@ -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++;
} }