mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 21:30:19 -06:00
Reformat all the things. Have fun with merge conflicts.
This commit is contained in:
@ -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;
|
||||
m_ready = false;
|
||||
|
||||
HRESULT hr;
|
||||
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 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 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 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");
|
||||
// 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 = true;
|
||||
}
|
||||
|
||||
void PSTextureEncoder::Shutdown()
|
||||
{
|
||||
m_ready = false;
|
||||
m_ready = false;
|
||||
|
||||
for (auto& it : m_staticShaders)
|
||||
{
|
||||
SAFE_RELEASE(it.second);
|
||||
}
|
||||
m_staticShaders.clear();
|
||||
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);
|
||||
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;
|
||||
if (!m_ready) // Make sure we initialized OK
|
||||
return;
|
||||
|
||||
HRESULT hr;
|
||||
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();
|
||||
// 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();
|
||||
// Reset API
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
// Set up all the state for EFB encoding
|
||||
{
|
||||
const u32 words_per_row = bytes_per_row / sizeof(u32);
|
||||
// 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);
|
||||
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);
|
||||
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, &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);
|
||||
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();
|
||||
// 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());
|
||||
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);
|
||||
// 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);
|
||||
// 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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
D3D::context->Unmap(m_outStage, 0);
|
||||
}
|
||||
|
||||
// Restore API
|
||||
g_renderer->RestoreAPIState();
|
||||
D3D::context->OMSetRenderTargets(1,
|
||||
&FramebufferManager::GetEFBColorTexture()->GetRTV(),
|
||||
FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||
// 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;
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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");
|
||||
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);
|
||||
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();
|
||||
}
|
||||
it = m_staticShaders.emplace(key, newShader).first;
|
||||
bytecode->Release();
|
||||
}
|
||||
|
||||
return it->second;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user