Prepare for shader depal (CLUT palette lookup) for ordinary textures

This commit is contained in:
Henrik Rydgård
2026-06-11 11:24:45 +02:00
parent d33425d01d
commit 0bf1d12053
8 changed files with 41 additions and 26 deletions
+19 -7
View File
@@ -462,6 +462,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
gstate_c.SetTextureIs3D(false);
gstate_c.SetTextureIsArray(false);
gstate_c.SetTextureIsFramebuffer(false);
gstate_c.SetShaderDepal(ShaderDepalMode::OFF);
return nullptr;
}
@@ -600,6 +601,11 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
gstate_c.SetTextureIsArray(false);
gstate_c.SetTextureIsBGRA(entry->status & TexStatus::BGRA);
gstate_c.SetTextureIsFramebuffer(false);
if (entry->status & TexStatus::CLUT8_INDEXED) {
gstate_c.SetShaderDepal(ShaderDepalMode::NORMAL, GE_FORMAT_CLUT8);
} else {
gstate_c.SetShaderDepal(ShaderDepalMode::OFF, GE_FORMAT_INVALID);
}
if (rehash) {
// Update in case any of these changed.
@@ -701,6 +707,11 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
gstate_c.SetTextureIs3D((entry->status & TexStatus::IS_3D) != 0);
gstate_c.SetTextureIsArray(false); // Ordinary 2D textures still aren't used by array view in VK. We probably might as well, though, at this point..
gstate_c.SetTextureIsFramebuffer(false);
if (entry->status & TexStatus::CLUT8_INDEXED) {
gstate_c.SetShaderDepal(ShaderDepalMode::NORMAL, GE_FORMAT_CLUT8);
} else {
gstate_c.SetShaderDepal(ShaderDepalMode::OFF, GE_FORMAT_INVALID);
}
failedTexture_ = false;
nextTexture_ = entry;
@@ -1233,6 +1244,7 @@ void TextureCacheCommon::SetTextureFramebuffer(const AttachCandidate &candidate)
gstate_c.SetTextureIsVideo(false);
gstate_c.SetTextureIs3D(false);
gstate_c.SetTextureIsArray(true);
gstate_c.SetShaderDepal(ShaderDepalMode::OFF);
nextNeedsRehash_ = false;
nextNeedsChange_ = false;
@@ -2218,7 +2230,7 @@ void TextureCacheCommon::ApplyTexture(bool doBind, bool flatZ) {
gstate_c.SetTextureIs3D((entry->status & TexStatus::IS_3D) != 0);
gstate_c.SetTextureIsArray(false);
gstate_c.SetTextureIsBGRA((entry->status & TexStatus::BGRA) != 0);
gstate_c.SetUseShaderDepal(ShaderDepalMode::OFF);
gstate_c.SetShaderDepal(ShaderDepalMode::OFF);
}
}
@@ -2358,8 +2370,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
}
gstate_c.Dirty(DIRTY_DEPAL | DIRTY_FRAGMENTSHADER_STATE);
gstate_c.SetUseShaderDepal(mode);
gstate_c.depalTextureFormat = fbFormat;
gstate_c.SetShaderDepal(mode, fbFormat);
const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16);
const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor;
@@ -2373,7 +2384,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
depthUpperBits = (depth && framebuffer->fb_format == GE_FORMAT_8888) ? ((gstate.getTextureAddress(0) & 0x600000) >> 20) : 0;
textureShader = textureShaderCache_.GetDepalettizeShader(clutMode, texFormat, fbFormat, smoothedDepal, depthUpperBits);
gstate_c.SetUseShaderDepal(ShaderDepalMode::OFF);
gstate_c.SetShaderDepal(ShaderDepalMode::OFF);
}
if (textureShader) {
@@ -2448,7 +2459,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
framebufferManager_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_MAY_COPY_WITH_UV | BINDFBCOLOR_APPLY_TEX_OFFSET, Draw::ALL_LAYERS);
BoundFramebufferTexture();
gstate_c.SetUseShaderDepal(ShaderDepalMode::OFF);
gstate_c.SetShaderDepal(ShaderDepalMode::OFF);
gstate_c.SetTextureSolidAlpha(gstate.getTextureFormat() == GE_TFMT_5650);
}
@@ -2487,7 +2498,7 @@ void TextureCacheCommon::ApplyTextureDepal(TexCacheEntry *entry) {
dynamicClutTemp_, 0.0f, 0.0f, 512.0f, 1.0f, dynamicClutFbo_, 0.0f, 0.0f, scaleFactorX * 512.0f, 1.0f, false, 1.0f, reinterpret, "reinterpret_clut");
Draw2DPipeline *textureShader = textureShaderCache_.GetDepalettizeShader(clutMode, GE_TFMT_CLUT8, GE_FORMAT_CLUT8, false, 0);
gstate_c.SetUseShaderDepal(ShaderDepalMode::OFF);
gstate_c.SetShaderDepal(ShaderDepalMode::OFF);
int texWidth = gstate.getTextureWidth(0);
int texHeight = gstate.getTextureHeight(0);
@@ -2987,7 +2998,8 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, s
if (!gstate_c.Use(GPU_USE_16BIT_FORMATS) || dstFmt == Draw::DataFormat::R8G8B8A8_UNORM) {
texDecFlags |= TexDecodeFlags::EXPAND32;
}
if (entry.status & TexStatus::CLUT_GPU) {
if (entry.status & (TexStatus::CLUT_GPU | TexStatus::CLUT8_INDEXED)) {
_dbg_assert_(entry.format == GE_TFMT_CLUT4 || entry.format == GE_TFMT_CLUT8);
texDecFlags |= TexDecodeFlags::TO_CLUT8;
}
+7 -5
View File
@@ -131,6 +131,10 @@ struct TextureDefinition {
// At one point we might merge the concepts of framebuffers and textures, but that
// moment is far away.
// When hashing large textures, we optimize 512x512 down to 512x272 by default, since this
// is commonly the only part accessed. If access is made above 272, we hash the entire
// texture, and set this flag to allow scaling the texture just once for the new hash.
enum class TexStatus : u16 {
VIDEO = (1 << 0),
BGRA = (1 << 1),
@@ -143,13 +147,11 @@ enum class TexStatus : u16 {
TO_SCALE = (1 << 7), // Pending texture scaling in a later frame.
IS_SCALED_OR_REPLACED = (1 << 8), // Has been scaled already (ignored for replacement checks).
TO_REPLACE = (1 << 9), // Pending texture replacement.
// When hashing large textures, we optimize 512x512 down to 512x272 by default, since this
// is commonly the only part accessed. If access is made above 272, we hash the entire
// texture, and set this flag to allow scaling the texture just once for the new hash.
IS_3D = (1 << 10),
NO_MIPS = (1 << 11), // Has bad or unusable mipmap levels.
FRAMEBUFFER_OVERLAP = (1 << 12),
FORCE_REBUILD = (1 << 13),
IS_3D = (1 << 14),
CLUT8_INDEXED = (1 << 14), // Decoded as plain CLUT8 indices instead of all the way to colors.
CLUT_GPU = (1 << 15),
};
ENUM_CLASS_BITOPS(TexStatus);
@@ -338,7 +340,7 @@ public:
void InvalidateAll(GPUInvalidationType type);
void ClearNextFrame();
TextureShaderCache &GetTextureShaderCache() { return textureShaderCache_; }
const TextureShaderCache &GetTextureShaderCache() const { return textureShaderCache_; }
virtual void ForgetLastTexture() = 0;
virtual void Clear(bool delete_them);
+5 -3
View File
@@ -132,7 +132,7 @@ Draw2DPipeline *TextureShaderCache::GetDepalettizeShader(uint32_t clutMode, GETe
return ts->pipeline ? ts : nullptr;
}
std::vector<std::string> TextureShaderCache::DebugGetShaderIDs(DebugShaderType type) {
std::vector<std::string> TextureShaderCache::DebugGetShaderIDs(DebugShaderType type) const {
std::vector<std::string> ids;
for (auto &entry : pipelineCache_) {
ids.push_back(StringFromFormat("%08x", entry.first));
@@ -140,9 +140,11 @@ std::vector<std::string> TextureShaderCache::DebugGetShaderIDs(DebugShaderType t
return ids;
}
std::string TextureShaderCache::DebugGetShaderString(const std::string &idstr, DebugShaderType type, DebugShaderStringType stringType) {
std::string TextureShaderCache::DebugGetShaderString(const std::string &idstr, DebugShaderType type, DebugShaderStringType stringType) const {
uint32_t id = 0;
sscanf(idstr.c_str(), "%08x", &id);
if (sscanf(idstr.c_str(), "%08x", &id) == 0) {
return "";
}
auto iter = pipelineCache_.find(id);
if (iter == pipelineCache_.end())
return "";
+2 -2
View File
@@ -63,8 +63,8 @@ public:
Draw::SamplerState *GetSampler(bool linearFilter);
void Clear();
std::vector<std::string> DebugGetShaderIDs(DebugShaderType type);
std::string DebugGetShaderString(const std::string &id, DebugShaderType type, DebugShaderStringType stringType);
std::vector<std::string> DebugGetShaderIDs(DebugShaderType type) const;
std::string DebugGetShaderString(const std::string &id, DebugShaderType type, DebugShaderStringType stringType) const;
void DeviceLost();
void DeviceRestore(Draw::DrawContext *draw);
-1
View File
@@ -225,7 +225,6 @@ void TextureCacheD3D11::BindTexture(TexCacheEntry *entry, bool flatZ) {
ComPtr<ID3D11SamplerState> state;
samplerCache_.GetOrCreateSampler(device_, samplerKey, &state);
context_->PSSetSamplers(0, 1, state.GetAddressOf());
gstate_c.SetUseShaderDepal(ShaderDepalMode::OFF);
}
void TextureCacheD3D11::ApplySamplingParams(const SamplerCacheKey &key) {
-1
View File
@@ -205,7 +205,6 @@ void TextureCacheGLES::BindTexture(TexCacheEntry *entry, bool flatZ) {
int maxLevel = (entry->status & TexStatus::NO_MIPS) ? 0 : entry->maxLevel;
SamplerCacheKey samplerKey = GetSamplingParams(maxLevel, entry, flatZ);
ApplySamplingParams(samplerKey);
gstate_c.SetUseShaderDepal(ShaderDepalMode::OFF);
}
void TextureCacheGLES::Unbind() {
+8 -6
View File
@@ -539,12 +539,6 @@ struct GPUStateCache {
bool IsDirty(u64 what) const {
return (dirty & what) != 0ULL;
}
void SetUseShaderDepal(ShaderDepalMode mode) {
if (mode != shaderDepalMode) {
shaderDepalMode = mode;
Dirty(DIRTY_FRAGMENTSHADER_STATE);
}
}
void SetTextureSolidAlpha(bool solidAlpha) {
if (solidAlpha != textureSolidAlpha) {
textureSolidAlpha = solidAlpha;
@@ -702,6 +696,14 @@ public:
ShaderDepalMode shaderDepalMode;
GEBufferFormat depalTextureFormat;
void SetShaderDepal(ShaderDepalMode mode, GEBufferFormat texFormat = {}) {
if (mode != shaderDepalMode || (mode != ShaderDepalMode::OFF && texFormat != depalTextureFormat)) {
shaderDepalMode = mode;
depalTextureFormat = texFormat;
Dirty(DIRTY_FRAGMENTSHADER_STATE);
}
}
u32 getRelativeAddress(u32 data) const {
u32 baseExtended = ((gstate.base & 0x000F0000) << 8) | data;
return (offsetAddr + baseExtended) & 0x0FFFFFFF;
-1
View File
@@ -587,7 +587,6 @@ void TextureCacheVulkan::BindTexture(TexCacheEntry *entry, bool flatZ) {
curSampler_ = samplerCache_.GetOrCreateSampler(samplerKey);
imageView_ = entry->vkTex->GetImageView();
drawEngine_->SetDepalTexture(VK_NULL_HANDLE, false);
gstate_c.SetUseShaderDepal(ShaderDepalMode::OFF);
}
void TextureCacheVulkan::ApplySamplingParams(const SamplerCacheKey &key) {