Merge pull request #15869 from hrydgard/fix-framebuffer-matching

Fix bug in framebuffer matching where the wrong format was checked
This commit is contained in:
Unknown W. Brackets authored and GitHub committed 2022-08-19 23:26:49 -07:00
commit 21cf6a6f04
7 files changed
+60 -30

No files matched your search

+3 -3
View File
@@ -44,7 +44,7 @@ static const VaryingDef varyings[1] = {
{ "vec2", "v_texcoord", Draw::SEM_TEXCOORD0, 0, "highp" },
};
// Uses integer instructions available since OpenGL 3.0. Suitable for ES 3.0 as well.
// 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) {
const int shift = config.shift;
const int mask = config.mask;
@@ -128,7 +128,7 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config, con
writer.C(" vec4 outColor = ").SampleTexture2D("pal", "uv").C(";\n");
}
// FP only, to suit GL(ES) 2.0
// FP only, to suit GL(ES) 2.0 and DX9
void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config, const ShaderLanguageDesc &lang) {
char lookupMethod[128] = "index.r";
@@ -249,7 +249,7 @@ void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config, c
// index_multiplier -= 0.01f / texturePixels;
if (!formatOK) {
ERROR_LOG_REPORT_ONCE(depal, G3D, "%i depal unsupported: shift=%i mask=%02x offset=%d", config.pixelFormat, shift, mask, config.startPos);
ERROR_LOG_REPORT_ONCE(depal, G3D, "%s depal unsupported: shift=%d mask=%02x offset=%d", GeBufferFormatToString(config.pixelFormat), shift, mask, config.startPos);
}
// Offset by half a texel (plus clutBase) to turn NEAREST filtering into FLOOR.
+36 -23
View File
@@ -515,6 +515,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
nextNeedsChange_ = false;
// Might need a rebuild if the hash fails, but that will be set later.
nextNeedsRebuild_ = false;
failedTexture_ = false;
VERBOSE_LOG(G3D, "Texture at %08x found in cache, applying", texaddr);
return entry; //Done!
} else {
@@ -610,10 +611,9 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
gstate_c.curTextureHeight = h;
gstate_c.SetTextureIs3D((entry->status & TexCacheEntry::STATUS_3D) != 0);
failedTexture_ = false;
nextTexture_ = entry;
if (nextFramebufferTexture_) {
nextFramebufferTexture_ = nullptr; // in case it was accidentally set somehow?
}
nextFramebufferTexture_ = nullptr;
nextNeedsRehash_ = true;
// We still need to rebuild, to allocate a texture. But we'll bail early.
nextNeedsRebuild_ = true;
@@ -633,7 +633,7 @@ std::vector<AttachCandidate> TextureCacheCommon::GetFramebufferCandidates(const
candidates.push_back(AttachCandidate{ match, entry, framebuffer, RASTER_COLOR, framebuffer->colorBindSeq });
}
match = {};
if (gstate_c.Supports(GPU_SUPPORTS_DEPTH_TEXTURE) && MatchFramebuffer(entry, framebuffer, texAddrOffset, RASTER_DEPTH, &match)) {
if (MatchFramebuffer(entry, framebuffer, texAddrOffset, RASTER_DEPTH, &match)) {
candidates.push_back(AttachCandidate{ match, entry, framebuffer, RASTER_DEPTH, framebuffer->depthBindSeq });
}
}
@@ -868,6 +868,7 @@ bool TextureCacheCommon::MatchFramebuffer(
uint32_t fb_address = channel == RASTER_DEPTH ? framebuffer->z_address : framebuffer->fb_address;
uint32_t fb_stride = channel == RASTER_DEPTH ? framebuffer->z_stride : framebuffer->fb_stride;
GEBufferFormat fb_format = channel == RASTER_DEPTH ? GE_FORMAT_DEPTH16 : framebuffer->format;
if (channel == RASTER_DEPTH && framebuffer->z_address == framebuffer->fb_address) {
// Try to avoid silly matches to somewhat malformed buffers.
@@ -913,14 +914,14 @@ bool TextureCacheCommon::MatchFramebuffer(
}
// NOTE: This check is okay because the first texture formats are the same as the buffer formats.
if (IsTextureFormatBufferCompatible(entry.format)) {
if (TextureFormatMatchesBufferFormat(entry.format, framebuffer->format) || (framebuffer->usageFlags & FB_USAGE_BLUE_TO_ALPHA)) {
if (TextureFormatMatchesBufferFormat(entry.format, fb_format) || (framebuffer->usageFlags & FB_USAGE_BLUE_TO_ALPHA)) {
return true;
} else if (IsTextureFormat16Bit(entry.format) && IsBufferFormat16Bit(framebuffer->format)) {
WARN_LOG_ONCE(diffFormat1, G3D, "Texturing from framebuffer with reinterpretable format: %s != %s", GeTextureFormatToString(entry.format), GeBufferFormatToString(framebuffer->format));
} else if (IsTextureFormat16Bit(entry.format) && IsBufferFormat16Bit(fb_format) && channel == RASTER_COLOR) {
WARN_LOG_ONCE(diffFormat1, G3D, "Texturing from framebuffer with reinterpretable format: %s != %s", GeTextureFormatToString(entry.format), GeBufferFormatToString(fb_format));
*matchInfo = FramebufferMatchInfo{ 0, 0, true, TextureFormatToBufferFormat(entry.format) };
return true;
} else {
WARN_LOG_ONCE(diffFormat2, G3D, "Texturing from framebuffer with incompatible formats %s != %s", GeTextureFormatToString(entry.format), GeBufferFormatToString(framebuffer->format));
WARN_LOG_ONCE(diffFormat2, G3D, "Not texturing from framebuffer with incompatible formats %s != %s", GeTextureFormatToString(entry.format), GeBufferFormatToString(fb_format));
return false;
}
} else {
@@ -935,9 +936,9 @@ bool TextureCacheCommon::MatchFramebuffer(
// Check works for D16 too (???)
const bool matchingClutFormat =
(channel != RASTER_COLOR && entry.format == GE_TFMT_CLUT16) ||
(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);
(fb_format == GE_FORMAT_DEPTH16 && entry.format == GE_TFMT_CLUT16) ||
(fb_format == GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT32) ||
(fb_format != GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT16);
const u32 bitOffset = (texaddr - addr) * 8;
if (bitOffset != 0) {
@@ -984,15 +985,15 @@ bool TextureCacheCommon::MatchFramebuffer(
}
return true;
} else if (IsClutFormat((GETextureFormat)(entry.format)) || IsDXTFormat((GETextureFormat)(entry.format))) {
WARN_LOG_ONCE(fourEightBit, G3D, "%s format not supported when texturing from framebuffer of format %s", GeTextureFormatToString(entry.format), GeBufferFormatToString(framebuffer->format));
WARN_LOG_ONCE(fourEightBit, G3D, "%s format not supported when texturing from framebuffer of format %s", GeTextureFormatToString(entry.format), GeBufferFormatToString(fb_format));
return false;
}
// This is either normal or we failed to generate a shader to depalettize
if ((int)framebuffer->format == (int)entry.format || matchingClutFormat) {
if ((int)framebuffer->format != (int)entry.format) {
if ((int)fb_format == (int)entry.format || matchingClutFormat) {
if ((int)fb_format != (int)entry.format) {
WARN_LOG_ONCE(diffFormat2, G3D, "Texturing from framebuffer with different formats %s != %s at %08x",
GeTextureFormatToString(entry.format), GeBufferFormatToString(framebuffer->format), fb_address);
GeTextureFormatToString(entry.format), GeBufferFormatToString(fb_format), fb_address);
return true;
} else {
WARN_LOG_ONCE(subarea, G3D, "Texturing from framebuffer at %08x +%dx%d", fb_address, matchInfo->xOffset, matchInfo->yOffset);
@@ -1000,7 +1001,7 @@ bool TextureCacheCommon::MatchFramebuffer(
}
} else {
WARN_LOG_ONCE(diffFormat2, G3D, "Texturing from framebuffer with incompatible format %s != %s at %08x",
GeTextureFormatToString(entry.format), GeBufferFormatToString(framebuffer->format), fb_address);
GeTextureFormatToString(entry.format), GeBufferFormatToString(fb_format), fb_address);
return false;
}
}
@@ -1019,10 +1020,12 @@ void TextureCacheCommon::SetTextureFramebuffer(const AttachCandidate &candidate)
_dbg_assert_msg_(framebuffer != nullptr, "Framebuffer must not be null.");
framebuffer->usageFlags |= FB_USAGE_TEXTURE;
if (framebufferManager_->UseBufferedRendering()) {
// Keep the framebuffer alive.
framebuffer->last_frame_used = gpuStats.numFlips;
// Keep the framebuffer alive.
framebuffer->last_frame_used = gpuStats.numFlips;
nextFramebufferTextureChannel_ = RASTER_COLOR;
if (framebufferManager_->UseBufferedRendering()) {
// We need to force it, since we may have set it on a texture before attaching.
gstate_c.curTextureWidth = framebuffer->bufferWidth;
gstate_c.curTextureHeight = framebuffer->bufferHeight;
@@ -1041,7 +1044,15 @@ void TextureCacheCommon::SetTextureFramebuffer(const AttachCandidate &candidate)
gstate_c.SetNeedShaderTexclamp(true);
}
nextFramebufferTexture_ = framebuffer;
if (candidate.channel == RASTER_DEPTH && !gstate_c.Supports(GPU_SUPPORTS_DEPTH_TEXTURE)) {
// Flag to bind a null texture if we can't support depth textures.
// Should only happen on old OpenGL.
nextFramebufferTexture_ = nullptr;
failedTexture_ = true;
} else {
nextFramebufferTexture_ = framebuffer;
nextFramebufferTextureChannel_ = candidate.channel;
}
nextTexture_ = nullptr;
} else {
if (framebuffer->fbo) {
@@ -1752,10 +1763,12 @@ void TextureCacheCommon::ApplyTexture() {
if (!entry) {
// Maybe we bound a framebuffer?
InvalidateLastTexture();
if (nextFramebufferTexture_) {
bool depth = Memory::IsDepthTexVRAMAddress(gstate.getTextureAddress(0));
if (failedTexture_) {
// Backends should handle this by binding a black texture with 0 alpha.
BindTexture(nullptr);
} else if (nextFramebufferTexture_) {
// ApplyTextureFrameBuffer is responsible for setting SetTextureFullAlpha.
ApplyTextureFramebuffer(nextFramebufferTexture_, gstate.getTextureFormat(), depth ? RASTER_DEPTH : RASTER_COLOR);
ApplyTextureFramebuffer(nextFramebufferTexture_, gstate.getTextureFormat(), nextFramebufferTextureChannel_);
nextFramebufferTexture_ = nullptr;
}
+2
View File
@@ -433,7 +433,9 @@ protected:
SimpleBuf<u32> tmpTexBufRearrange_;
TexCacheEntry *nextTexture_ = nullptr;
bool failedTexture_ = false;
VirtualFramebuffer *nextFramebufferTexture_ = nullptr;
RasterChannel nextFramebufferTextureChannel_ = RASTER_COLOR;
u32 clutHash_ = 0;
+5
View File
@@ -236,6 +236,11 @@ void TextureCacheD3D11::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBa
}
void TextureCacheD3D11::BindTexture(TexCacheEntry *entry) {
if (!entry) {
ID3D11ShaderResourceView *textureView = nullptr;
context_->PSSetShaderResources(0, 1, &textureView);
return;
}
ID3D11ShaderResourceView *textureView = DxView(entry);
if (textureView != lastBoundTexture) {
context_->PSSetShaderResources(0, 1, &textureView);
+5 -1
View File
@@ -204,6 +204,10 @@ void TextureCacheDX9::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase
}
void TextureCacheDX9::BindTexture(TexCacheEntry *entry) {
if (!entry) {
device_->SetTexture(0, nullptr);
return;
}
LPDIRECT3DBASETEXTURE9 texture = DxTex(entry);
if (texture != lastBoundTexture) {
device_->SetTexture(0, texture);
@@ -215,7 +219,7 @@ void TextureCacheDX9::BindTexture(TexCacheEntry *entry) {
}
void TextureCacheDX9::Unbind() {
device_->SetTexture(0, NULL);
device_->SetTexture(0, nullptr);
InvalidateLastTexture();
}
+1
View File
@@ -6,6 +6,7 @@ const char *GeBufferFormatToString(GEBufferFormat fmt) {
case GE_FORMAT_5551: return "5551";
case GE_FORMAT_565: return "565";
case GE_FORMAT_8888: return "8888";
case GE_FORMAT_DEPTH16: return "DEPTH16";
default: return "N/A";
}
}
+8 -3
View File
@@ -388,14 +388,19 @@ void TextureCacheVulkan::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutB
}
void TextureCacheVulkan::BindTexture(TexCacheEntry *entry) {
_assert_(entry);
_assert_(entry->vkTex);
if (!entry) {
imageView_ = VK_NULL_HANDLE;
curSampler_ = VK_NULL_HANDLE;
return;
}
_dbg_assert_(entry->vkTex);
entry->vkTex->Touch();
imageView_ = entry->vkTex->GetImageView();
int maxLevel = (entry->status & TexCacheEntry::STATUS_NO_MIPS) ? 0 : entry->maxLevel;
SamplerCacheKey samplerKey = GetSamplingParams(maxLevel, entry);
curSampler_ = samplerCache_.GetOrCreateSampler(samplerKey);
imageView_ = entry->vkTex->GetImageView();
drawEngine_->SetDepalTexture(VK_NULL_HANDLE);
gstate_c.SetUseShaderDepal(false);
}