From 752dd4761d292c94623b166403733847c198162a Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 30 Oct 2017 23:11:46 +1000 Subject: [PATCH] D3D: Use new readback methods for EFB2RAM --- .../VideoBackends/D3D/PSTextureEncoder.cpp | 95 ++++++------------- .../Core/VideoBackends/D3D/PSTextureEncoder.h | 14 +-- 2 files changed, 37 insertions(+), 72 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp index 4fcce4ef03..d97cd2bc35 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp @@ -4,17 +4,21 @@ #include "VideoBackends/D3D/PSTextureEncoder.h" +#include "Common/Assert.h" #include "Common/Logging/Log.h" #include "Core/HW/Memmap.h" #include "VideoBackends/D3D/D3DBase.h" #include "VideoBackends/D3D/D3DShader.h" #include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/D3DUtil.h" +#include "VideoBackends/D3D/DXTexture.h" #include "VideoBackends/D3D/FramebufferManager.h" #include "VideoBackends/D3D/Render.h" #include "VideoBackends/D3D/TextureCache.h" #include "VideoBackends/D3D/VertexShaderCache.h" +#include "VideoCommon/AbstractStagingTexture.h" +#include "VideoCommon/AbstractTexture.h" #include "VideoCommon/TextureConversionShader.h" #include "VideoCommon/VideoCommon.h" @@ -31,76 +35,41 @@ struct EFBEncodeParams }; PSTextureEncoder::PSTextureEncoder() - : m_ready(false), m_out(nullptr), m_outRTV(nullptr), m_outStage(nullptr), - m_encodeParams(nullptr) { } +PSTextureEncoder::~PSTextureEncoder() = default; + void PSTextureEncoder::Init() { - m_ready = false; - - HRESULT hr; - - // Create output texture RGBA format - // TODO: This Texture is overly large and parts of it are unused - // EFB2RAM copies use max (EFB_WIDTH * 4) by (EFB_HEIGHT / 4) - // XFB2RAM copies use max (EFB_WIDTH / 2) by (EFB_HEIGHT) - D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_B8G8R8A8_UNORM, EFB_WIDTH * 4, 1024, - 1, 1, D3D11_BIND_RENDER_TARGET); - hr = D3D::device->CreateTexture2D(&t2dd, nullptr, &m_out); - CHECK(SUCCEEDED(hr), "create efb encode output texture"); - D3D::SetDebugObjectName(m_out, "efb encoder output texture"); - - // Create output render target view - D3D11_RENDER_TARGET_VIEW_DESC rtvd = CD3D11_RENDER_TARGET_VIEW_DESC( - m_out, D3D11_RTV_DIMENSION_TEXTURE2D, DXGI_FORMAT_B8G8R8A8_UNORM); - hr = D3D::device->CreateRenderTargetView(m_out, &rtvd, &m_outRTV); - CHECK(SUCCEEDED(hr), "create efb encode output render target view"); - D3D::SetDebugObjectName(m_outRTV, "efb encoder output rtv"); - - // Create output staging buffer - t2dd.Usage = D3D11_USAGE_STAGING; - t2dd.BindFlags = 0; - t2dd.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - hr = D3D::device->CreateTexture2D(&t2dd, nullptr, &m_outStage); - CHECK(SUCCEEDED(hr), "create efb encode output staging buffer"); - D3D::SetDebugObjectName(m_outStage, "efb encoder output staging buffer"); + // TODO: Move this to a constant somewhere in common. + TextureConfig encoding_texture_config(EFB_WIDTH * 4, 1024, 1, 1, AbstractTextureFormat::BGRA8, + true); + m_encoding_render_texture = g_renderer->CreateTexture(encoding_texture_config); + m_encoding_readback_texture = + g_renderer->CreateStagingTexture(StagingTextureType::Readback, encoding_texture_config); + _assert_(m_encoding_render_texture && m_encoding_readback_texture); // Create constant buffer for uploading data to shaders D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(EFBEncodeParams), D3D11_BIND_CONSTANT_BUFFER); - hr = D3D::device->CreateBuffer(&bd, nullptr, &m_encodeParams); + HRESULT hr = D3D::device->CreateBuffer(&bd, nullptr, &m_encode_params); CHECK(SUCCEEDED(hr), "create efb encode params buffer"); - D3D::SetDebugObjectName(m_encodeParams, "efb encoder params buffer"); - - m_ready = true; + D3D::SetDebugObjectName(m_encode_params, "efb encoder params buffer"); } void PSTextureEncoder::Shutdown() { - m_ready = false; - for (auto& it : m_encoding_shaders) - { SAFE_RELEASE(it.second); - } m_encoding_shaders.clear(); - SAFE_RELEASE(m_encodeParams); - SAFE_RELEASE(m_outStage); - SAFE_RELEASE(m_outRTV); - SAFE_RELEASE(m_out); + SAFE_RELEASE(m_encode_params); } void PSTextureEncoder::Encode(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half) { - if (!m_ready) // Make sure we initialized OK - return; - - HRESULT hr; - // Resolve MSAA targets before copying. // FIXME: Instead of resolving EFB, it would be better to pick out a // single sample from each pixel. The game may break if it isn't @@ -122,7 +91,10 @@ void PSTextureEncoder::Encode(u8* dst, const EFBCopyParams& params, u32 native_w constexpr EFBRectangle fullSrcRect(0, 0, EFB_WIDTH, EFB_HEIGHT); TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(fullSrcRect); - D3D::context->OMSetRenderTargets(1, &m_outRTV, nullptr); + D3D::context->OMSetRenderTargets( + 1, + &static_cast(m_encoding_render_texture.get())->GetRawTexIdentifier()->GetRTV(), + nullptr); EFBEncodeParams encode_params; encode_params.SrcLeft = src_rect.left; @@ -130,8 +102,8 @@ void PSTextureEncoder::Encode(u8* dst, const EFBCopyParams& params, u32 native_w encode_params.DestWidth = native_width; encode_params.ScaleFactor = scale_by_half ? 2 : 1; encode_params.y_scale = params.y_scale; - D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, &encode_params, 0, 0); - D3D::stateman->SetPixelConstants(m_encodeParams); + D3D::context->UpdateSubresource(m_encode_params, 0, nullptr, &encode_params, 0, 0); + D3D::stateman->SetPixelConstants(m_encode_params); // We also linear filtering for both box filtering and downsampling higher resolutions to 1x // TODO: This only produces perfect downsampling for 2x IR, other resolutions will need more @@ -148,24 +120,15 @@ void PSTextureEncoder::Encode(u8* dst, const EFBCopyParams& params, u32 native_w VertexShaderCache::GetSimpleInputLayout()); // Copy to staging buffer - D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, words_per_row, num_blocks_y, 1); - D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox); - - // Transfer staging buffer to GameCube/Wii RAM - D3D11_MAPPED_SUBRESOURCE map = {0}; - hr = D3D::context->Map(m_outStage, 0, D3D11_MAP_READ, 0, &map); - CHECK(SUCCEEDED(hr), "map staging buffer (0x%x)", hr); - - u8* src = (u8*)map.pData; - u32 readStride = std::min(bytes_per_row, map.RowPitch); - for (unsigned int y = 0; y < num_blocks_y; ++y) + MathUtil::Rectangle copy_rect(0, 0, words_per_row, num_blocks_y); + m_encoding_readback_texture->CopyFromTexture(m_encoding_render_texture.get(), copy_rect, 0, 0, + copy_rect); + m_encoding_readback_texture->Flush(); + if (m_encoding_readback_texture->Map()) { - memcpy(dst, src, readStride); - dst += memory_stride; - src += map.RowPitch; + m_encoding_readback_texture->ReadTexels(copy_rect, dst, memory_stride); + m_encoding_readback_texture->Unmap(); } - - D3D::context->Unmap(m_outStage, 0); } // Restore API diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.h b/Source/Core/VideoBackends/D3D/PSTextureEncoder.h index 738f1b2d3e..7c45970d19 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.h +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.h @@ -5,11 +5,15 @@ #pragma once #include +#include #include "Common/CommonTypes.h" #include "VideoCommon/TextureConversionShader.h" #include "VideoCommon/VideoCommon.h" +class AbstractTexture; +class AbstractStagingTexture; + struct ID3D11Texture2D; struct ID3D11RenderTargetView; struct ID3D11Buffer; @@ -29,6 +33,7 @@ class PSTextureEncoder final { public: PSTextureEncoder(); + ~PSTextureEncoder(); void Init(); void Shutdown(); @@ -39,12 +44,9 @@ public: private: ID3D11PixelShader* GetEncodingPixelShader(const EFBCopyParams& params); - bool m_ready; - - ID3D11Texture2D* m_out; - ID3D11RenderTargetView* m_outRTV; - ID3D11Texture2D* m_outStage; - ID3D11Buffer* m_encodeParams; + ID3D11Buffer* m_encode_params = nullptr; + std::unique_ptr m_encoding_render_texture; + std::unique_ptr m_encoding_readback_texture; std::map m_encoding_shaders; }; }