Skip to content

Commit

Permalink
Allow binding depth as 565 by going through depal.
Browse files Browse the repository at this point in the history
This is a partial fix for #6105 (Ratchet & Clank particles visible
through things), but there's still weird glitchiness. There's a pass
during rendering that scrambles the mini depth buffer by using a
triangle mesh. I wonder if it's trying to simulate the swizzle? But it
doesn't really look like it...
  • Loading branch information
hrydgard committed Aug 18, 2022
1 parent f8ab610 commit 56350fe
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 17 deletions.
7 changes: 4 additions & 3 deletions GPU/Common/DepalettizeCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,10 @@ Draw::SamplerState *DepalShaderCache::GetSampler() {
return nearestSampler_;
}

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

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

auto shader = cache_.find(id);
if (shader != cache_.end()) {
Expand All @@ -171,7 +171,8 @@ DepalShader *DepalShaderCache::GetDepalettizeShader(uint32_t clutMode, GEBufferF
config.startPos = gstate.getClutIndexStartPos();
config.shift = gstate.getClutIndexShift();
config.mask = gstate.getClutIndexMask();
config.pixelFormat = pixelFormat;
config.bufferFormat = bufferFormat;
config.textureFormat = textureFormat;

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

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

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

Draw::SamplerState *GetSampler();
Expand All @@ -63,8 +63,8 @@ class DepalShaderCache {
void DeviceRestore(Draw::DrawContext *draw);

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

static uint32_t GetClutID(GEPaletteFormat clutFormat, uint32_t clutHash) {
Expand Down
21 changes: 16 additions & 5 deletions GPU/Common/DepalettizeShaderCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config, con
const int shift = config.shift;
const int mask = config.mask;

if (config.pixelFormat == GE_FORMAT_DEPTH16) {
if (config.bufferFormat == GE_FORMAT_DEPTH16) {
DepthScaleFactors factors = GetDepthScaleFactors();
writer.ConstFloat("z_scale", factors.scale);
writer.ConstFloat("z_offset", factors.offset);
Expand All @@ -71,7 +71,7 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config, con
writer.C(" vec4 color = ").SampleTexture2D("tex", "v_texcoord").C(";\n");

int shiftedMask = mask << shift;
switch (config.pixelFormat) {
switch (config.bufferFormat) {
case GE_FORMAT_8888:
if (shiftedMask & 0xFF) writer.C(" int r = int(color.r * 255.99);\n"); else writer.C(" int r = 0;\n");
if (shiftedMask & 0xFF00) writer.C(" int g = int(color.g * 255.99);\n"); else writer.C(" int g = 0;\n");
Expand Down Expand Up @@ -102,6 +102,17 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config, con
case GE_FORMAT_DEPTH16:
// Remap depth buffer.
writer.C(" float depth = (color.x - z_offset) * z_scale;\n");

if (config.bufferFormat == GE_FORMAT_DEPTH16 && config.textureFormat == GE_TFMT_5650) {
// Convert depth to 565, without going through a CLUT.
writer.C(" int idepth = int(clamp(depth, 0.0, 65535.0));\n");
writer.C(" float r = (idepth & 31) / 31.0f;\n");
writer.C(" float g = ((idepth >> 5) & 63) / 63.0f;\n");
writer.C(" float b = ((idepth >> 11) & 31) / 31.0f;\n");
writer.C(" vec4 outColor = vec4(r, g, b, 1.0);\n");
return;
}

writer.C(" int index = int(clamp(depth, 0.0, 65535.0));\n");
break;
default:
Expand Down Expand Up @@ -135,7 +146,7 @@ void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config, c
const int shift = config.shift;
const int mask = config.mask;

if (config.pixelFormat == GE_FORMAT_DEPTH16) {
if (config.bufferFormat == GE_FORMAT_DEPTH16) {
DepthScaleFactors factors = GetDepthScaleFactors();
writer.ConstFloat("z_scale", factors.scale);
writer.ConstFloat("z_offset", factors.offset);
Expand All @@ -144,7 +155,7 @@ void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config, c
float index_multiplier = 1.0f;
// pixelformat is the format of the texture we are sampling.
bool formatOK = true;
switch (config.pixelFormat) {
switch (config.bufferFormat) {
case GE_FORMAT_8888:
if ((mask & (mask + 1)) == 0) {
// If the value has all bits contiguous (bitmask check above), we can mod by it + 1.
Expand Down Expand Up @@ -249,7 +260,7 @@ void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config, c
// index_multiplier -= 0.01f / texturePixels;

if (!formatOK) {
ERROR_LOG_REPORT_ONCE(depal, G3D, "%s depal unsupported: shift=%d mask=%02x offset=%d", GeBufferFormatToString(config.pixelFormat), shift, mask, config.startPos);
ERROR_LOG_REPORT_ONCE(depal, G3D, "%s depal unsupported: shift=%d mask=%02x offset=%d", GeBufferFormatToString(config.bufferFormat), shift, mask, config.startPos);
}

// Offset by half a texel (plus clutBase) to turn NEAREST filtering into FLOOR.
Expand Down
3 changes: 2 additions & 1 deletion GPU/Common/DepalettizeShaderCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ struct DepalConfig {
int shift;
u32 startPos;
GEPaletteFormat clutFormat;
GEBufferFormat pixelFormat;
GETextureFormat textureFormat;
GEBufferFormat bufferFormat;
};

void GenerateDepalFs(char *buffer, const DepalConfig &config, const ShaderLanguageDesc &lang);
Expand Down
37 changes: 33 additions & 4 deletions GPU/Common/TextureCacheCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,10 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
def.format = format;
def.bufw = bufw;

if (texaddr == 0x04710000) {
texaddr = texaddr;
}

std::vector<AttachCandidate> candidates = GetFramebufferCandidates(def, 0);
if (candidates.size() > 0) {
int index = GetBestCandidateIndex(candidates);
Expand Down Expand Up @@ -891,6 +895,7 @@ bool TextureCacheCommon::MatchFramebuffer(

const bool noOffset = texaddr == addr;
const bool exactMatch = noOffset && entry.format < 4 && channel == RASTER_COLOR;

const u32 w = 1 << ((entry.dim >> 0) & 0xf);
const u32 h = 1 << ((entry.dim >> 8) & 0xf);
// 512 on a 272 framebuffer is sane, so let's be lenient.
Expand Down Expand Up @@ -925,7 +930,8 @@ bool TextureCacheCommon::MatchFramebuffer(

// Check works for D16 too (???)
const bool matchingClutFormat =
(channel != RASTER_COLOR && entry.format == GE_TFMT_CLUT16) ||
(channel == RASTER_DEPTH && entry.format == GE_TFMT_CLUT16) ||
(channel == RASTER_DEPTH && entry.format == GE_TFMT_5650) ||
(channel == RASTER_COLOR && framebuffer->format == GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT32) ||
(channel == RASTER_COLOR && framebuffer->format != GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT16);

Expand Down Expand Up @@ -970,7 +976,9 @@ bool TextureCacheCommon::MatchFramebuffer(
// 3rd Birthday (and a bunch of other games) render to a 16 bit clut texture.
if (matchingClutFormat) {
if (!noOffset) {
WARN_LOG_ONCE(subareaClut, G3D, "Texturing from framebuffer using CLUT with offset at %08x +%dx%d", fb_address, matchInfo->xOffset, matchInfo->yOffset);
WARN_LOG_ONCE(subareaClut, G3D, "Texturing from framebuffer (%s) using %s with offset at %08x +%dx%d", channel == RASTER_DEPTH ? "DEPTH" : "COLOR", GeTextureFormatToString(entry.format), fb_address, matchInfo->xOffset, matchInfo->yOffset);
} else {
WARN_LOG_ONCE(subareaClut, G3D, "Texturing from framebuffer (%s) using %s at %08x", channel == RASTER_DEPTH ? "DEPTH" : "COLOR", GeTextureFormatToString(entry.format), fb_address);
}
return true;
} else if (IsClutFormat((GETextureFormat)(entry.format)) || IsDXTFormat((GETextureFormat)(entry.format))) {
Expand Down Expand Up @@ -1818,12 +1826,33 @@ void TextureCacheCommon::ApplyTexture() {
gstate_c.SetTextureIs3D((entry->status & TexCacheEntry::STATUS_3D) != 0);
}

bool CanDepalettize(GETextureFormat texFormat, GEBufferFormat bufferFormat) {
if (IsClutFormat(texFormat)) {
switch (bufferFormat) {
case GE_FORMAT_4444:
case GE_FORMAT_565:
case GE_FORMAT_5551:
case GE_FORMAT_DEPTH16:
return texFormat == GE_TFMT_CLUT16;
case GE_FORMAT_8888:
return texFormat == GE_TFMT_CLUT32;
}
WARN_LOG(G3D, "Invalid CLUT/framebuffer combination: %s vs %s", GeTextureFormatToString(texFormat), GeBufferFormatToString(bufferFormat));
return false;
} else if (texFormat == GE_TFMT_5650 && bufferFormat == GE_FORMAT_DEPTH16) {
// We can also "depal" 565 format, this is used to read depth buffers as 565 on occasion (#15491).
return true;
} else {
return false;
}
}

void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, GETextureFormat texFormat, RasterChannel channel) {
DepalShader *depalShader = nullptr;
uint32_t clutMode = gstate.clutformat & 0xFFFFFF;

bool need_depalettize = IsClutFormat(texFormat);
bool depth = channel == RASTER_DEPTH;
bool need_depalettize = CanDepalettize(texFormat, depth ? GE_FORMAT_DEPTH16 : framebuffer->drawnFormat);
bool useShaderDepal = framebufferManager_->GetCurrentRenderVFB() != framebuffer && !depth && !gstate_c.curTextureIs3D;

// TODO: Implement shader depal in the fragment shader generator for D3D11 at least.
Expand Down Expand Up @@ -1873,7 +1902,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
return;
}

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

Expand Down
3 changes: 2 additions & 1 deletion unittest/TestShaderGenerators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,8 @@ bool TestDepalShaders() {
config.shift = 8;
config.startPos = 64;
config.mask = 0xFF;
config.pixelFormat = GE_FORMAT_8888;
config.bufferFormat = GE_FORMAT_8888;
config.textureFormat = GE_TFMT_CLUT32;

GenerateDepalFs(buffer, config, desc);
if (!TestCompileShader(buffer, languages[k], ShaderStage::Fragment, &errorMessage)) {
Expand Down

0 comments on commit 56350fe

Please sign in to comment.