diff options
| author | Pierre Bourdon <delroth@gmail.com> | 2016-06-24 10:43:46 +0200 |
|---|---|---|
| committer | Pierre Bourdon <delroth@gmail.com> | 2016-06-24 10:43:46 +0200 |
| commit | 3570c7f03a2aa90aa634f96c0af1969af610f14d (patch) | |
| tree | 4252e03c0e853ba7cffe022937698c854ad0eaa9 /Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp | |
| parent | 2115e8a4a6814e32107b5205ff5c95bbd3c6e99c (diff) | |
Reformat all the things. Have fun with merge conflicts.
Diffstat (limited to 'Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp | 377 |
1 files changed, 187 insertions, 190 deletions
diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp index 5698077817..ad7d7146f0 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp @@ -2,13 +2,13 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include "VideoBackends/D3D/PSTextureEncoder.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/FramebufferManager.h" -#include "VideoBackends/D3D/PSTextureEncoder.h" #include "VideoBackends/D3D/Render.h" #include "VideoBackends/D3D/TextureCache.h" #include "VideoBackends/D3D/VertexShaderCache.h" @@ -17,214 +17,211 @@ namespace DX11 { - struct EFBEncodeParams { - DWORD SrcLeft; - DWORD SrcTop; - DWORD DestWidth; - DWORD ScaleFactor; + DWORD SrcLeft; + DWORD SrcTop; + DWORD DestWidth; + DWORD ScaleFactor; }; PSTextureEncoder::PSTextureEncoder() - : m_ready(false), m_out(nullptr), m_outRTV(nullptr), m_outStage(nullptr), - m_encodeParams(nullptr) + : m_ready(false), m_out(nullptr), m_outRTV(nullptr), m_outStage(nullptr), + m_encodeParams(nullptr) { } void PSTextureEncoder::Init() { - m_ready = false; - - HRESULT hr; - - // Create output texture RGBA format - D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC( - DXGI_FORMAT_B8G8R8A8_UNORM, - EFB_WIDTH * 4, EFB_HEIGHT / 4, 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"); - - // 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); - CHECK(SUCCEEDED(hr), "create efb encode params buffer"); - D3D::SetDebugObjectName(m_encodeParams, "efb encoder params buffer"); - - m_ready = true; + m_ready = false; + + HRESULT hr; + + // Create output texture RGBA format + D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_B8G8R8A8_UNORM, EFB_WIDTH * 4, + EFB_HEIGHT / 4, 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"); + + // 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); + CHECK(SUCCEEDED(hr), "create efb encode params buffer"); + D3D::SetDebugObjectName(m_encodeParams, "efb encoder params buffer"); + + m_ready = true; } void PSTextureEncoder::Shutdown() { - m_ready = false; - - for (auto& it : m_staticShaders) - { - SAFE_RELEASE(it.second); - } - m_staticShaders.clear(); - - SAFE_RELEASE(m_encodeParams); - SAFE_RELEASE(m_outStage); - SAFE_RELEASE(m_outRTV); - SAFE_RELEASE(m_out); + m_ready = false; + + for (auto& it : m_staticShaders) + { + SAFE_RELEASE(it.second); + } + m_staticShaders.clear(); + + SAFE_RELEASE(m_encodeParams); + SAFE_RELEASE(m_outStage); + SAFE_RELEASE(m_outRTV); + SAFE_RELEASE(m_out); } -void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, - PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, - bool isIntensity, bool scaleByHalf) +void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, + u32 num_blocks_y, u32 memory_stride, PEControl::PixelFormat srcFormat, + const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf) { - if (!m_ready) // Make sure we initialized OK - return; - - HRESULT hr; - - // Resolve MSAA targets before copying. - ID3D11ShaderResourceView* pEFB = (srcFormat == PEControl::Z24) ? - FramebufferManager::GetResolvedEFBDepthTexture()->GetSRV() : - // 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 - // expecting the blurred edges around multisampled shapes. - FramebufferManager::GetResolvedEFBColorTexture()->GetSRV(); - - // Reset API - g_renderer->ResetAPIState(); - - // Set up all the state for EFB encoding - { - const u32 words_per_row = bytes_per_row / sizeof(u32); - - D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(words_per_row), FLOAT(num_blocks_y)); - D3D::context->RSSetViewports(1, &vp); - - constexpr EFBRectangle fullSrcRect(0, 0, EFB_WIDTH, EFB_HEIGHT); - TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(fullSrcRect); - - D3D::context->OMSetRenderTargets(1, &m_outRTV, nullptr); - - EFBEncodeParams params; - params.SrcLeft = srcRect.left; - params.SrcTop = srcRect.top; - params.DestWidth = native_width; - params.ScaleFactor = scaleByHalf ? 2 : 1; - D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, ¶ms, 0, 0); - D3D::stateman->SetPixelConstants(m_encodeParams); - - // Use linear filtering if (bScaleByHalf), use point filtering otherwise - if (scaleByHalf) - D3D::SetLinearCopySampler(); - else - D3D::SetPointCopySampler(); - - D3D::drawShadedTexQuad(pEFB, - targetRect.AsRECT(), - Renderer::GetTargetWidth(), - Renderer::GetTargetHeight(), - SetStaticShader(format, srcFormat, isIntensity, scaleByHalf), - VertexShaderCache::GetSimpleVertexShader(), - 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) - { - memcpy(dst, src, readStride); - dst += memory_stride; - src += map.RowPitch; - } - - D3D::context->Unmap(m_outStage, 0); - } - - // Restore API - g_renderer->RestoreAPIState(); - D3D::context->OMSetRenderTargets(1, - &FramebufferManager::GetEFBColorTexture()->GetRTV(), - FramebufferManager::GetEFBDepthTexture()->GetDSV()); + if (!m_ready) // Make sure we initialized OK + return; + + HRESULT hr; + + // Resolve MSAA targets before copying. + ID3D11ShaderResourceView* pEFB = + (srcFormat == PEControl::Z24) ? + FramebufferManager::GetResolvedEFBDepthTexture()->GetSRV() : + // 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 + // expecting the blurred edges around multisampled shapes. + FramebufferManager::GetResolvedEFBColorTexture()->GetSRV(); + + // Reset API + g_renderer->ResetAPIState(); + + // Set up all the state for EFB encoding + { + const u32 words_per_row = bytes_per_row / sizeof(u32); + + D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(words_per_row), FLOAT(num_blocks_y)); + D3D::context->RSSetViewports(1, &vp); + + constexpr EFBRectangle fullSrcRect(0, 0, EFB_WIDTH, EFB_HEIGHT); + TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(fullSrcRect); + + D3D::context->OMSetRenderTargets(1, &m_outRTV, nullptr); + + EFBEncodeParams params; + params.SrcLeft = srcRect.left; + params.SrcTop = srcRect.top; + params.DestWidth = native_width; + params.ScaleFactor = scaleByHalf ? 2 : 1; + D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, ¶ms, 0, 0); + D3D::stateman->SetPixelConstants(m_encodeParams); + + // Use linear filtering if (bScaleByHalf), use point filtering otherwise + if (scaleByHalf) + D3D::SetLinearCopySampler(); + else + D3D::SetPointCopySampler(); + + D3D::drawShadedTexQuad( + pEFB, targetRect.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), + SetStaticShader(format, srcFormat, isIntensity, scaleByHalf), + VertexShaderCache::GetSimpleVertexShader(), 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) + { + memcpy(dst, src, readStride); + dst += memory_stride; + src += map.RowPitch; + } + + D3D::context->Unmap(m_outStage, 0); + } + + // Restore API + g_renderer->RestoreAPIState(); + D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), + FramebufferManager::GetEFBDepthTexture()->GetDSV()); } -ID3D11PixelShader* PSTextureEncoder::SetStaticShader(unsigned int dstFormat, PEControl::PixelFormat srcFormat, - bool isIntensity, bool scaleByHalf) +ID3D11PixelShader* PSTextureEncoder::SetStaticShader(unsigned int dstFormat, + PEControl::PixelFormat srcFormat, + bool isIntensity, bool scaleByHalf) { - size_t fetchNum = static_cast<size_t>(srcFormat); - size_t scaledFetchNum = scaleByHalf ? 1 : 0; - size_t intensityNum = isIntensity ? 1 : 0; - size_t generatorNum = dstFormat; - - ComboKey key = MakeComboKey(dstFormat, srcFormat, isIntensity, scaleByHalf); - - ComboMap::iterator it = m_staticShaders.find(key); - if (it == m_staticShaders.end()) - { - INFO_LOG(VIDEO, "Compiling efb encoding shader for dstFormat 0x%X, srcFormat %d, isIntensity %d, scaleByHalf %d", - dstFormat, static_cast<int>(srcFormat), isIntensity ? 1 : 0, scaleByHalf ? 1 : 0); - - u32 format = dstFormat; - - if (srcFormat == PEControl::Z24) - { - format |= _GX_TF_ZTF; - if (dstFormat == 11) - format = GX_TF_Z16; - else if (format < GX_TF_Z8 || format > GX_TF_Z24X8) - format |= _GX_TF_CTF; - } - else - { - if (dstFormat > GX_TF_RGBA8 || (dstFormat < GX_TF_RGB565 && !isIntensity)) - format |= _GX_TF_CTF; - } - - D3DBlob* bytecode = nullptr; - const char* shader = TextureConversionShader::GenerateEncodingShader(format, API_D3D); - if (!D3D::CompilePixelShader(shader, &bytecode)) - { - WARN_LOG(VIDEO, "EFB encoder shader for dstFormat 0x%X, srcFormat %d, isIntensity %d, scaleByHalf %d failed to compile", - dstFormat, static_cast<int>(srcFormat), isIntensity ? 1 : 0, scaleByHalf ? 1 : 0); - m_staticShaders[key] = nullptr; - return nullptr; - } - - ID3D11PixelShader* newShader; - HRESULT hr = D3D::device->CreatePixelShader(bytecode->Data(), bytecode->Size(), nullptr, &newShader); - CHECK(SUCCEEDED(hr), "create efb encoder pixel shader"); - - char debugName[255] = {}; - sprintf_s(debugName, "efb encoder pixel shader (dst:%d, src:%d, intensity:%d, scale:%d)", - dstFormat, srcFormat, isIntensity, scaleByHalf); - D3D::SetDebugObjectName(newShader, debugName); - - it = m_staticShaders.emplace(key, newShader).first; - bytecode->Release(); - } - - return it->second; + size_t fetchNum = static_cast<size_t>(srcFormat); + size_t scaledFetchNum = scaleByHalf ? 1 : 0; + size_t intensityNum = isIntensity ? 1 : 0; + size_t generatorNum = dstFormat; + + ComboKey key = MakeComboKey(dstFormat, srcFormat, isIntensity, scaleByHalf); + + ComboMap::iterator it = m_staticShaders.find(key); + if (it == m_staticShaders.end()) + { + INFO_LOG(VIDEO, "Compiling efb encoding shader for dstFormat 0x%X, srcFormat %d, isIntensity " + "%d, scaleByHalf %d", + dstFormat, static_cast<int>(srcFormat), isIntensity ? 1 : 0, scaleByHalf ? 1 : 0); + + u32 format = dstFormat; + + if (srcFormat == PEControl::Z24) + { + format |= _GX_TF_ZTF; + if (dstFormat == 11) + format = GX_TF_Z16; + else if (format < GX_TF_Z8 || format > GX_TF_Z24X8) + format |= _GX_TF_CTF; + } + else + { + if (dstFormat > GX_TF_RGBA8 || (dstFormat < GX_TF_RGB565 && !isIntensity)) + format |= _GX_TF_CTF; + } + + D3DBlob* bytecode = nullptr; + const char* shader = TextureConversionShader::GenerateEncodingShader(format, API_D3D); + if (!D3D::CompilePixelShader(shader, &bytecode)) + { + WARN_LOG(VIDEO, "EFB encoder shader for dstFormat 0x%X, srcFormat %d, isIntensity %d, " + "scaleByHalf %d failed to compile", + dstFormat, static_cast<int>(srcFormat), isIntensity ? 1 : 0, scaleByHalf ? 1 : 0); + m_staticShaders[key] = nullptr; + return nullptr; + } + + ID3D11PixelShader* newShader; + HRESULT hr = + D3D::device->CreatePixelShader(bytecode->Data(), bytecode->Size(), nullptr, &newShader); + CHECK(SUCCEEDED(hr), "create efb encoder pixel shader"); + + char debugName[255] = {}; + sprintf_s(debugName, "efb encoder pixel shader (dst:%d, src:%d, intensity:%d, scale:%d)", + dstFormat, srcFormat, isIntensity, scaleByHalf); + D3D::SetDebugObjectName(newShader, debugName); + + it = m_staticShaders.emplace(key, newShader).first; + bytecode->Release(); + } + + return it->second; } - } |
