Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decode EFB copies used as paletted textures. #2059

Merged
merged 3 commits into from Feb 20, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
160 changes: 159 additions & 1 deletion Source/Core/VideoBackends/D3D/TextureCache.cpp
Expand Up @@ -4,6 +4,7 @@

#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"
Expand All @@ -14,6 +15,7 @@
#include "VideoBackends/D3D/TextureEncoder.h"
#include "VideoBackends/D3D/VertexShaderCache.h"
#include "VideoCommon/ImageWrite.h"
#include "VideoCommon/LookUpTables.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/VideoConfig.h"

Expand Down Expand Up @@ -179,17 +181,167 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo

size_in_bytes = (u32)encoded_size;

TextureCache::MakeRangeDynamic(addr, (u32)encoded_size);
TextureCache::MakeRangeDynamic(dstAddr, (u32)encoded_size);

this->hash = hash;
}
}

const char palette_shader[] =
R"HLSL(
sampler samp0 : register(s0);
Texture2DArray Tex0 : register(t0);
Buffer<uint> Tex1 : register(t1);
uniform float Multiply;

uint Convert3To8(uint v)
{
// Swizzle bits: 00000123 -> 12312312
return (v << 5) | (v << 2) | (v >> 1);

This comment was marked as off-topic.

This comment was marked as off-topic.

}

uint Convert4To8(uint v)
{
// Swizzle bits: 00001234 -> 12341234
return (v << 4) | v;
}

uint Convert5To8(uint v)
{
// Swizzle bits: 00012345 -> 12345123
return (v << 3) | (v >> 2);
}

uint Convert6To8(uint v)
{
// Swizzle bits: 00123456 -> 12345612
return (v << 2) | (v >> 4);
}

float4 DecodePixel_RGB5A3(uint val)
{
int r,g,b,a;
if ((val&0x8000))
{
r=Convert5To8((val>>10) & 0x1f);
g=Convert5To8((val>>5 ) & 0x1f);
b=Convert5To8((val ) & 0x1f);
a=0xFF;
}
else
{
a=Convert3To8((val>>12) & 0x7);
r=Convert4To8((val>>8 ) & 0xf);
g=Convert4To8((val>>4 ) & 0xf);
b=Convert4To8((val ) & 0xf);
}
return float4(r, g, b, a) / 255;
}

float4 DecodePixel_RGB565(uint val)
{
int r, g, b, a;
r = Convert5To8((val >> 11) & 0x1f);
g = Convert6To8((val >> 5) & 0x3f);
b = Convert5To8((val) & 0x1f);
a = 0xFF;
return float4(r, g, b, a) / 255;
}

float4 DecodePixel_IA8(uint val)
{
int i = val & 0xFF;
int a = val >> 8;
return float4(i, i, i, a) / 255;
}

void main(
out float4 ocol0 : SV_Target,
in float4 pos : SV_Position,
in float3 uv0 : TEXCOORD0)
{
uint src = round(Tex0.Sample(samp0,uv0) * Multiply).r;
src = Tex1.Load(src);
src = ((src << 8) & 0xFF00) | (src >> 8);
ocol0 = DECODE(src);
}
)HLSL";

void TextureCache::ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format)
{
g_renderer->ResetAPIState();

// stretch picture with increased internal resolution
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)unconverted->config.width, (float)unconverted->config.height);
D3D::context->RSSetViewports(1, &vp);

D3D11_BOX box{ 0, 0, 0, 512, 1, 1 };
D3D::context->UpdateSubresource(palette_buf, 0, &box, palette, 0, 0);

D3D::stateman->SetTexture(1, palette_buf_srv);

// TODO: Add support for C14X2 format. (Different multiplier, more palette entries.)
float params[4] = { unconverted->format == 0 ? 15.f : 255.f };
D3D::context->UpdateSubresource(palette_uniform, 0, nullptr, &params, 0, 0);
D3D::stateman->SetPixelConstants(palette_uniform);

const D3D11_RECT sourcerect = CD3D11_RECT(0, 0, unconverted->config.width, unconverted->config.height);

D3D::SetPointCopySampler();

// Make sure we don't draw with the texture set as both a source and target.
// (This can happen because we don't unbind textures when we free them.)
D3D::stateman->UnsetTexture(static_cast<TCacheEntry*>(entry)->texture->GetSRV());

D3D::context->OMSetRenderTargets(1, &static_cast<TCacheEntry*>(entry)->texture->GetRTV(), nullptr);

// Create texture copy
D3D::drawShadedTexQuad(
static_cast<TCacheEntry*>(unconverted)->texture->GetSRV(),
&sourcerect, unconverted->config.width, unconverted->config.height,
palette_pixel_shader[format],
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(),
GeometryShaderCache::GetCopyGeometryShader());

D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());

g_renderer->RestoreAPIState();
}

ID3D11PixelShader *GetConvertShader(const char* Type)
{
std::string shader = "#define DECODE DecodePixel_";
shader.append(Type);
shader.append("\n");
shader.append(palette_shader);
return D3D::CompileAndCreatePixelShader(shader);
}

TextureCache::TextureCache()
{
// FIXME: Is it safe here?
g_encoder = new PSTextureEncoder;
g_encoder->Init();

palette_buf = nullptr;
palette_buf_srv = nullptr;
palette_uniform = nullptr;
palette_pixel_shader[GX_TL_IA8] = GetConvertShader("IA8");
palette_pixel_shader[GX_TL_RGB565] = GetConvertShader("RGB565");
palette_pixel_shader[GX_TL_RGB5A3] = GetConvertShader("RGB5A3");
auto lutBd = CD3D11_BUFFER_DESC(sizeof(u16) * 256, D3D11_BIND_SHADER_RESOURCE);

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

HRESULT hr = D3D::device->CreateBuffer(&lutBd, nullptr, &palette_buf);
CHECK(SUCCEEDED(hr), "create palette decoder lut buffer");
D3D::SetDebugObjectName(palette_buf, "texture decoder lut buffer");
// TODO: C14X2 format.
auto outlutUavDesc = CD3D11_SHADER_RESOURCE_VIEW_DESC(palette_buf, DXGI_FORMAT_R16_UINT, 0, 256, 0);
hr = D3D::device->CreateShaderResourceView(palette_buf, &outlutUavDesc, &palette_buf_srv);
CHECK(SUCCEEDED(hr), "create palette decoder lut srv");
D3D::SetDebugObjectName(palette_buf_srv, "texture decoder lut srv");
const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(16, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT);
hr = D3D::device->CreateBuffer(&cbdesc, nullptr, &palette_uniform);
CHECK(SUCCEEDED(hr), "Create palette decoder constant buffer");
D3D::SetDebugObjectName((ID3D11DeviceChild*)palette_uniform, "a constant buffer used in TextureCache::CopyRenderTargetToTexture");
}

TextureCache::~TextureCache()
Expand All @@ -200,6 +352,12 @@ TextureCache::~TextureCache()
g_encoder->Shutdown();
delete g_encoder;
g_encoder = nullptr;

SAFE_RELEASE(palette_buf);
SAFE_RELEASE(palette_buf_srv);
SAFE_RELEASE(palette_uniform);
for (ID3D11PixelShader*& shader : palette_pixel_shader)
SAFE_RELEASE(shader);
}

}
7 changes: 7 additions & 0 deletions Source/Core/VideoBackends/D3D/TextureCache.h
Expand Up @@ -42,8 +42,15 @@ class TextureCache : public ::TextureCache

u64 EncodeToRamFromTexture(u32 address, void* source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) {return 0;};

void ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format) override;

void CompileShaders() override { }
void DeleteShaders() override { }

ID3D11Buffer* palette_buf;
ID3D11ShaderResourceView* palette_buf_srv;
ID3D11Buffer* palette_uniform;
ID3D11PixelShader* palette_pixel_shader[3];
};

}
1 change: 1 addition & 0 deletions Source/Core/VideoBackends/D3D/main.cpp
Expand Up @@ -82,6 +82,7 @@ void InitBackendInfo()
g_Config.backend_info.bSupportsGeometryShaders = true;
g_Config.backend_info.bSupports3DVision = true;
g_Config.backend_info.bSupportsPostProcessing = false;
g_Config.backend_info.bSupportsPaletteConversion = true;

IDXGIFactory* factory;
IDXGIAdapter* ad;
Expand Down
12 changes: 9 additions & 3 deletions Source/Core/VideoBackends/OGL/TextureCache.cpp
Expand Up @@ -204,20 +204,20 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
if (false == g_ActiveConfig.bCopyEFBToTexture)
{
int encoded_size = TextureConverter::EncodeToRamFromTexture(
addr,
dstAddr,
read_texture,
srcFormat == PEControl::Z24,
isIntensity,
dstFormat,
scaleByHalf,
srcRect);

u8* dst = Memory::GetPointer(addr);
u8* dst = Memory::GetPointer(dstAddr);
u64 const new_hash = GetHash64(dst,encoded_size,g_ActiveConfig.iSafeTextureCache_ColorSamples);

size_in_bytes = (u32)encoded_size;

TextureCache::MakeRangeDynamic(addr,encoded_size);
TextureCache::MakeRangeDynamic(dstAddr, encoded_size);

hash = new_hash;
}
Expand Down Expand Up @@ -359,4 +359,10 @@ void TextureCache::DeleteShaders()
s_DepthMatrixProgram.Destroy();
}

void TextureCache::ConvertTexture(TextureCache::TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format)
{
// TODO: Implement.
return;

This comment was marked as off-topic.

This comment was marked as off-topic.

}

}
1 change: 1 addition & 0 deletions Source/Core/VideoBackends/OGL/TextureCache.h
Expand Up @@ -48,6 +48,7 @@ class TextureCache : public ::TextureCache
~TextureCache();

TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) override;
void ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format) override;

void CompileShaders() override;
void DeleteShaders() override;
Expand Down
1 change: 1 addition & 0 deletions Source/Core/VideoBackends/OGL/main.cpp
Expand Up @@ -140,6 +140,7 @@ static void InitBackendInfo()
g_Config.backend_info.bSupportsGeometryShaders = true;
g_Config.backend_info.bSupports3DVision = false;
g_Config.backend_info.bSupportsPostProcessing = true;
g_Config.backend_info.bSupportsPaletteConversion = false;

g_Config.backend_info.Adapters.clear();

Expand Down