Skip to content

Commit

Permalink
Implement smoothed depal for the "old" depal path as well.
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Aug 22, 2022
1 parent 89d05b7 commit 1d9717d
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 36 deletions.
38 changes: 28 additions & 10 deletions GPU/Common/DepalettizeCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ void DepalShaderCache::Clear() {
nearestSampler_->Release();
nearestSampler_ = nullptr;
}
if (linearSampler_) {
linearSampler_->Release();
linearSampler_ = nullptr;
}
}

void DepalShaderCache::Decimate() {
Expand All @@ -161,21 +165,34 @@ void DepalShaderCache::Decimate() {
}
}

Draw::SamplerState *DepalShaderCache::GetSampler() {
if (!nearestSampler_) {
Draw::SamplerStateDesc desc{};
desc.wrapU = Draw::TextureAddressMode::CLAMP_TO_EDGE;
desc.wrapV = Draw::TextureAddressMode::CLAMP_TO_EDGE;
desc.wrapW = Draw::TextureAddressMode::CLAMP_TO_EDGE;
nearestSampler_ = draw_->CreateSamplerState(desc);
Draw::SamplerState *DepalShaderCache::GetSampler(bool linearFilter) {
if (linearFilter) {
if (!linearSampler_) {
Draw::SamplerStateDesc desc{};
desc.magFilter = Draw::TextureFilter::LINEAR;
desc.minFilter = Draw::TextureFilter::LINEAR;
desc.wrapU = Draw::TextureAddressMode::CLAMP_TO_EDGE;
desc.wrapV = Draw::TextureAddressMode::CLAMP_TO_EDGE;
desc.wrapW = Draw::TextureAddressMode::CLAMP_TO_EDGE;
linearSampler_ = draw_->CreateSamplerState(desc);
}
return linearSampler_;
} else {
if (!nearestSampler_) {
Draw::SamplerStateDesc desc{};
desc.wrapU = Draw::TextureAddressMode::CLAMP_TO_EDGE;
desc.wrapV = Draw::TextureAddressMode::CLAMP_TO_EDGE;
desc.wrapW = Draw::TextureAddressMode::CLAMP_TO_EDGE;
nearestSampler_ = draw_->CreateSamplerState(desc);
}
return nearestSampler_;
}
return nearestSampler_;
}

DepalShader *DepalShaderCache::GetDepalettizeShader(uint32_t clutMode, GETextureFormat textureFormat, GEBufferFormat bufferFormat) {
DepalShader *DepalShaderCache::GetDepalettizeShader(uint32_t clutMode, GETextureFormat textureFormat, GEBufferFormat bufferFormat, bool smoothedDepal) {
using namespace Draw;

u32 id = GenerateShaderID(clutMode, textureFormat, bufferFormat);
u32 id = GenerateShaderID(clutMode, textureFormat, bufferFormat, smoothedDepal);

auto shader = cache_.find(id);
if (shader != cache_.end()) {
Expand All @@ -198,6 +215,7 @@ DepalShader *DepalShaderCache::GetDepalettizeShader(uint32_t clutMode, GETexture
config.mask = gstate.getClutIndexMask();
config.bufferFormat = bufferFormat;
config.textureFormat = textureFormat;
config.smoothedDepal = smoothedDepal;

GenerateDepalFs(buffer, config, draw_->GetShaderLanguageDesc());

Expand Down
10 changes: 6 additions & 4 deletions GPU/Common/DepalettizeCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ class DepalShaderCache {
~DepalShaderCache();

// This also uploads the palette and binds the correct texture.
DepalShader *GetDepalettizeShader(uint32_t clutMode, GETextureFormat texFormat, GEBufferFormat pixelFormat);
DepalShader *GetDepalettizeShader(uint32_t clutMode, GETextureFormat texFormat, GEBufferFormat pixelFormat, bool smoothedDepal);
DepalTexture GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, u32 *rawClut);

Draw::SamplerState *GetSampler();
Draw::SamplerState *GetSampler(bool linearFilter);

void Clear();
void Decimate();
Expand All @@ -65,8 +65,8 @@ class DepalShaderCache {
void DeviceRestore(Draw::DrawContext *draw);

private:
static uint32_t GenerateShaderID(uint32_t clutMode, GETextureFormat texFormat, GEBufferFormat pixelFormat) {
return (clutMode & 0xFFFFFF) | (pixelFormat << 24) | (texFormat << 28);
static uint32_t GenerateShaderID(uint32_t clutMode, GETextureFormat texFormat, GEBufferFormat pixelFormat, bool smoothedDepal) {
return (clutMode & 0xFFFFFF) | (pixelFormat << 24) | (texFormat << 28) | ((int)smoothedDepal << 27);
}

static uint32_t GetClutID(GEPaletteFormat clutFormat, uint32_t clutHash) {
Expand All @@ -77,6 +77,7 @@ class DepalShaderCache {
Draw::DrawContext *draw_;
Draw::ShaderModule *vertexShader_ = nullptr;
Draw::SamplerState *nearestSampler_ = nullptr;
Draw::SamplerState *linearSampler_ = nullptr;

std::map<u32, DepalShader *> cache_;
std::map<u32, DepalTexture *> texCache_;
Expand Down Expand Up @@ -166,6 +167,7 @@ class TextureShaderApplier {

void Shade() {
Draw::Viewport vp{ 0.0f, 0.0f, (float)renderW_, (float)renderH_, 0.0f, 1.0f };
// TODO: Half pixel offset for D3D9?
draw_->SetViewports(1, &vp);
draw_->SetScissorRect(0, 0, renderW_, renderH_);
draw_->DrawUP((const uint8_t *)verts_, 4);
Expand Down
69 changes: 55 additions & 14 deletions GPU/Common/DepalettizeShaderCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ static const VaryingDef varyings[1] = {
};

// Uses integer instructions available since OpenGL 3.0, ES 3.0 (and 2.0 with extensions), and of course Vulkan and D3D11.
void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config, const ShaderLanguageDesc &lang) {
void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config) {
const int shift = config.shift;
const int mask = config.mask;

Expand Down Expand Up @@ -140,7 +140,7 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config, con
}

// FP only, to suit GL(ES) 2.0 and DX9
void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config, const ShaderLanguageDesc &lang) {
void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config) {
char lookupMethod[128] = "index.r";

const int shift = config.shift;
Expand Down Expand Up @@ -288,23 +288,64 @@ void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config, c
writer.C(" vec4 outColor = ").SampleTexture2D("pal", "vec2(coord, 0.0)").C(";\n");
}

void GenerateDepalSmoothed(ShaderWriter &writer, const DepalConfig &config) {
const char *sourceChannel = "error";
float indexMultiplier = 32.0f;

if (config.bufferFormat == GE_FORMAT_5551) {
_dbg_assert_(config.mask == 0x1F);
switch (config.shift) {
case 0: sourceChannel = "r"; break;
case 5: sourceChannel = "g"; break;
case 10: sourceChannel = "b"; break;
default: _dbg_assert_(false);
}
} else if (config.bufferFormat == GE_FORMAT_565) {
_dbg_assert_(config.mask == 0x1F || config.mask == 0x3F);
switch (config.shift) {
case 0: sourceChannel = "r"; break;
case 5: sourceChannel = "g"; indexMultiplier = 64.0f; break;
case 11: sourceChannel = "b"; break;
default: _dbg_assert_(false);
}
} else {
_dbg_assert_(false);
}

writer.C(" float index = ").SampleTexture2D("tex", "v_texcoord").F(".%s * %0.1f;\n", sourceChannel, indexMultiplier);

float texturePixels = 256.f;
if (config.clutFormat != GE_CMODE_32BIT_ABGR8888) {
texturePixels = 512.f;
}

writer.F(" float coord = (index + 0.5) * %f;\n", 1.0 / texturePixels);
writer.C(" vec4 outColor = ").SampleTexture2D("pal", "vec2(coord, 0.0)").C(";\n");
}

void GenerateDepalFs(char *buffer, const DepalConfig &config, const ShaderLanguageDesc &lang) {
ShaderWriter writer(buffer, lang, ShaderStage::Fragment);
writer.DeclareSamplers(samplers);
writer.HighPrecisionFloat();
writer.BeginFSMain(Slice<UniformDef>::empty(), varyings, FSFLAG_NONE);
switch (lang.shaderLanguage) {
case HLSL_D3D9:
case GLSL_1xx:
GenerateDepalShaderFloat(writer, config, lang);
break;
case GLSL_VULKAN:
case GLSL_3xx:
case HLSL_D3D11:
GenerateDepalShader300(writer, config, lang);
break;
default:
_assert_msg_(false, "Depal shader language not supported: %d", (int)lang.shaderLanguage);
if (config.smoothedDepal) {
// Handles a limited set of cases, but doesn't need any integer math so we don't
// need two variants.
GenerateDepalSmoothed(writer, config);
} else {
switch (lang.shaderLanguage) {
case HLSL_D3D9:
case GLSL_1xx:
GenerateDepalShaderFloat(writer, config);
break;
case GLSL_VULKAN:
case GLSL_3xx:
case HLSL_D3D11:
GenerateDepalShader300(writer, config);
break;
default:
_assert_msg_(false, "Depal shader language not supported: %d", (int)lang.shaderLanguage);
}
}
writer.EndFSMain("outColor", FSFLAG_NONE);
}
Expand Down
1 change: 1 addition & 0 deletions GPU/Common/DepalettizeShaderCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ struct DepalConfig {
GEPaletteFormat clutFormat;
GETextureFormat textureFormat;
GEBufferFormat bufferFormat;
bool smoothedDepal;
};

void GenerateDepalFs(char *buffer, const DepalConfig &config, const ShaderLanguageDesc &lang);
Expand Down
20 changes: 12 additions & 8 deletions GPU/Common/TextureCacheCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1899,12 +1899,17 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
break;
}

const GEPaletteFormat clutFormat = gstate.getClutPaletteFormat();
DepalTexture clutTexture{};
bool smoothedDepal = false;

if (need_depalettize && !g_Config.bDisableSlowFramebufEffects) {
clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBufRaw_);
smoothedDepal = CanUseSmoothDepal(gstate, framebuffer->drawnFormat, clutTexture.rampLength);

if (useShaderDepal) {
const GEPaletteFormat clutFormat = gstate.getClutPaletteFormat();

// Very icky conflation here of native and thin3d rendering. This will need careful work per backend in BindAsClutTexture.
DepalTexture clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBufRaw_);
BindAsClutTexture(clutTexture.texture);

framebufferManager_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_MAY_COPY_WITH_UV | BINDFBCOLOR_APPLY_TEX_OFFSET);
Expand All @@ -1920,7 +1925,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
// Since we started/ended render passes, might need these.
gstate_c.Dirty(DIRTY_DEPAL);

gstate_c.SetUseShaderDepal(true, CanUseSmoothDepal(gstate, framebuffer->drawnFormat, clutTexture.rampLength));
gstate_c.SetUseShaderDepal(true, smoothedDepal);
gstate_c.depalFramebufferFormat = framebuffer->drawnFormat;
const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16);
const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor;
Expand All @@ -1932,13 +1937,11 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
return;
}

depalShader = depalShaderCache_->GetDepalettizeShader(clutMode, texFormat, depth ? GE_FORMAT_DEPTH16 : framebuffer->drawnFormat);
depalShader = depalShaderCache_->GetDepalettizeShader(clutMode, texFormat, depth ? GE_FORMAT_DEPTH16 : framebuffer->drawnFormat, smoothedDepal);
gstate_c.SetUseShaderDepal(false, false);
}

if (depalShader) {
const GEPaletteFormat clutFormat = gstate.getClutPaletteFormat();
DepalTexture clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBufRaw_);
Draw::Framebuffer *depalFBO = framebufferManager_->GetTempFBO(TempFBO::DEPAL, framebuffer->renderWidth, framebuffer->renderHeight);
draw_->BindTexture(0, nullptr);
draw_->BindTexture(1, nullptr);
Expand All @@ -1954,9 +1957,10 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer

draw_->BindFramebufferAsTexture(framebuffer->fbo, 0, depth ? Draw::FB_DEPTH_BIT : Draw::FB_COLOR_BIT, 0);
draw_->BindTexture(1, clutTexture.texture);
Draw::SamplerState *nearest = depalShaderCache_->GetSampler();
Draw::SamplerState *nearest = depalShaderCache_->GetSampler(false);
Draw::SamplerState *clutSampler = depalShaderCache_->GetSampler(smoothedDepal);
draw_->BindSamplerStates(0, 1, &nearest);
draw_->BindSamplerStates(1, 1, &nearest);
draw_->BindSamplerStates(1, 1, &clutSampler);

shaderApply.Shade();
draw_->BindTexture(0, nullptr);
Expand Down

0 comments on commit 1d9717d

Please sign in to comment.