mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-09 20:46:24 +02:00
Merge pull request #13429 from hrydgard/more-tex-filtering-cleanups
More tex filtering code cleanups
This commit is contained in:
16 files changed
+144
-310
No files matched your search
@@ -146,19 +146,23 @@ static int TexLog2(float delta) {
|
||||
return useful - 127 * 256;
|
||||
}
|
||||
|
||||
void TextureCacheCommon::GetSamplingParams(int &minFilt, int &magFilt, bool &sClamp, bool &tClamp, float &lodBias, int maxLevel, u32 addr, GETexLevelMode &mode) {
|
||||
minFilt = gstate.texfilter & 0x7;
|
||||
magFilt = gstate.isMagnifyFilteringEnabled();
|
||||
sClamp = gstate.isTexCoordClampedS();
|
||||
tClamp = gstate.isTexCoordClampedT();
|
||||
SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, u32 texAddr) {
|
||||
SamplerCacheKey key;
|
||||
|
||||
int minFilt = gstate.texfilter & 0x7;
|
||||
key.minFilt = minFilt & 1;
|
||||
key.mipEnable = (minFilt >> 2) & 1;
|
||||
key.mipFilt = (minFilt >> 1) & 1;
|
||||
key.magFilt = gstate.isMagnifyFilteringEnabled();
|
||||
key.sClamp = gstate.isTexCoordClampedS();
|
||||
key.tClamp = gstate.isTexCoordClampedT();
|
||||
key.aniso = false;
|
||||
|
||||
GETexLevelMode mipMode = gstate.getTexLevelMode();
|
||||
mode = mipMode;
|
||||
|
||||
bool autoMip = mipMode == GE_TEXLEVEL_MODE_AUTO;
|
||||
|
||||
// TODO: Slope mipmap bias is still not well understood.
|
||||
lodBias = (float)gstate.getTexLevelOffset16() * (1.0f / 16.0f);
|
||||
float lodBias = (float)gstate.getTexLevelOffset16() * (1.0f / 16.0f);
|
||||
if (mipMode == GE_TEXLEVEL_MODE_SLOPE) {
|
||||
lodBias += 1.0f + TexLog2(gstate.getTextureLodSlope()) * (1.0f / 256.0f);
|
||||
}
|
||||
@@ -171,72 +175,18 @@ void TextureCacheCommon::GetSamplingParams(int &minFilt, int &magFilt, bool &sCl
|
||||
|
||||
if (noMip) {
|
||||
// Enforce no mip filtering, for safety.
|
||||
minFilt &= 1; // no mipmaps yet
|
||||
key.mipEnable = false;
|
||||
key.mipFilt = 0;
|
||||
lodBias = 0.0f;
|
||||
}
|
||||
|
||||
if (!(magFilt & 1) && addr != 0 && g_Config.iTexFiltering != TEX_FILTER_FORCE_NEAREST) {
|
||||
if (videos_.find(addr & 0x3FFFFFFF) != videos_.end()) {
|
||||
// Enforce bilinear filtering on magnification.
|
||||
magFilt |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtering overrides
|
||||
switch (g_Config.iTexFiltering) {
|
||||
case TEX_FILTER_AUTO:
|
||||
// Follow what the game wants. We just do a single heuristic change to avoid bleeding of wacky color test colors
|
||||
// in higher resolution (used by some games for sprites, and they accidentally have linear filter on).
|
||||
if (gstate.isModeThrough() && g_Config.iInternalResolution != 1) {
|
||||
bool uglyColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue() && gstate.getColorTestRef() != 0;
|
||||
if (uglyColorTest) {
|
||||
// Force to nearest.
|
||||
magFilt &= ~1;
|
||||
minFilt &= ~1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TEX_FILTER_FORCE_LINEAR:
|
||||
// Override to linear filtering if there's no alpha or color testing going on.
|
||||
if ((!gstate.isColorTestEnabled() || IsColorTestTriviallyTrue()) &&
|
||||
(!gstate.isAlphaTestEnabled() || IsAlphaTestTriviallyTrue())) {
|
||||
magFilt |= 1;
|
||||
minFilt |= 1;
|
||||
}
|
||||
break;
|
||||
case TEX_FILTER_FORCE_NEAREST:
|
||||
default:
|
||||
// Just force to nearest without checks. Safe (but ugly).
|
||||
magFilt &= ~1;
|
||||
minFilt &= ~1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCacheCommon::UpdateSamplingParams(int maxLevel, u32 texAddr, SamplerCacheKey &key) {
|
||||
// TODO: Make GetSamplingParams write SamplerCacheKey directly
|
||||
int minFilt;
|
||||
int magFilt;
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GETexLevelMode mode;
|
||||
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, maxLevel, texAddr, mode);
|
||||
key.minFilt = minFilt & 1;
|
||||
key.mipEnable = (minFilt >> 2) & 1;
|
||||
key.mipFilt = (minFilt >> 1) & 1;
|
||||
key.magFilt = magFilt & 1;
|
||||
key.sClamp = sClamp;
|
||||
key.tClamp = tClamp;
|
||||
key.aniso = false;
|
||||
|
||||
if (!key.mipEnable) {
|
||||
key.maxLevel = 0;
|
||||
key.minLevel = 0;
|
||||
key.lodBias = 0;
|
||||
key.mipFilt = 0;
|
||||
} else {
|
||||
switch (mode) {
|
||||
switch (mipMode) {
|
||||
case GE_TEXLEVEL_MODE_AUTO:
|
||||
key.maxLevel = maxLevel * 256;
|
||||
key.minLevel = 0;
|
||||
@@ -261,6 +211,67 @@ void TextureCacheCommon::UpdateSamplingParams(int maxLevel, u32 texAddr, Sampler
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Video bilinear override
|
||||
if (!key.magFilt && texAddr != 0) {
|
||||
if (videos_.find(texAddr & 0x3FFFFFFF) != videos_.end()) {
|
||||
// Enforce bilinear filtering on magnification.
|
||||
key.magFilt = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtering overrides
|
||||
switch (g_Config.iTexFiltering) {
|
||||
case TEX_FILTER_AUTO:
|
||||
// Follow what the game wants. We just do a single heuristic change to avoid bleeding of wacky color test colors
|
||||
// in higher resolution (used by some games for sprites, and they accidentally have linear filter on).
|
||||
if (gstate.isModeThrough() && g_Config.iInternalResolution != 1) {
|
||||
bool uglyColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue() && gstate.getColorTestRef() != 0;
|
||||
if (uglyColorTest) {
|
||||
// Force to nearest.
|
||||
key.magFilt = 0;
|
||||
key.minFilt = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TEX_FILTER_FORCE_LINEAR:
|
||||
// Override to linear filtering if there's no alpha or color testing going on.
|
||||
if ((!gstate.isColorTestEnabled() || IsColorTestTriviallyTrue()) &&
|
||||
(!gstate.isAlphaTestEnabled() || IsAlphaTestTriviallyTrue())) {
|
||||
key.magFilt = 1;
|
||||
key.minFilt = 1;
|
||||
key.mipFilt = 1;
|
||||
}
|
||||
break;
|
||||
case TEX_FILTER_FORCE_NEAREST:
|
||||
default:
|
||||
// Just force to nearest without checks. Safe (but ugly).
|
||||
key.magFilt = 0;
|
||||
key.minFilt = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
SamplerCacheKey TextureCacheCommon::GetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight) {
|
||||
SamplerCacheKey key = GetSamplingParams(0, 0);
|
||||
|
||||
// Kill any mipmapping settings.
|
||||
key.mipEnable = false;
|
||||
key.minFilt &= 1;
|
||||
key.mipFilt = 0;
|
||||
key.magFilt &= 1;
|
||||
key.aniso = 0.0;
|
||||
|
||||
// Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case.
|
||||
int w = gstate.getTextureWidth(0);
|
||||
int h = gstate.getTextureHeight(0);
|
||||
if (w != bufferWidth || h != bufferHeight) {
|
||||
key.sClamp = true;
|
||||
key.tClamp = true;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
void TextureCacheCommon::UpdateMaxSeenV(TexCacheEntry *entry, bool throughMode) {
|
||||
|
||||
@@ -284,8 +284,9 @@ protected:
|
||||
}
|
||||
|
||||
u32 EstimateTexMemoryUsage(const TexCacheEntry *entry);
|
||||
void GetSamplingParams(int &minFilt, int &magFilt, bool &sClamp, bool &tClamp, float &lodBias, int maxLevel, u32 addr, GETexLevelMode &mode);
|
||||
void UpdateSamplingParams(int maxLevel, u32 texAddr, SamplerCacheKey &key); // Used by D3D11 and Vulkan.
|
||||
|
||||
SamplerCacheKey GetSamplingParams(int maxLevel, u32 texAddr);
|
||||
SamplerCacheKey GetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight);
|
||||
void UpdateMaxSeenV(TexCacheEntry *entry, bool throughMode);
|
||||
|
||||
FramebufferMatchInfo MatchFramebuffer(const TextureDefinition &entry, VirtualFramebuffer *framebuffer, u32 texaddrOffset, FramebufferNotificationChannel channel) const;
|
||||
|
||||
@@ -17,19 +17,19 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <d3d11.h>
|
||||
|
||||
#include "GPU/GPUCommon.h"
|
||||
#include "GPU/D3D11/DrawEngineD3D11.h"
|
||||
#include "GPU/D3D11/TextureCacheD3D11.h"
|
||||
#include "GPU/D3D11/DepalettizeShaderD3D11.h"
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
|
||||
class FramebufferManagerD3D11;
|
||||
class ShaderManagerD3D11;
|
||||
class LinkedShaderD3D11;
|
||||
class TextureCacheD3D11;
|
||||
|
||||
class GPU_D3D11 : public GPUCommon {
|
||||
public:
|
||||
|
||||
@@ -156,31 +156,6 @@ void TextureCacheD3D11::InvalidateLastTexture(TexCacheEntry *entry) {
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCacheD3D11::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) {
|
||||
int minFilt;
|
||||
int magFilt;
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GETexLevelMode mode;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0, mode);
|
||||
|
||||
key.minFilt = minFilt & 1;
|
||||
key.mipFilt = 0;
|
||||
key.magFilt = magFilt & 1;
|
||||
key.sClamp = sClamp;
|
||||
key.tClamp = tClamp;
|
||||
|
||||
// Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case.
|
||||
// This happens whether we have OES_texture_npot or not.
|
||||
int w = gstate.getTextureWidth(0);
|
||||
int h = gstate.getTextureHeight(0);
|
||||
if (w != bufferWidth || h != bufferHeight) {
|
||||
key.sClamp = true;
|
||||
key.tClamp = true;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCacheD3D11::StartFrame() {
|
||||
InvalidateLastTexture();
|
||||
timesInvalidatedAllThisFrame_ = 0;
|
||||
@@ -239,10 +214,9 @@ void TextureCacheD3D11::BindTexture(TexCacheEntry *entry) {
|
||||
context_->PSSetShaderResources(0, 1, &textureView);
|
||||
lastBoundTexture = textureView;
|
||||
}
|
||||
SamplerCacheKey key{};
|
||||
int maxLevel = (entry->status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry->maxLevel;
|
||||
UpdateSamplingParams(maxLevel, entry->addr, key);
|
||||
ID3D11SamplerState *state = samplerCache_.GetOrCreateSampler(device_, key);
|
||||
SamplerCacheKey samplerKey = GetSamplingParams(maxLevel, entry->addr);
|
||||
ID3D11SamplerState *state = samplerCache_.GetOrCreateSampler(device_, samplerKey);
|
||||
context_->PSSetSamplers(0, 1, &state);
|
||||
}
|
||||
|
||||
@@ -428,8 +402,8 @@ void TextureCacheD3D11::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer,
|
||||
gstate_c.SetTextureFullAlpha(gstate.getTextureFormat() == GE_TFMT_5650);
|
||||
framebufferManagerD3D11_->RebindFramebuffer("RebindFramebuffer - ApplyTextureFramebuffer"); // Probably not necessary.
|
||||
}
|
||||
SamplerCacheKey samplerKey{};
|
||||
SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, samplerKey);
|
||||
|
||||
SamplerCacheKey samplerKey = GetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight);
|
||||
ID3D11SamplerState *state = samplerCache_.GetOrCreateSampler(device_, samplerKey);
|
||||
context_->PSSetSamplers(0, 1, &state);
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ public:
|
||||
void ForgetLastTexture() override;
|
||||
void InvalidateLastTexture(TexCacheEntry *entry = nullptr) override;
|
||||
|
||||
void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key);
|
||||
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -17,13 +17,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "GPU/GPUCommon.h"
|
||||
#include "GPU/Directx9/FramebufferManagerDX9.h"
|
||||
#include "GPU/Directx9/DrawEngineDX9.h"
|
||||
#include "GPU/Directx9/TextureCacheDX9.h"
|
||||
#include "GPU/Directx9/DepalettizeShaderDX9.h"
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
|
||||
@@ -31,6 +30,7 @@ namespace DX9 {
|
||||
|
||||
class ShaderManagerDX9;
|
||||
class LinkedShaderDX9;
|
||||
class TextureCacheDX9;
|
||||
|
||||
class GPU_DX9 : public GPUCommon {
|
||||
public:
|
||||
|
||||
@@ -119,101 +119,24 @@ D3DFORMAT getClutDestFormat(GEPaletteFormat format) {
|
||||
return D3DFMT_A8R8G8B8;
|
||||
}
|
||||
|
||||
static const u8 MinFilt[8] = {
|
||||
D3DTEXF_POINT,
|
||||
D3DTEXF_LINEAR,
|
||||
D3DTEXF_POINT,
|
||||
D3DTEXF_LINEAR,
|
||||
D3DTEXF_POINT, // GL_NEAREST_MIPMAP_NEAREST,
|
||||
D3DTEXF_LINEAR, // GL_LINEAR_MIPMAP_NEAREST,
|
||||
D3DTEXF_POINT, // GL_NEAREST_MIPMAP_LINEAR,
|
||||
D3DTEXF_LINEAR, // GL_LINEAR_MIPMAP_LINEAR,
|
||||
};
|
||||
void TextureCacheDX9::ApplySamplingParams(const SamplerCacheKey &key) {
|
||||
dxstate.texMinFilter.set(key.minFilt ? D3DTEXF_LINEAR : D3DTEXF_POINT);
|
||||
dxstate.texMipFilter.set(key.mipFilt ? D3DTEXF_LINEAR : D3DTEXF_POINT);
|
||||
dxstate.texMagFilter.set(key.magFilt ? D3DTEXF_LINEAR : D3DTEXF_POINT);
|
||||
|
||||
static const u8 MipFilt[8] = {
|
||||
D3DTEXF_NONE,
|
||||
D3DTEXF_NONE,
|
||||
D3DTEXF_NONE,
|
||||
D3DTEXF_NONE,
|
||||
D3DTEXF_POINT, // GL_NEAREST_MIPMAP_NEAREST,
|
||||
D3DTEXF_POINT, // GL_LINEAR_MIPMAP_NEAREST,
|
||||
D3DTEXF_LINEAR, // GL_NEAREST_MIPMAP_LINEAR,
|
||||
D3DTEXF_LINEAR, // GL_LINEAR_MIPMAP_LINEAR,
|
||||
};
|
||||
// DX9 mip levels are .. odd. The "max level" sets the LARGEST mip to use.
|
||||
// We can enforce only the top mip level by setting a massive negative lod bias.
|
||||
|
||||
static const u8 MagFilt[2] = {
|
||||
D3DTEXF_POINT,
|
||||
D3DTEXF_LINEAR
|
||||
};
|
||||
|
||||
void TextureCacheDX9::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
|
||||
int minFilt;
|
||||
int magFilt;
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GETexLevelMode mode;
|
||||
u8 maxLevel = (entry.status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry.maxLevel;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, maxLevel, entry.addr, mode);
|
||||
|
||||
if (maxLevel != 0) {
|
||||
if (mode == GE_TEXLEVEL_MODE_AUTO) {
|
||||
dxstate.texMaxMipLevel.set(0);
|
||||
dxstate.texMipLodBias.set(lodBias);
|
||||
} else if (mode == GE_TEXLEVEL_MODE_CONST) {
|
||||
// TODO: This is just an approximation - texMaxMipLevel sets the lowest numbered mip to use.
|
||||
// Unfortunately, this doesn't support a const 1.5 or etc.
|
||||
dxstate.texMaxMipLevel.set(std::max(0, std::min((int)maxLevel, (int)lodBias)));
|
||||
dxstate.texMipLodBias.set(-1000.0f);
|
||||
} else { // if (mode == GE_TEXLEVEL_MODE_SLOPE{
|
||||
dxstate.texMaxMipLevel.set(0);
|
||||
dxstate.texMipLodBias.set(0.0f);
|
||||
}
|
||||
} else {
|
||||
if (!key.mipEnable) {
|
||||
dxstate.texMaxMipLevel.set(0);
|
||||
dxstate.texMipLodBias.set(0.0f);
|
||||
dxstate.texMipLodBias.set(-100.0f);
|
||||
} else {
|
||||
dxstate.texMipLodBias.set((float)key.lodBias / 256.0f);
|
||||
dxstate.texMaxMipLevel.set(key.minLevel / 256);
|
||||
}
|
||||
|
||||
D3DTEXTUREFILTERTYPE minf = (D3DTEXTUREFILTERTYPE)MinFilt[minFilt];
|
||||
D3DTEXTUREFILTERTYPE mipf = (D3DTEXTUREFILTERTYPE)MipFilt[minFilt];
|
||||
D3DTEXTUREFILTERTYPE magf = (D3DTEXTUREFILTERTYPE)MagFilt[magFilt];
|
||||
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_ANISOTROPY) && g_Config.iAnisotropyLevel > 0 && minf == D3DTEXF_LINEAR) {
|
||||
minf = D3DTEXF_ANISOTROPIC;
|
||||
}
|
||||
|
||||
dxstate.texMinFilter.set(minf);
|
||||
dxstate.texMipFilter.set(mipf);
|
||||
dxstate.texMagFilter.set(magf);
|
||||
dxstate.texAddressU.set(sClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP);
|
||||
dxstate.texAddressV.set(tClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP);
|
||||
}
|
||||
|
||||
void TextureCacheDX9::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight) {
|
||||
int minFilt;
|
||||
int magFilt;
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GETexLevelMode mode;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0, mode);
|
||||
|
||||
dxstate.texMinFilter.set(MinFilt[minFilt]);
|
||||
dxstate.texMipFilter.set(MipFilt[minFilt]);
|
||||
dxstate.texMagFilter.set(MagFilt[magFilt]);
|
||||
dxstate.texMipLodBias.set(0.0f);
|
||||
dxstate.texMaxMipLevel.set(0.0f);
|
||||
|
||||
// Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case.
|
||||
// This happens whether we have OES_texture_npot or not.
|
||||
int w = gstate.getTextureWidth(0);
|
||||
int h = gstate.getTextureHeight(0);
|
||||
if (w != bufferWidth || h != bufferHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
dxstate.texAddressU.set(sClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP);
|
||||
dxstate.texAddressV.set(tClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP);
|
||||
dxstate.texAddressU.set(key.sClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP);
|
||||
dxstate.texAddressV.set(key.tClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP);
|
||||
}
|
||||
|
||||
void TextureCacheDX9::StartFrame() {
|
||||
@@ -236,7 +159,6 @@ void TextureCacheDX9::StartFrame() {
|
||||
DWORD anisotropyLevel = aniso > maxAnisotropyLevel ? maxAnisotropyLevel : aniso;
|
||||
device_->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, anisotropyLevel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TextureCacheDX9::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) {
|
||||
@@ -281,7 +203,9 @@ void TextureCacheDX9::BindTexture(TexCacheEntry *entry) {
|
||||
device_->SetTexture(0, texture);
|
||||
lastBoundTexture = texture;
|
||||
}
|
||||
UpdateSamplingParams(*entry, false);
|
||||
int maxLevel = (entry->status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry->maxLevel;
|
||||
SamplerCacheKey samplerKey = GetSamplingParams(maxLevel, entry->addr);
|
||||
ApplySamplingParams(samplerKey);
|
||||
}
|
||||
|
||||
void TextureCacheDX9::Unbind() {
|
||||
@@ -467,7 +391,9 @@ void TextureCacheDX9::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, G
|
||||
}
|
||||
|
||||
framebufferManagerDX9_->RebindFramebuffer("RebindFramebuffer - ApplyTextureFromFramebuffer");
|
||||
SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight);
|
||||
|
||||
SamplerCacheKey samplerKey = GetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight);
|
||||
ApplySamplingParams(samplerKey);
|
||||
}
|
||||
|
||||
void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) {
|
||||
|
||||
@@ -52,8 +52,6 @@ public:
|
||||
void ForgetLastTexture() override;
|
||||
void InvalidateLastTexture(TexCacheEntry *entry = nullptr) override;
|
||||
|
||||
void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight);
|
||||
|
||||
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override;
|
||||
|
||||
protected:
|
||||
@@ -62,7 +60,8 @@ protected:
|
||||
void ReleaseTexture(TexCacheEntry *entry, bool delete_them) override;
|
||||
|
||||
private:
|
||||
void UpdateSamplingParams(TexCacheEntry &entry, bool force);
|
||||
void ApplySamplingParams(const SamplerCacheKey &key);
|
||||
|
||||
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, int scaleFactor, u32 dstFmt);
|
||||
D3DFORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
|
||||
TexCacheEntry::TexStatus CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h);
|
||||
|
||||
+3
-3
@@ -17,17 +17,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "GPU/GPUCommon.h"
|
||||
#include "GPU/GLES/FramebufferManagerGLES.h"
|
||||
#include "GPU/GLES/DrawEngineGLES.h"
|
||||
#include "GPU/GLES/TextureCacheGLES.h"
|
||||
#include "GPU/GLES/DepalettizeShaderGLES.h"
|
||||
#include "GPU/GLES/FragmentTestCacheGLES.h"
|
||||
|
||||
class ShaderManagerGLES;
|
||||
class TextureCacheGLES;
|
||||
class LinkedShader;
|
||||
|
||||
class GPU_GLES : public GPUCommon {
|
||||
|
||||
@@ -115,76 +115,19 @@ static const GLuint MagFiltGL[2] = {
|
||||
GL_LINEAR
|
||||
};
|
||||
|
||||
// This should not have to be done per texture! OpenGL is silly yo
|
||||
void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
|
||||
int minFilt;
|
||||
int magFilt;
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
u8 maxLevel = (entry.status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry.maxLevel;
|
||||
GETexLevelMode mode;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, maxLevel, entry.addr, mode);
|
||||
|
||||
void TextureCacheGLES::ApplySamplingParams(const SamplerCacheKey &key) {
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) {
|
||||
float minLod = 0.0f;
|
||||
float maxLod = 0.0f;
|
||||
if (maxLevel != 0) {
|
||||
// TODO: What about a swap of autoMip mode?
|
||||
if (true) {
|
||||
if (mode == GE_TEXLEVEL_MODE_AUTO) {
|
||||
minLod = 0.0f;
|
||||
maxLod = (float)maxLevel;
|
||||
} else if (mode == GE_TEXLEVEL_MODE_CONST) {
|
||||
minLod = std::max(0.0f, std::min((float)maxLevel, lodBias));
|
||||
maxLod = std::max(0.0f, std::min((float)maxLevel, lodBias));
|
||||
} else { // mode == GE_TEXLEVEL_MODE_SLOPE) {
|
||||
// It's incorrect to use the slope as a bias. Instead it should be passed
|
||||
// into the shader directly as an explicit lod level, with the bias on top. For now, we just kill the
|
||||
// lodBias in this mode, working around #9772.
|
||||
#ifndef USING_GLES2
|
||||
lodBias = 0.0f;
|
||||
#endif
|
||||
minLod = 0.0f;
|
||||
maxLod = (float)maxLevel;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
minLod = 0.0f;
|
||||
maxLod = 0.0f;
|
||||
}
|
||||
float minLod = (float)key.minLevel / 256.0f;
|
||||
float maxLod = (float)key.maxLevel / 256.0f;
|
||||
float lodBias = (float)key.lodBias / 256.0f;
|
||||
render_->SetTextureLod(0, minLod, maxLod, lodBias);
|
||||
}
|
||||
|
||||
float aniso = 0.0f;
|
||||
render_->SetTextureSampler(0, sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso);
|
||||
}
|
||||
|
||||
void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, bool forcePoint) {
|
||||
int minFilt;
|
||||
int magFilt;
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GETexLevelMode mode;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0, mode);
|
||||
|
||||
minFilt &= 1; // framebuffers can't mipmap.
|
||||
if (forcePoint) {
|
||||
minFilt &= ~1;
|
||||
magFilt &= ~1;
|
||||
}
|
||||
|
||||
// Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case.
|
||||
// This happens whether we have OES_texture_npot or not.
|
||||
int w = gstate.getTextureWidth(0);
|
||||
int h = gstate.getTextureHeight(0);
|
||||
if (w != bufferWidth || h != bufferHeight) {
|
||||
sClamp = true;
|
||||
tClamp = true;
|
||||
}
|
||||
float aniso = 0.0f;
|
||||
render_->SetTextureSampler(TEX_SLOT_PSP_TEXTURE, sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso);
|
||||
int magKey = ((int)key.mipEnable << 2) | ((int)key.mipFilt << 1) | ((int)key.magFilt);
|
||||
render_->SetTextureSampler(0,
|
||||
key.sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, key.tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT,
|
||||
MagFiltGL[magKey], key.minFilt ? GL_LINEAR : GL_NEAREST, aniso);
|
||||
}
|
||||
|
||||
static void ConvertColors(void *dstBuf, const void *srcBuf, Draw::DataFormat dstFmt, int numPixels) {
|
||||
@@ -287,7 +230,9 @@ void TextureCacheGLES::BindTexture(TexCacheEntry *entry) {
|
||||
render_->BindTexture(0, entry->textureName);
|
||||
lastBoundTexture = entry->textureName;
|
||||
}
|
||||
UpdateSamplingParams(*entry, false);
|
||||
int maxLevel = (entry->status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry->maxLevel;
|
||||
SamplerCacheKey samplerKey = GetSamplingParams(maxLevel, entry->addr);
|
||||
ApplySamplingParams(samplerKey);
|
||||
gstate_c.SetUseShaderDepal(false);
|
||||
}
|
||||
|
||||
@@ -415,7 +360,11 @@ void TextureCacheGLES::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer,
|
||||
render_->BindTexture(TEX_SLOT_CLUT, clutTexture);
|
||||
render_->SetTextureSampler(TEX_SLOT_CLUT, GL_REPEAT, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f);
|
||||
framebufferManagerGL_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_MAY_COPY_WITH_UV | BINDFBCOLOR_APPLY_TEX_OFFSET);
|
||||
SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, true);
|
||||
SamplerCacheKey samplerKey = GetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight);
|
||||
samplerKey.magFilt = false;
|
||||
samplerKey.minFilt = false;
|
||||
samplerKey.mipEnable = false;
|
||||
ApplySamplingParams(samplerKey);
|
||||
InvalidateLastTexture();
|
||||
|
||||
// Since we started/ended render passes, might need these.
|
||||
@@ -465,7 +414,9 @@ void TextureCacheGLES::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer,
|
||||
}
|
||||
|
||||
framebufferManagerGL_->RebindFramebuffer("ApplyTextureFramebuffer");
|
||||
SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, false);
|
||||
|
||||
SamplerCacheKey samplerKey = GetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight);
|
||||
ApplySamplingParams(samplerKey);
|
||||
|
||||
// Since we started/ended render passes, might need these.
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
|
||||
@@ -648,7 +599,9 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
|
||||
// This will rebind it, but that's okay.
|
||||
// Need to actually bind it now - it might only have gotten bound in the init phase.
|
||||
render_->BindTexture(TEX_SLOT_PSP_TEXTURE, entry->textureName);
|
||||
UpdateSamplingParams(*entry, true);
|
||||
|
||||
SamplerCacheKey samplerKey = GetSamplingParams(entry->maxLevel, entry->addr);
|
||||
ApplySamplingParams(samplerKey);
|
||||
}
|
||||
|
||||
Draw::DataFormat TextureCacheGLES::GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const {
|
||||
|
||||
@@ -63,7 +63,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, bool forcePoint);
|
||||
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override;
|
||||
|
||||
void DeviceLost();
|
||||
@@ -75,7 +74,7 @@ protected:
|
||||
void ReleaseTexture(TexCacheEntry *entry, bool delete_them) override;
|
||||
|
||||
private:
|
||||
void UpdateSamplingParams(TexCacheEntry &entry, bool force);
|
||||
void ApplySamplingParams(const SamplerCacheKey &key);
|
||||
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int scaleFactor, Draw::DataFormat dstFmt);
|
||||
Draw::DataFormat GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "Common/Vulkan/VulkanImage.h"
|
||||
#include "GPU/Vulkan/GPU_Vulkan.h"
|
||||
#include "GPU/Vulkan/VulkanUtil.h"
|
||||
#include "GPU/Vulkan/TextureCacheVulkan.h"
|
||||
|
||||
#undef DrawText
|
||||
|
||||
|
||||
@@ -17,18 +17,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "GPU/GPUCommon.h"
|
||||
#include "GPU/Vulkan/DrawEngineVulkan.h"
|
||||
#include "GPU/Vulkan/PipelineManagerVulkan.h"
|
||||
#include "GPU/Vulkan/TextureCacheVulkan.h"
|
||||
#include "GPU/Vulkan/DepalettizeShaderVulkan.h"
|
||||
|
||||
class FramebufferManagerVulkan;
|
||||
class ShaderManagerVulkan;
|
||||
class LinkedShader;
|
||||
class TextureCacheVulkan;
|
||||
|
||||
class GPU_Vulkan : public GPUCommon {
|
||||
public:
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "Core/Reporting.h"
|
||||
#include "GPU/Vulkan/GPU_Vulkan.h"
|
||||
#include "GPU/Vulkan/PipelineManagerVulkan.h"
|
||||
#include "GPU/Vulkan/TextureCacheVulkan.h"
|
||||
#include "GPU/Vulkan/FramebufferManagerVulkan.h"
|
||||
#include "GPU/Vulkan/ShaderManagerVulkan.h"
|
||||
#include "GPU/Vulkan/DrawEngineVulkan.h"
|
||||
|
||||
@@ -439,31 +439,6 @@ static const VkFilter MagFiltVK[2] = {
|
||||
VK_FILTER_LINEAR
|
||||
};
|
||||
|
||||
void TextureCacheVulkan::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) {
|
||||
int minFilt;
|
||||
int magFilt;
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GETexLevelMode mode;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0, mode);
|
||||
|
||||
key.minFilt = minFilt & 1;
|
||||
key.mipFilt = 0;
|
||||
key.magFilt = magFilt & 1;
|
||||
key.sClamp = sClamp;
|
||||
key.tClamp = tClamp;
|
||||
|
||||
// Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case.
|
||||
// This happens whether we have OES_texture_npot or not.
|
||||
int w = gstate.getTextureWidth(0);
|
||||
int h = gstate.getTextureHeight(0);
|
||||
if (w != bufferWidth || h != bufferHeight) {
|
||||
key.sClamp = true;
|
||||
key.tClamp = true;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCacheVulkan::StartFrame() {
|
||||
InvalidateLastTexture();
|
||||
depalShaderCache_->Decimate();
|
||||
@@ -541,10 +516,9 @@ void TextureCacheVulkan::BindTexture(TexCacheEntry *entry) {
|
||||
|
||||
entry->vkTex->Touch();
|
||||
imageView_ = entry->vkTex->GetImageView();
|
||||
SamplerCacheKey key{};
|
||||
int maxLevel = (entry->status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry->maxLevel;
|
||||
UpdateSamplingParams(maxLevel, entry->addr, key);
|
||||
curSampler_ = samplerCache_.GetOrCreateSampler(key);
|
||||
SamplerCacheKey samplerKey = GetSamplingParams(maxLevel, entry->addr);
|
||||
curSampler_ = samplerCache_.GetOrCreateSampler(samplerKey);
|
||||
drawEngine_->SetDepalTexture(VK_NULL_HANDLE);
|
||||
gstate_c.SetUseShaderDepal(false);
|
||||
}
|
||||
@@ -556,8 +530,7 @@ void TextureCacheVulkan::Unbind() {
|
||||
}
|
||||
|
||||
void TextureCacheVulkan::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, GETextureFormat texFormat, FramebufferNotificationChannel channel) {
|
||||
SamplerCacheKey samplerKey{};
|
||||
SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, samplerKey);
|
||||
SamplerCacheKey samplerKey = GetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight);
|
||||
|
||||
DepalShaderVulkan *depalShader = nullptr;
|
||||
uint32_t clutMode = gstate.clutformat & 0xFFFFFF;
|
||||
|
||||
@@ -100,7 +100,6 @@ public:
|
||||
imageView = imageView_;
|
||||
sampler = curSampler_;
|
||||
}
|
||||
void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key);
|
||||
|
||||
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override;
|
||||
|
||||
|
||||
Reference in new issue
Block a user