Skip to content

Commit

Permalink
Merge pull request #5202 from stenzek/efb-copy-source-format
Browse files Browse the repository at this point in the history
TextureConversionShader: Consider source format of EFB for EFB2RAM
  • Loading branch information
degasus committed Apr 11, 2017
2 parents 8ecc5e9 + 5e7bd03 commit 29344cb
Show file tree
Hide file tree
Showing 23 changed files with 351 additions and 384 deletions.
94 changes: 30 additions & 64 deletions Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,21 @@ void PSTextureEncoder::Shutdown()
{
m_ready = false;

for (auto& it : m_staticShaders)
for (auto& it : m_encoding_shaders)
{
SAFE_RELEASE(it.second);
}
m_staticShaders.clear();
m_encoding_shaders.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, bool is_depth_copy,
const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf)
void PSTextureEncoder::Encode(u8* dst, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half)
{
if (!m_ready) // Make sure we initialized OK
return;
Expand Down Expand Up @@ -120,26 +120,26 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p
D3D::context->OMSetRenderTargets(1, &m_outRTV, nullptr);

EFBEncodeParams params;
params.SrcLeft = srcRect.left;
params.SrcTop = srcRect.top;
params.SrcLeft = src_rect.left;
params.SrcTop = src_rect.top;
params.DestWidth = native_width;
params.ScaleFactor = scaleByHalf ? 2 : 1;
params.ScaleFactor = scale_by_half ? 2 : 1;
D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, &params, 0, 0);
D3D::stateman->SetPixelConstants(m_encodeParams);

// We also linear filtering for both box filtering and downsampling higher resolutions to 1x
// TODO: This only produces perfect downsampling for 1.5x and 2x IR, other resolution will
// need more complex down filtering to average all pixels and produce the correct result.
// Also, box filtering won't be correct for anything other than 1x IR
if (scaleByHalf || g_ActiveConfig.iEFBScale != SCALE_1X)
if (scale_by_half || g_ActiveConfig.iEFBScale != SCALE_1X)
D3D::SetLinearCopySampler();
else
D3D::SetPointCopySampler();

D3D::drawShadedTexQuad(
pEFB, targetRect.AsRECT(), g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(),
SetStaticShader(format, is_depth_copy, isIntensity, scaleByHalf),
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
D3D::drawShadedTexQuad(pEFB, targetRect.AsRECT(), g_renderer->GetTargetWidth(),
g_renderer->GetTargetHeight(), GetEncodingPixelShader(format),
VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout());

// Copy to staging buffer
D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, words_per_row, num_blocks_y, 1);
Expand Down Expand Up @@ -168,61 +168,27 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p
FramebufferManager::GetEFBDepthTexture()->GetDSV());
}

ID3D11PixelShader* PSTextureEncoder::SetStaticShader(unsigned int dstFormat, bool is_depth_copy,
bool isIntensity, bool scaleByHalf)
ID3D11PixelShader* PSTextureEncoder::GetEncodingPixelShader(const EFBCopyFormat& format)
{
ComboKey key = MakeComboKey(dstFormat, is_depth_copy, isIntensity, scaleByHalf);
auto iter = m_encoding_shaders.find(format);
if (iter != m_encoding_shaders.end())
return iter->second;

ComboMap::iterator it = m_staticShaders.find(key);
if (it == m_staticShaders.end())
D3DBlob* bytecode = nullptr;
const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::D3D);
if (!D3D::CompilePixelShader(shader, &bytecode))
{
INFO_LOG(VIDEO,
"Compiling efb encoding shader for dstFormat 0x%X, is_depth_copy %d, isIntensity "
"%d, scaleByHalf %d",
dstFormat, is_depth_copy, isIntensity ? 1 : 0, scaleByHalf ? 1 : 0);

u32 format = dstFormat;

if (is_depth_copy)
{
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, APIType::D3D);
if (!D3D::CompilePixelShader(shader, &bytecode))
{
WARN_LOG(VIDEO, "EFB encoder shader for dstFormat 0x%X, is_depth_copy %d, isIntensity %d, "
"scaleByHalf %d failed to compile",
dstFormat, is_depth_copy, 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, is_depth_copy:%d, intensity:%d, scale:%d)",
dstFormat, is_depth_copy, isIntensity, scaleByHalf);
D3D::SetDebugObjectName(newShader, debugName);

it = m_staticShaders.emplace(key, newShader).first;
bytecode->Release();
PanicAlert("Failed to compile texture encoding shader.");
m_encoding_shaders[format] = nullptr;
return nullptr;
}

return it->second;
ID3D11PixelShader* newShader;
HRESULT hr =
D3D::device->CreatePixelShader(bytecode->Data(), bytecode->Size(), nullptr, &newShader);
CHECK(SUCCEEDED(hr), "create efb encoder pixel shader");

m_encoding_shaders.emplace(format, newShader);
return newShader;
}
}
26 changes: 7 additions & 19 deletions Source/Core/VideoBackends/D3D/PSTextureEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <map>

#include "Common/CommonTypes.h"
#include "VideoCommon/TextureConversionShader.h"
#include "VideoCommon/VideoCommon.h"

struct ID3D11Texture2D;
Expand All @@ -31,32 +32,19 @@ class PSTextureEncoder final

void Init();
void Shutdown();
void Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y,
u32 memory_stride, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity,
bool scaleByHalf);
void Encode(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, const EFBRectangle& src_rect,
bool scale_by_half);

private:
ID3D11PixelShader* GetEncodingPixelShader(const EFBCopyFormat& format);

bool m_ready;

ID3D11Texture2D* m_out;
ID3D11RenderTargetView* m_outRTV;
ID3D11Texture2D* m_outStage;
ID3D11Buffer* m_encodeParams;

ID3D11PixelShader* SetStaticShader(unsigned int dstFormat, bool is_depth_copy, bool isIntensity,
bool scaleByHalf);

typedef unsigned int ComboKey; // Key for a shader combination

ComboKey MakeComboKey(unsigned int dstFormat, bool is_depth_copy, bool isIntensity,
bool scaleByHalf)
{
return (dstFormat << 4) | (static_cast<int>(is_depth_copy) << 2) |
(isIntensity ? (1 << 1) : 0) | (scaleByHalf ? (1 << 0) : 0);
}

typedef std::map<ComboKey, ID3D11PixelShader*> ComboMap;

ComboMap m_staticShaders;
std::map<EFBCopyFormat, ID3D11PixelShader*> m_encoding_shaders;
};
}
8 changes: 4 additions & 4 deletions Source/Core/VideoBackends/D3D/TextureCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRe
g_renderer->RestoreAPIState();
}

void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf)
void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half)
{
g_encoder->Encode(dst, format, native_width, bytes_per_row, num_blocks_y, memory_stride,
is_depth_copy, srcRect, isIntensity, scaleByHalf);
is_depth_copy, src_rect, scale_by_half);
}

const char palette_shader[] =
Expand Down
6 changes: 3 additions & 3 deletions Source/Core/VideoBackends/D3D/TextureCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ class TextureCache : public TextureCacheBase
void ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette,
TlutFormat format) override;

void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y,
u32 memory_stride, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity,
bool scaleByHalf) override;
void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& src_rect, bool scale_by_half) override;

bool CompileShaders() override { return true; }
void DeleteShaders() override {}
Expand Down
75 changes: 24 additions & 51 deletions Source/Core/VideoBackends/D3D12/PSTextureEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,18 @@ void PSTextureEncoder::Shutdown()
D3D::command_list_mgr->DestroyResourceAfterCurrentCommandListExecuted(m_out_readback_buffer);
D3D::command_list_mgr->DestroyResourceAfterCurrentCommandListExecuted(m_encode_params_buffer);

for (auto& it : m_static_shaders_blobs)
for (auto& it : m_shader_blobs)
{
SAFE_RELEASE(it);
}

m_static_shaders_blobs.clear();
m_static_shaders_map.clear();
m_shader_blobs.clear();
m_encoding_shaders.clear();
}

void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& src_rect, bool is_intensity, bool scale_by_half)
void PSTextureEncoder::Encode(u8* dst, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half)
{
if (!m_ready) // Make sure we initialized OK
return;
Expand Down Expand Up @@ -167,8 +167,7 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p

D3D::DrawShadedTexQuad(
efb_source, target_rect.AsRECT(), g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(),
SetStaticShader(format, is_depth_copy, is_intensity, scale_by_half),
StaticShaderCache::GetSimpleVertexShader(),
GetEncodingPixelShader(format), StaticShaderCache::GetSimpleVertexShader(),
StaticShaderCache::GetSimpleVertexShaderInputLayout(), D3D12_SHADER_BYTECODE(), 1.0f, 0,
DXGI_FORMAT_B8G8R8A8_UNORM, false, false /* Render target is not multisampled */
);
Expand Down Expand Up @@ -223,53 +222,27 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p
m_out_readback_buffer->Unmap(0, &write_range);
}

D3D12_SHADER_BYTECODE PSTextureEncoder::SetStaticShader(unsigned int dst_format, bool is_depth_copy,
bool is_intensity, bool scale_by_half)
D3D12_SHADER_BYTECODE PSTextureEncoder::GetEncodingPixelShader(const EFBCopyFormat& format)
{
ComboKey key = MakeComboKey(dst_format, is_depth_copy, is_intensity, scale_by_half);
auto iter = m_encoding_shaders.find(format);
if (iter != m_encoding_shaders.end())
return iter->second;

ComboMap::iterator it = m_static_shaders_map.find(key);
if (it == m_static_shaders_map.end())
ID3DBlob* bytecode = nullptr;
const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::D3D);
if (!D3D::CompilePixelShader(shader, &bytecode))
{
INFO_LOG(VIDEO, "Compiling efb encoding shader for dst_format 0x%X, is_depth_copy %d, "
"is_intensity %d, scale_by_half %d",
dst_format, is_depth_copy, is_intensity ? 1 : 0, scale_by_half ? 1 : 0);

u32 format = dst_format;

if (is_depth_copy)
{
format |= _GX_TF_ZTF;
if (dst_format == 11)
format = GX_TF_Z16;
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
format |= _GX_TF_CTF;
}
else
{
if (dst_format > GX_TF_RGBA8 || (dst_format < GX_TF_RGB565 && !is_intensity))
format |= _GX_TF_CTF;
}

ID3DBlob* bytecode = nullptr;
const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::D3D);
if (!D3D::CompilePixelShader(shader, &bytecode))
{
WARN_LOG(VIDEO, "EFB encoder shader for dst_format 0x%X, is_depth_copy %d, is_intensity %d, "
"scale_by_half %d failed to compile",
dst_format, is_depth_copy, is_intensity ? 1 : 0, scale_by_half ? 1 : 0);
m_static_shaders_blobs[key] = {};
return {};
}

D3D12_SHADER_BYTECODE new_shader = {bytecode->GetBufferPointer(), bytecode->GetBufferSize()};

it = m_static_shaders_map.emplace(key, new_shader).first;

// Keep track of the ID3DBlobs, so we can free them upon shutdown.
m_static_shaders_blobs.push_back(bytecode);
PanicAlert("Failed to compile texture encoding shader.");
m_encoding_shaders[format] = {};
return {};
}

return it->second;
D3D12_SHADER_BYTECODE new_shader = {bytecode->GetBufferPointer(), bytecode->GetBufferSize()};
m_encoding_shaders.emplace(format, new_shader);

// Keep track of the ID3DBlobs, so we can free them upon shutdown.
m_shader_blobs.push_back(bytecode);

return new_shader;
}
}
25 changes: 8 additions & 17 deletions Source/Core/VideoBackends/D3D12/PSTextureEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "Common/CommonTypes.h"
#include "VideoBackends/D3D12/D3DBase.h"
#include "VideoCommon/TextureConversionShader.h"
#include "VideoCommon/VideoCommon.h"

namespace DX12
Expand All @@ -20,11 +21,13 @@ class PSTextureEncoder final

void Init();
void Shutdown();
void Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y,
u32 memory_stride, bool is_depth_copy, const EFBRectangle& src_rect,
bool is_intensity, bool scale_by_half);
void Encode(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, const EFBRectangle& src_rect,
bool scale_by_half);

private:
D3D12_SHADER_BYTECODE GetEncodingPixelShader(const EFBCopyFormat& format);

bool m_ready = false;

ID3D12Resource* m_out = nullptr;
Expand All @@ -35,19 +38,7 @@ class PSTextureEncoder final
ID3D12Resource* m_encode_params_buffer = nullptr;
void* m_encode_params_buffer_data = nullptr;

D3D12_SHADER_BYTECODE SetStaticShader(unsigned int dst_format, bool is_depth_copy,
bool is_intensity, bool scale_by_half);

using ComboKey = unsigned int; // Key for a shader combination
static ComboKey MakeComboKey(unsigned int dst_format, bool is_depth_copy, bool is_intensity,
bool scale_by_half)
{
return (dst_format << 4) | (is_depth_copy << 2) | (is_intensity ? (1 << 1) : 0) |
(scale_by_half ? (1 << 0) : 0);
}

using ComboMap = std::map<ComboKey, D3D12_SHADER_BYTECODE>;
ComboMap m_static_shaders_map;
std::vector<ID3DBlob*> m_static_shaders_blobs;
std::map<EFBCopyFormat, D3D12_SHADER_BYTECODE> m_encoding_shaders;
std::vector<ID3DBlob*> m_shader_blobs;
};
}
8 changes: 4 additions & 4 deletions Source/Core/VideoBackends/D3D12/TextureCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,12 +306,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRe
g_renderer->RestoreAPIState();
}

void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf)
void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half)
{
s_encoder->Encode(dst, format, native_width, bytes_per_row, num_blocks_y, memory_stride,
is_depth_copy, srcRect, isIntensity, scaleByHalf);
is_depth_copy, src_rect, scale_by_half);
}

static const constexpr char s_palette_shader_hlsl[] =
Expand Down

0 comments on commit 29344cb

Please sign in to comment.