PixelShaderGen: For custom textures and scaled EFB copies, use correct texel to pixel mapping when sampling textures

(D3D9 only)

This is basically the same as revision e58692653a, just for scaled textures and with a LOT more work...
This commit is contained in:
NeoBrainX 2012-02-20 17:55:18 +01:00
parent d068686a7f
commit 9adc119e3c
8 changed files with 61 additions and 25 deletions

View file

@ -24,7 +24,7 @@
// Increment this every time you change shader generation code.
enum
{
LINEAR_DISKCACHE_VER = 6970
LINEAR_DISKCACHE_VER = 6971
};
// On disk format:

View file

@ -560,6 +560,7 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
WRITE(p, "uniform float4 "I_KCOLORS"[4] : register(c%d);\n", C_KCOLORS);
WRITE(p, "uniform float4 "I_ALPHA"[1] : register(c%d);\n", C_ALPHA);
WRITE(p, "uniform float4 "I_TEXDIMS"[8] : register(c%d);\n", C_TEXDIMS);
WRITE(p, "uniform float4 "I_VTEXSCALE"[8] : register(c%d);\n", C_VTEXSCALE);
WRITE(p, "uniform float4 "I_ZBIAS"[2] : register(c%d);\n", C_ZBIAS);
WRITE(p, "uniform float4 "I_INDTEXSCALE"[2] : register(c%d);\n", C_INDTEXSCALE);
WRITE(p, "uniform float4 "I_INDTEXMTX"[6] : register(c%d);\n", C_INDTEXMTX);
@ -1102,9 +1103,9 @@ void SampleTexture(char *&p, const char *destination, const char *texcoords, con
WRITE(p, "%s=Tex%d.Sample(samp%d, %s.xy * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap,texmap, texcoords, texmap, texswap);
else if (ApiType & API_D3D9)
{
// D3D9 uses different pixel to texel mapping, so we need to offset our base address by half a pixel.
// D3D9 uses different pixel to texel mapping, so we need to offset our sampling address by half a pixel (assuming native and virtual texture dimensions match each other, otherwise some math is involved).
// Read the MSDN article "Directly Mapping Texels to Pixels (Direct3D 9)" for further info.
WRITE(p, "%s=tex2D(samp%d, (%s.xy + float2(0.5f,0.5f)) * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap);
WRITE(p, "%s=tex2D(samp%d, (%s.xy + 0.5f*"I_VTEXSCALE"[%d].%s) * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap/2, (texmap&1)?"zw":"xy", texmap, texswap);
}
else
WRITE(p, "%s=tex2D(samp%d, %s.xy * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap);

View file

@ -24,26 +24,27 @@
#define I_KCOLORS "k"
#define I_ALPHA "alphaRef"
#define I_TEXDIMS "texdim"
#define I_VTEXSCALE "vtexscale"
#define I_ZBIAS "czbias"
#define I_INDTEXSCALE "cindscale"
#define I_INDTEXMTX "cindmtx"
#define I_FOG "cfog"
#define I_PLIGHTS "cLights"
#define I_PMATERIALS "cmtrl"
#define I_PMATERIALS "cmtrl"
#define C_COLORMATRIX 0 // 0
#define C_COLORS 0 // 0
#define C_KCOLORS (C_COLORS + 4) // 4
#define C_ALPHA (C_KCOLORS + 4) // 8
#define C_TEXDIMS (C_ALPHA + 1) // 9
#define C_ZBIAS (C_TEXDIMS + 8) //17
#define C_INDTEXSCALE (C_ZBIAS + 2) //19
#define C_INDTEXMTX (C_INDTEXSCALE + 2) //21
#define C_FOG (C_INDTEXMTX + 6) //27
#define C_PLIGHTS (C_FOG + 3)
#define C_PMATERIALS (C_PLIGHTS + 40)
#define C_PENVCONST_END (C_PMATERIALS + 4)
#define C_VTEXSCALE (C_TEXDIMS + 8) //17 - virtual texture scaling factor (e.g. custom textures, scaled EFB copies)
#define C_ZBIAS (C_VTEXSCALE + 4) //21
#define C_INDTEXSCALE (C_ZBIAS + 2) //23
#define C_INDTEXMTX (C_INDTEXSCALE + 2) //25
#define C_FOG (C_INDTEXMTX + 6) //31
#define C_PLIGHTS (C_FOG + 3) //34
#define C_PMATERIALS (C_PLIGHTS + 40) //74
#define C_PENVCONST_END (C_PMATERIALS + 4) //78
#define PIXELSHADERUID_MAX_VALUES 70
#define PIXELSHADERUID_MAX_VALUES_SAFE 120

View file

@ -36,9 +36,11 @@ static bool s_bFogRangeAdjustChanged;
static int nLightsChanged[2]; // min,max
static float lastRGBAfull[2][4][4];
static u8 s_nTexDimsChanged;
static u8 s_nVirtualTexScalesChanged;
static u8 s_nIndTexScaleChanged;
static u32 lastAlpha;
static u32 lastTexDims[8]; // width | height << 16 | wrap_s << 28 | wrap_t << 30
static float lastVirtualTexScales[16]; // even fields: width ratio; odd fields: height ratio
static u32 lastZBias;
static int nMaterialsChanged;
@ -61,6 +63,7 @@ void PixelShaderManager::Init()
{
lastAlpha = 0;
memset(lastTexDims, 0, sizeof(lastTexDims));
memset(lastVirtualTexScales, 0, sizeof(lastVirtualTexScales));
lastZBias = 0;
memset(lastRGBAfull, 0, sizeof(lastRGBAfull));
Dirty();
@ -70,6 +73,7 @@ void PixelShaderManager::Dirty()
{
s_nColorsChanged[0] = s_nColorsChanged[1] = 15;
s_nTexDimsChanged = 0xFF;
s_nVirtualTexScalesChanged = 0xFF;
s_nIndTexScaleChanged = 0xFF;
s_nIndTexMtxChanged = 15;
s_bAlphaChanged = s_bZBiasChanged = s_bZTextureTypeChanged = s_bDepthRangeChanged = true;
@ -83,7 +87,7 @@ void PixelShaderManager::Shutdown()
}
void PixelShaderManager::SetConstants()
void PixelShaderManager::SetConstants(API_TYPE api_type)
{
for (int i = 0; i < 2; ++i)
{
@ -109,6 +113,16 @@ void PixelShaderManager::SetConstants()
s_nTexDimsChanged = 0;
}
if ((api_type & API_D3D9) && s_nVirtualTexScalesChanged)
{
for (int i = 0; i < 8; i += 2)
{
if (s_nVirtualTexScalesChanged & (3<<i))
SetPSVirtualTexScalePair(i/2);
}
s_nVirtualTexScalesChanged = 0;
}
if (s_bAlphaChanged)
{
SetPSConstant4f(C_ALPHA, (lastAlpha&0xff)/255.0f, ((lastAlpha>>8)&0xff)/255.0f, 0, ((lastAlpha>>16)&0xff)/255.0f);
@ -338,6 +352,13 @@ void PixelShaderManager::SetPSTextureDims(int texid)
SetPSConstant4fv(C_TEXDIMS + texid, fdims);
}
void PixelShaderManager::SetPSVirtualTexScalePair(int texpairid)
{
PRIM_LOG("vtexscale%d: %f %f %f %f\n", texpairid, lastVirtualTexScales[texpairid*4], lastVirtualTexScales[texpairid*4+1],
lastVirtualTexScales[texpairid*4+2], lastVirtualTexScales[texpairid*4+3]);
SetPSConstant4fv(C_VTEXSCALE + texpairid, &lastVirtualTexScales[texpairid*4]);
}
// This one is high in profiles (0.5%). TODO: Move conversion out, only store the raw color value
// and update it when the shader constant is set, only.
void PixelShaderManager::SetColorChanged(int type, int num, bool high)
@ -376,14 +397,25 @@ void PixelShaderManager::SetDestAlpha(const ConstantAlpha& alpha)
}
}
void PixelShaderManager::SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt)
void PixelShaderManager::SetTexDims(int texmapid, u32 width, u32 height, u32 virtual_width, u32 virtual_height, u32 wraps, u32 wrapt, API_TYPE api_type)
{
u32 wh = width | (height << 16) | (wraps << 28) | (wrapt << 30);
if (lastTexDims[texmapid] != wh)
bool refresh = lastTexDims[texmapid] != wh;
if (api_type & API_D3D9)
{
lastTexDims[texmapid] = wh;
refresh |= (lastVirtualTexScales[texmapid*2] != (float)width / (float)virtual_width);
refresh |= (lastVirtualTexScales[texmapid*2+1] != (float)height / (float)virtual_height);
}
if (refresh)
{
lastTexDims[texmapid] = wh;
lastVirtualTexScales[texmapid*2] = (float)width / (float)virtual_width;
lastVirtualTexScales[texmapid*2+1] = (float)height / (float)virtual_height;
s_nTexDimsChanged |= 1 << texmapid;
}
s_nVirtualTexScalesChanged |= 1 << texmapid;
}
}
void PixelShaderManager::SetZTextureBias(u32 bias)

View file

@ -26,18 +26,20 @@
class PixelShaderManager
{
static void SetPSTextureDims(int texid);
static void SetPSVirtualTexScalePair(int texpairid);
public:
static void Init();
static void Dirty();
static void Shutdown();
static void SetConstants(); // sets pixel shader constants
static void SetConstants(API_TYPE api_type); // sets pixel shader constants
// constant management, should be called after memory is committed
static void SetColorChanged(int type, int index, bool high);
static void SetAlpha(const AlphaFunc& alpha);
static void SetDestAlpha(const ConstantAlpha& alpha);
static void SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt);
static void SetTexDims(int texmapid, u32 width, u32 height, u32 virtual_width, u32 virtual_height, u32 wraps, u32 wrapt, API_TYPE api_type);
static void SetZTextureBias(u32 bias);
static void SetViewportChanged();
static void SetIndMatrixChanged(int matrixidx);

View file

@ -234,7 +234,7 @@ void VertexManager::vFlush()
if (tentry)
{
// 0s are probably for no manual wrapping needed.
PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0);
PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, tentry->virtual_width, tentry->virtual_height, 0, 0, API_D3D11);
}
else
ERROR_LOG(VIDEO, "error loading texture");
@ -243,7 +243,7 @@ void VertexManager::vFlush()
// set global constants
VertexShaderManager::SetConstants();
PixelShaderManager::SetConstants();
PixelShaderManager::SetConstants(API_D3D11);
bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate &&
bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;

View file

@ -143,7 +143,7 @@ void VertexManager::vFlush()
if (tentry)
{
// 0s are probably for no manual wrapping needed.
PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0);
PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, tentry->virtual_width, tentry->virtual_height, 0, 0, API_D3D9);
}
else
ERROR_LOG(VIDEO, "error loading texture");
@ -152,7 +152,7 @@ void VertexManager::vFlush()
// set global constants
VertexShaderManager::SetConstants();
PixelShaderManager::SetConstants();
PixelShaderManager::SetConstants(API_D3D9);
if (!PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components))
{

View file

@ -161,7 +161,7 @@ void VertexManager::vFlush()
if (tentry)
{
// 0s are probably for no manual wrapping needed.
PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0);
PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, tentry->virtual_width, tentry->virtual_height, 0, 0, API_OPENGL);
if (g_ActiveConfig.iLog & CONF_SAVETEXTURES)
{
@ -179,7 +179,7 @@ void VertexManager::vFlush()
// set global constants
VertexShaderManager::SetConstants();
PixelShaderManager::SetConstants();
PixelShaderManager::SetConstants(API_OPENGL);
bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate
&& bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;