mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 03:55:32 +00: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)
|
||||
{
|
||||
m_queueCompletion = 0;
|
||||
// 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_textureUploadCommandAllocator));
|
||||
|
@ -345,6 +344,57 @@ void D3D12GSRender::Close()
|
|||
|
||||
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)
|
||||
{
|
||||
|
||||
|
@ -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->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()
|
||||
{
|
||||
InitDrawBuffers();
|
||||
|
||||
ID3D12GraphicsCommandList *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);
|
||||
|
@ -681,8 +738,6 @@ void D3D12GSRender::ExecCMD()
|
|||
|
||||
m_perFrameStorage.m_currentTextureIndex += usedTexture;
|
||||
|
||||
InitDrawBuffers();
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE *DepthStencilHandle = &m_fbo->getDSVCPUHandle();
|
||||
switch (m_surface_color_target)
|
||||
{
|
||||
|
@ -1123,6 +1178,7 @@ void D3D12GSRender::Flip()
|
|||
WaitForSingleObject(handle, INFINITE);
|
||||
CloseHandle(handle);
|
||||
m_perFrameStorage.Reset();
|
||||
m_texturesRTTs.clear();
|
||||
|
||||
m_frame->Flip(nullptr);
|
||||
}
|
||||
|
|
|
@ -47,7 +47,8 @@ void SetGetD3DGSFrameCallback(GetGSFrameCb2 value);
|
|||
class D3D12GSRender : public GSRender
|
||||
{
|
||||
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;
|
||||
|
||||
PipelineStateObjectCache m_cachePSO;
|
||||
|
@ -85,9 +86,6 @@ private:
|
|||
ID3D12DescriptorHeap *m_samplerDescriptorHeap;
|
||||
size_t m_currentTextureIndex;
|
||||
|
||||
// Fence
|
||||
HANDLE m_queueCompletion;
|
||||
|
||||
void Reset();
|
||||
void Init(ID3D12Device *device);
|
||||
void Release();
|
||||
|
|
|
@ -25,5 +25,7 @@ public:
|
|||
D3D12_CPU_DESCRIPTOR_HANDLE getDSVCPUHandle() const;
|
||||
ID3D12Resource *getRenderTargetTexture(u8 Id) 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
|
|
@ -90,13 +90,13 @@ size_t D3D12GSRender::UploadTextures()
|
|||
if (!m_textures[i].IsEnabled()) continue;
|
||||
size_t w = m_textures[i].GetWidth(), h = m_textures[i].GetHeight();
|
||||
|
||||
// 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)));
|
||||
const u32 texaddr = GetAddress(m_textures[i].GetOffset(), m_textures[i].GetLocation());
|
||||
u32 address = GetAddress(m_surface_offset_a, m_context_dma_color_a - 0xfeed0000);
|
||||
|
||||
DXGI_FORMAT dxgiFormat;
|
||||
size_t blockSizeInByte, blockWidthInPixel, blockHeightInPixel;
|
||||
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);
|
||||
switch (format)
|
||||
{
|
||||
|
@ -146,90 +146,104 @@ size_t D3D12GSRender::UploadTextures()
|
|||
break;
|
||||
}
|
||||
|
||||
size_t heightInBlocks = (m_textures[i].GetHeight() + blockHeightInPixel - 1) / blockHeightInPixel;
|
||||
size_t widthInBlocks = (m_textures[i].GetWidth() + blockWidthInPixel - 1) / blockWidthInPixel;
|
||||
// Multiple of 256
|
||||
size_t rowPitch = blockSizeInByte * widthInBlocks;
|
||||
rowPitch = (rowPitch + 255) & ~255;
|
||||
|
||||
|
||||
ID3D12Resource *Texture, *vramTexture;
|
||||
size_t textureSize = rowPitch * heightInBlocks;
|
||||
|
||||
check(m_device->CreatePlacedResource(
|
||||
m_perFrameStorage.m_uploadTextureHeap,
|
||||
m_perFrameStorage.m_currentStorageOffset,
|
||||
&getBufferResourceDesc(textureSize),
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&Texture)
|
||||
));
|
||||
|
||||
const u32 texaddr = GetAddress(m_textures[i].GetOffset(), m_textures[i].GetLocation());
|
||||
auto pixels = vm::get_ptr<const u8>(texaddr);
|
||||
void *textureData;
|
||||
check(Texture->Map(0, nullptr, (void**)&textureData));
|
||||
|
||||
// Upload with correct rowpitch
|
||||
for (unsigned row = 0; row < heightInBlocks; row++)
|
||||
ID3D12Resource *vramTexture;
|
||||
std::unordered_map<u32, Microsoft::WRL::ComPtr<ID3D12Resource> >::const_iterator It = m_texturesRTTs.find(address);
|
||||
if (It != m_texturesRTTs.end())
|
||||
{
|
||||
size_t m_texture_pitch = m_textures[i].m_pitch;
|
||||
if (!m_texture_pitch) m_texture_pitch = rowPitch;
|
||||
if (format == CELL_GCM_TEXTURE_A8R8G8B8 && is_swizzled)
|
||||
{
|
||||
u32 *src, *dst;
|
||||
u32 log2width, log2height;
|
||||
|
||||
src = (u32*)pixels;
|
||||
dst = (u32*)textureData;
|
||||
|
||||
log2width = (u32)(logf(m_textures[i].GetWidth()) / logf(2.f));
|
||||
log2height = (u32)(logf(m_textures[i].GetHeight()) / logf(2.f));
|
||||
|
||||
for (int j = 0; j < m_textures[i].GetWidth(); j++)
|
||||
{
|
||||
dst[(row * rowPitch / 4) + j] = src[LinearToSwizzleAddress(j, i, 0, log2width, log2height, 0)];
|
||||
}
|
||||
}
|
||||
else
|
||||
streamToBuffer((char*)textureData + row * rowPitch, (char*)pixels + row * m_texture_pitch, m_texture_pitch);
|
||||
vramTexture = It->second.Get();
|
||||
}
|
||||
Texture->Unmap(0, nullptr);
|
||||
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)));
|
||||
|
||||
check(m_device->CreatePlacedResource(
|
||||
m_perFrameStorage.m_textureStorage,
|
||||
m_perFrameStorage.m_currentStorageOffset,
|
||||
&getTexture2DResourceDesc(m_textures[i].GetWidth(), m_textures[i].GetHeight(), dxgiFormat),
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&vramTexture)
|
||||
));
|
||||
size_t heightInBlocks = (m_textures[i].GetHeight() + blockHeightInPixel - 1) / blockHeightInPixel;
|
||||
size_t widthInBlocks = (m_textures[i].GetWidth() + blockWidthInPixel - 1) / blockWidthInPixel;
|
||||
// Multiple of 256
|
||||
size_t rowPitch = blockSizeInByte * widthInBlocks;
|
||||
rowPitch = (rowPitch + 255) & ~255;
|
||||
|
||||
m_perFrameStorage.m_currentStorageOffset += textureSize;
|
||||
m_perFrameStorage.m_currentStorageOffset = (m_perFrameStorage.m_currentStorageOffset + 65536 - 1) & ~65535;
|
||||
m_perFrameStorage.m_inflightResources.push_back(Texture);
|
||||
m_perFrameStorage.m_inflightResources.push_back(vramTexture);
|
||||
ID3D12Resource *Texture;
|
||||
size_t textureSize = rowPitch * heightInBlocks;
|
||||
|
||||
check(m_device->CreatePlacedResource(
|
||||
m_perFrameStorage.m_uploadTextureHeap,
|
||||
m_perFrameStorage.m_currentStorageOffset,
|
||||
&getBufferResourceDesc(textureSize),
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&Texture)
|
||||
));
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION dst = {}, src = {};
|
||||
dst.pResource = vramTexture;
|
||||
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
src.pResource = Texture;
|
||||
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
src.PlacedFootprint.Footprint.Depth = 1;
|
||||
src.PlacedFootprint.Footprint.Width = m_textures[i].GetWidth();
|
||||
src.PlacedFootprint.Footprint.Height = m_textures[i].GetHeight();
|
||||
src.PlacedFootprint.Footprint.RowPitch = (UINT)rowPitch;
|
||||
src.PlacedFootprint.Footprint.Format = dxgiFormat;
|
||||
auto pixels = vm::get_ptr<const u8>(texaddr);
|
||||
void *textureData;
|
||||
check(Texture->Map(0, nullptr, (void**)&textureData));
|
||||
|
||||
commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
|
||||
// Upload with correct rowpitch
|
||||
for (unsigned row = 0; row < heightInBlocks; row++)
|
||||
{
|
||||
size_t m_texture_pitch = m_textures[i].m_pitch;
|
||||
if (!m_texture_pitch) m_texture_pitch = rowPitch;
|
||||
if (format == CELL_GCM_TEXTURE_A8R8G8B8 && is_swizzled)
|
||||
{
|
||||
u32 *src, *dst;
|
||||
u32 log2width, log2height;
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Transition.pResource = vramTexture;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||
commandList->ResourceBarrier(1, &barrier);
|
||||
src = (u32*)pixels;
|
||||
dst = (u32*)textureData;
|
||||
|
||||
log2width = (u32)(logf(m_textures[i].GetWidth()) / logf(2.f));
|
||||
log2height = (u32)(logf(m_textures[i].GetHeight()) / logf(2.f));
|
||||
|
||||
for (int j = 0; j < m_textures[i].GetWidth(); j++)
|
||||
{
|
||||
dst[(row * rowPitch / 4) + j] = src[LinearToSwizzleAddress(j, i, 0, log2width, log2height, 0)];
|
||||
}
|
||||
}
|
||||
else
|
||||
streamToBuffer((char*)textureData + row * rowPitch, (char*)pixels + row * m_texture_pitch, m_texture_pitch);
|
||||
}
|
||||
Texture->Unmap(0, nullptr);
|
||||
|
||||
check(m_device->CreatePlacedResource(
|
||||
m_perFrameStorage.m_textureStorage,
|
||||
m_perFrameStorage.m_currentStorageOffset,
|
||||
&getTexture2DResourceDesc(m_textures[i].GetWidth(), m_textures[i].GetHeight(), dxgiFormat),
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&vramTexture)
|
||||
));
|
||||
|
||||
m_perFrameStorage.m_currentStorageOffset += textureSize;
|
||||
m_perFrameStorage.m_currentStorageOffset = (m_perFrameStorage.m_currentStorageOffset + 65536 - 1) & ~65535;
|
||||
m_perFrameStorage.m_inflightResources.push_back(Texture);
|
||||
m_perFrameStorage.m_inflightResources.push_back(vramTexture);
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION dst = {}, src = {};
|
||||
dst.pResource = vramTexture;
|
||||
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
src.pResource = Texture;
|
||||
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
src.PlacedFootprint.Footprint.Depth = 1;
|
||||
src.PlacedFootprint.Footprint.Width = m_textures[i].GetWidth();
|
||||
src.PlacedFootprint.Footprint.Height = m_textures[i].GetHeight();
|
||||
src.PlacedFootprint.Footprint.RowPitch = (UINT)rowPitch;
|
||||
src.PlacedFootprint.Footprint.Format = dxgiFormat;
|
||||
|
||||
commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Transition.pResource = vramTexture;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||
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 = {};
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
|
@ -274,10 +288,6 @@ size_t D3D12GSRender::UploadTextures()
|
|||
Handle.ptr += (m_perFrameStorage.m_currentTextureIndex + usedTexture) * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
m_device->CreateSampler(&samplerDesc, Handle);
|
||||
|
||||
commandList->Close();
|
||||
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList);
|
||||
m_perFrameStorage.m_inflightCommandList.push_back(commandList);
|
||||
|
||||
usedTexture++;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue