diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 4c39ca7152..3fdf445576 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -50,6 +50,7 @@ D3D12GSRender::D3D12GSRender() // Create a global command allocator m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator)); + m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_textureUploadCommandAllocator)); m_frame = GetGSFrame(); @@ -708,100 +709,7 @@ void D3D12GSRender::ExecCMD() commandList->SetGraphicsRootDescriptorTable(1, Handle); commandList->SetPipelineState(m_PSO); - - size_t usedTexture = 0; - - for (u32 i = 0; i < m_textures_count; ++i) - { - if (!m_textures[i].IsEnabled()) continue; - ID3D12Resource *Texture, *vramTexture; - size_t textureSize = m_textures[i].GetWidth() * m_textures[i].GetHeight() * 4; - D3D12_RESOURCE_DESC textureDesc = {}; - textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - textureDesc.Width = textureSize; - textureDesc.Height = 1; - textureDesc.DepthOrArraySize = 1; - textureDesc.SampleDesc.Count = 1; - textureDesc.MipLevels = 1; - textureDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - check(m_device->CreatePlacedResource( - m_uploadTextureHeap, - m_currentStorageOffset, - &textureDesc, - 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(texaddr); - void *textureData; - check(Texture->Map(0, nullptr, (void**)&textureData)); - memcpy(textureData, pixels, textureSize); - Texture->Unmap(0, nullptr); - - D3D12_RESOURCE_DESC vramTextureDesc = {}; - vramTextureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - vramTextureDesc.Width = m_textures[i].GetWidth(); - vramTextureDesc.Height = m_textures[i].GetHeight(); - vramTextureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - vramTextureDesc.DepthOrArraySize = 1; - vramTextureDesc.SampleDesc.Count = 1; - vramTextureDesc.MipLevels = 1; - check(m_device->CreatePlacedResource( - m_textureStorage, - m_currentStorageOffset, - &vramTextureDesc, - D3D12_RESOURCE_STATE_COPY_DEST, - nullptr, - IID_PPV_ARGS(&vramTexture) - )); - - m_currentStorageOffset += textureSize; - m_currentStorageOffset = (m_currentStorageOffset + 65536 - 1) & ~65535; - - 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 = m_textures[i].GetWidth() * 4; - src.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - - 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); - - D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; - srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.Texture2D.MipLevels = 1; - srvDesc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0); - D3D12_CPU_DESCRIPTOR_HANDLE Handle = m_textureDescriptorsHeap->GetCPUDescriptorHandleForHeapStart(); - Handle.ptr += (m_currentTextureIndex + usedTexture) * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - m_device->CreateShaderResourceView(vramTexture, &srvDesc, Handle); - - // TODO : Correctly define sampler - D3D12_SAMPLER_DESC samplerDesc = {}; - samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; - samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; - samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; - samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; - Handle = m_samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); - Handle.ptr += (m_currentTextureIndex + usedTexture) * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - m_device->CreateSampler(&samplerDesc, Handle); - - usedTexture++; - } - + size_t usedTexture = UploadTextures(); Handle = m_textureDescriptorsHeap->GetGPUDescriptorHandleForHeapStart(); Handle.ptr += m_currentTextureIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); commandList->SetDescriptorHeaps(1, &m_textureDescriptorsHeap); @@ -1283,6 +1191,7 @@ void D3D12GSRender::Flip() WaitForSingleObject(gfxqueuecompletion, INFINITE); CloseHandle(gfxqueuecompletion); m_commandAllocator->Reset(); + m_textureUploadCommandAllocator->Reset(); for (ID3D12GraphicsCommandList *gfxCommandList : m_inflightCommandList) gfxCommandList->Release(); m_inflightCommandList.clear(); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index 8b9b3f719a..aee262ec41 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -50,6 +50,7 @@ private: ID3D12PipelineState *m_PSO; ID3D12RootSignature *m_rootSignature; + ID3D12CommandAllocator *m_textureUploadCommandAllocator; ID3D12Heap *m_uploadTextureHeap, *m_textureStorage; size_t m_currentStorageOffset; ID3D12DescriptorHeap *m_textureDescriptorsHeap; @@ -101,6 +102,10 @@ private: void setScaleOffset(); void FillVertexShaderConstantsBuffer(); void FillPixelShaderConstantsBuffer(); + /** + * returns the number of texture uploaded + */ + size_t UploadTextures(); /*void DisableVertexData(); void WriteBuffers(); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp new file mode 100644 index 0000000000..7cfe423087 --- /dev/null +++ b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp @@ -0,0 +1,118 @@ +#include "stdafx.h" +#if defined(DX12_SUPPORT) +#include "D3D12GSRender.h" +// For clarity this code deals with texture but belongs to D3D12GSRender class + +static void check(HRESULT hr) +{ + if (hr != 0) + abort(); +} + +size_t D3D12GSRender::UploadTextures() +{ + size_t usedTexture = 0; + + for (u32 i = 0; i < m_textures_count; ++i) + { + if (!m_textures[i].IsEnabled()) continue; + + // Upload at each iteration to take advantage of overlapping transfer + ID3D12GraphicsCommandList *commandList; + check(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_textureUploadCommandAllocator, nullptr, IID_PPV_ARGS(&commandList))); + + ID3D12Resource *Texture, *vramTexture; + size_t textureSize = m_textures[i].GetWidth() * m_textures[i].GetHeight() * 4; + D3D12_RESOURCE_DESC textureDesc = {}; + textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + textureDesc.Width = textureSize; + textureDesc.Height = 1; + textureDesc.DepthOrArraySize = 1; + textureDesc.SampleDesc.Count = 1; + textureDesc.MipLevels = 1; + textureDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + check(m_device->CreatePlacedResource( + m_uploadTextureHeap, + m_currentStorageOffset, + &textureDesc, + 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(texaddr); + void *textureData; + check(Texture->Map(0, nullptr, (void**)&textureData)); + memcpy(textureData, pixels, textureSize); + Texture->Unmap(0, nullptr); + + D3D12_RESOURCE_DESC vramTextureDesc = {}; + vramTextureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + vramTextureDesc.Width = m_textures[i].GetWidth(); + vramTextureDesc.Height = m_textures[i].GetHeight(); + vramTextureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + vramTextureDesc.DepthOrArraySize = 1; + vramTextureDesc.SampleDesc.Count = 1; + vramTextureDesc.MipLevels = 1; + check(m_device->CreatePlacedResource( + m_textureStorage, + m_currentStorageOffset, + &vramTextureDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&vramTexture) + )); + + m_currentStorageOffset += textureSize; + m_currentStorageOffset = (m_currentStorageOffset + 65536 - 1) & ~65535; + + 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 = m_textures[i].GetWidth() * 4; + src.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + + 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); + + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srvDesc.Texture2D.MipLevels = 1; + srvDesc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0); + D3D12_CPU_DESCRIPTOR_HANDLE Handle = m_textureDescriptorsHeap->GetCPUDescriptorHandleForHeapStart(); + Handle.ptr += (m_currentTextureIndex + usedTexture) * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + m_device->CreateShaderResourceView(vramTexture, &srvDesc, Handle); + + // TODO : Correctly define sampler + D3D12_SAMPLER_DESC samplerDesc = {}; + samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; + samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + Handle = m_samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + Handle.ptr += (m_currentTextureIndex + usedTexture) * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + m_device->CreateSampler(&samplerDesc, Handle); + + commandList->Close(); + m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList); + + usedTexture++; + } + + return usedTexture; +} + +#endif \ No newline at end of file diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Texture.h b/rpcs3/Emu/RSX/D3D12/D3D12Texture.h new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/rpcs3/Emu/RSX/D3D12/D3D12Texture.h @@ -0,0 +1 @@ +#pragma once diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 88d174a108..8dccd27240 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -46,6 +46,7 @@ + @@ -509,6 +510,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 21b05ad7e5..204f2cc488 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -986,6 +986,9 @@ Emu\GPU\RSX\D3D12 + + Emu\GPU\RSX\D3D12 + @@ -1867,5 +1870,8 @@ Emu\GPU\RSX\D3D12 + + Emu\GPU\RSX\D3D12 + \ No newline at end of file