1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-04 10:03:36 +00:00

Delay texture coordinate normalization. Adapt texture filter to texture engine.

This commit is contained in:
S2S 2020-04-18 18:20:17 +02:00 committed by Sergey Lipskiy
parent a405ad8659
commit 4834359ec1
8 changed files with 248 additions and 324 deletions

View File

@ -45,6 +45,9 @@ void RDRAMtoColorBuffer::init()
m_pTexture->height = 580; m_pTexture->height = 580;
m_pTexture->textureBytes = m_pTexture->width * m_pTexture->height * fbTexFormats.colorFormatBytes; m_pTexture->textureBytes = m_pTexture->width * m_pTexture->height * fbTexFormats.colorFormatBytes;
m_pTexture->hdRatioS = 1.0f;
m_pTexture->hdRatioT = 1.0f;
Context::InitTextureParams initParams; Context::InitTextureParams initParams;
initParams.handle = m_pTexture->name; initParams.handle = m_pTexture->name;
initParams.width = m_pTexture->width; initParams.width = m_pTexture->width;

View File

@ -106,6 +106,8 @@ void _initFrameBufferTexture(u32 _address, u16 _width, u16 _height, f32 _scale,
_pTexture->mirrorS = 0; _pTexture->mirrorS = 0;
_pTexture->mirrorT = 0; _pTexture->mirrorT = 0;
_pTexture->textureBytes = _pTexture->width * _pTexture->height; _pTexture->textureBytes = _pTexture->width * _pTexture->height;
_pTexture->hdRatioS = _scale;
_pTexture->hdRatioT = _scale;
if (_size > G_IM_SIZ_8b) if (_size > G_IM_SIZ_8b)
_pTexture->textureBytes *= fbTexFormats.colorFormatBytes; _pTexture->textureBytes *= fbTexFormats.colorFormatBytes;
else else
@ -385,6 +387,8 @@ bool FrameBuffer::_initSubTexture(u32 _t)
m_pSubTexture->clampT = pTile->clampt; m_pSubTexture->clampT = pTile->clampt;
m_pSubTexture->offsetS = 0.0f; m_pSubTexture->offsetS = 0.0f;
m_pSubTexture->offsetT = 0.0f; m_pSubTexture->offsetT = 0.0f;
m_pSubTexture->hdRatioS = m_pTexture->hdRatioS;
m_pSubTexture->hdRatioT = m_pTexture->hdRatioT;
_setAndAttachTexture(m_SubFBO, m_pSubTexture, _t, false); _setAndAttachTexture(m_SubFBO, m_pSubTexture, _t, false);

View File

@ -308,9 +308,9 @@ public:
" vec2 texCoordOut = texCoord*uCacheShiftScale[idx]; \n" " vec2 texCoordOut = texCoord*uCacheShiftScale[idx]; \n"
" texCoordOut -= uTexOffset[idx]; \n" " texCoordOut -= uTexOffset[idx]; \n"
" texCoordOut += uCacheOffset[idx]; \n" " texCoordOut += uCacheOffset[idx]; \n"
" if (uTextureFilterMode != 0 && uCacheFrameBuffer[idx] == 0)\n" " if (uTextureFilterMode != 0 && uCacheFrameBuffer[idx] != 0) \n"
" texCoordOut += vec2(0.5); \n" " texCoordOut -= vec2(0.5); \n"
" return texCoordOut* uCacheScale[idx]; \n" " return texCoordOut * uCacheScale[idx]; \n"
"} \n" "} \n"
" \n" " \n"
"void main() \n" "void main() \n"
@ -856,14 +856,16 @@ public:
"uniform lowp int uDepthSource; \n" "uniform lowp int uDepthSource; \n"
"uniform highp float uPrimDepth; \n" "uniform highp float uPrimDepth; \n"
"uniform mediump vec2 uScreenScale; \n" "uniform mediump vec2 uScreenScale; \n"
"uniform highp vec4 uTexClamp0; \n" "uniform highp vec2 uTexClamp0; \n"
"uniform highp vec4 uTexClamp1; \n" "uniform highp vec2 uTexClamp1; \n"
"uniform highp vec2 uTexWrap0; \n" "uniform highp vec2 uTexWrap0; \n"
"uniform highp vec2 uTexWrap1; \n" "uniform highp vec2 uTexWrap1; \n"
"uniform lowp vec2 uTexMirror0; \n" "uniform lowp vec2 uTexWrapEn0; \n"
"uniform lowp vec2 uTexMirror1; \n" "uniform lowp vec2 uTexWrapEn1; \n"
"uniform highp vec2 uTexScale0; \n" "uniform lowp vec2 uTexMirrorEn0; \n"
"uniform highp vec2 uTexScale1; \n" "uniform lowp vec2 uTexMirrorEn1; \n"
"uniform lowp vec2 uTexClampEn0; \n"
"uniform lowp vec2 uTexClampEn1; \n"
"uniform lowp int uScreenSpaceTriangle; \n" "uniform lowp int uScreenSpaceTriangle; \n"
"highp vec2 texCoord0; \n" "highp vec2 texCoord0; \n"
"highp vec2 texCoord1; \n" "highp vec2 texCoord1; \n"
@ -1072,25 +1074,15 @@ public:
} }
}; };
class ShaderFragmentHeaderClampWrapMirror : public ShaderPart
{
public:
ShaderFragmentHeaderClampWrapMirror(const opengl::GLInfo & _glinfo)
{
m_part =
"highp vec2 clampWrapMirror(in highp vec2 vTexCoord, \n"
" in highp vec4 vClamp, in highp vec2 vWrap, \n"
" in lowp vec2 vMirror, in highp vec2 vOffset); \n"
;
}
};
class ShaderFragmentHeaderTextureEngine : public ShaderPart class ShaderFragmentHeaderTextureEngine : public ShaderPart
{ {
public: public:
ShaderFragmentHeaderTextureEngine(const opengl::GLInfo & _glinfo) ShaderFragmentHeaderTextureEngine(const opengl::GLInfo & _glinfo)
{ {
m_part = m_part =
"highp vec2 clampWrapMirror(in highp vec2 vTexCoord, \n"
" in highp vec2 vWrap, in highp vec2 vClamp, \n"
" in lowp vec2 vClampEn, in lowp vec2 vMirrorEn ); \n"
"lowp vec2[5] textureEngine0(in highp vec2 texCoord); \n" "lowp vec2[5] textureEngine0(in highp vec2 texCoord); \n"
"lowp vec2[5] textureEngine1(in highp vec2 texCoord); \n" "lowp vec2[5] textureEngine1(in highp vec2 texCoord); \n"
; ;
@ -1111,7 +1103,7 @@ public:
(g_cycleType == G_CYC_COPY || g_textureConvert.useTextureFiltering())) (g_cycleType == G_CYC_COPY || g_textureConvert.useTextureFiltering()))
{ {
shader << shader <<
"lowp vec4 readTexMS(in lowp sampler2DMS mstex, in highp vec2 texCoord, in lowp int fbMonochrome, in lowp int fbFixedAlpha);\n"; "lowp vec4 readTexMS(in lowp sampler2DMS mstex, in highp vec2[5] tcData, in lowp int fbMonochrome, in lowp int fbFixedAlpha);\n";
} }
} }
@ -1166,50 +1158,45 @@ public:
void write(std::stringstream & shader) const override void write(std::stringstream & shader) const override
{ {
std::string shaderPart; std::string shaderPart;
if (!m_glinfo.isGLES2) { if (!m_glinfo.isGLES2) {
if (g_textureConvert.useTextureFiltering()) { if (g_textureConvert.useTextureFiltering()) {
shaderPart += "uniform lowp int uTextureFilterMode; \n"; shaderPart += "uniform lowp int uTextureFilterMode; \n";
shaderPart += "#define TEX_NEAREST(name, tex, tcData) \\\n"
"{ \\\n"
" name = texelFetch(tex, ivec2(tcData[0]), 0); \\\n"
"} \n"
;
switch (config.texture.bilinearMode + config.texture.enableHalosRemoval * 2) { switch (config.texture.bilinearMode + config.texture.enableHalosRemoval * 2) {
case BILINEAR_3POINT: case BILINEAR_3POINT:
// 3 point texture filtering. // 3 point texture filtering.
// Original author: ArthurCarvalho // Original author: ArthurCarvalho
// GLSL implementation: twinaphex, mupen64plus-libretro project. // GLSL implementation: twinaphex, mupen64plus-libretro project.
shaderPart += shaderPart +=
"#define TEX_OFFSET(off, tex, texCoord) texture(tex, texCoord - (off)/texSize) \n" "#define TEX_FILTER(name, tex, tcData) \\\n"
"#define TEX_FILTER(name, tex, texCoord) \\\n"
" { \\\n" " { \\\n"
" mediump vec2 texSize = vec2(textureSize(tex,0)); \\\n" " lowp float bottomRightTri = step(1.0, tcData[4].s + tcData[4].t); \\\n"
" mediump vec2 offset = fract(texCoord*texSize - vec2(0.5)); \\\n" " lowp vec4 c00 = texelFetch(tex, ivec2(tcData[0]), 0); \\\n"
" offset -= step(1.0, offset.x + offset.y); \\\n" " lowp vec4 c01 = texelFetch(tex, ivec2(tcData[1]), 0); \\\n"
" lowp vec4 c0 = TEX_OFFSET(offset, tex, texCoord); \\\n" " lowp vec4 c10 = texelFetch(tex, ivec2(tcData[2]), 0); \\\n"
" lowp vec4 c1 = TEX_OFFSET(vec2(offset.x - sign(offset.x), offset.y), tex, texCoord); \\\n" " lowp vec4 c11 = texelFetch(tex, ivec2(tcData[3]), 0); \\\n"
" lowp vec4 c2 = TEX_OFFSET(vec2(offset.x, offset.y - sign(offset.y)), tex, texCoord); \\\n" " lowp vec4 c0 = c00 + tcData[4].s*(c10-c00) + tcData[4].t*(c01-c00); \\\n"
" name = c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0); \\\n" " lowp vec4 c1 = c11 + (1.0-tcData[4].s)*(c01-c11) + (1.0-tcData[4].t)*(c10-c11); \\\n"
" name = c0 + bottomRightTri * (c1-c0); \\\n"
" } \n" " } \n"
; ;
break; break;
case BILINEAR_STANDARD: case BILINEAR_STANDARD:
shaderPart += shaderPart +=
"#define TEX_OFFSET(off, tex, texCoord) texture(tex, texCoord - (off)/texSize) \n" "#define TEX_FILTER(name, tex, tcData) \\\n"
"#define TEX_FILTER(name, tex, texCoord) \\\n"
"{ \\\n" "{ \\\n"
" mediump vec2 texSize = vec2(textureSize(tex,0)); \\\n" " lowp vec4 c00 = texelFetch(tex, ivec2(tcData[0]), 0); \\\n"
" mediump vec2 offset = fract(texCoord*texSize - vec2(0.5)); \\\n" " lowp vec4 c01 = texelFetch(tex, ivec2(tcData[1]), 0); \\\n"
" offset -= step(1.0, offset.x + offset.y); \\\n" " lowp vec4 c10 = texelFetch(tex, ivec2(tcData[2]), 0); \\\n"
" lowp vec4 zero = vec4(0.0); \\\n" " lowp vec4 c11 = texelFetch(tex, ivec2(tcData[3]), 0); \\\n"
" \\\n" " lowp vec4 c0 = c00 + tcData[4].s * (c10-c00); \\\n"
" lowp vec4 p0q0 = TEX_OFFSET(offset, tex, texCoord); \\\n" " lowp vec4 c1 = c01 + tcData[4].s * (c11-c01); \\\n"
" lowp vec4 p1q0 = TEX_OFFSET(vec2(offset.x - sign(offset.x), offset.y), tex, texCoord); \\\n" " name = c0 + tcData[4].t * (c1-c0); \\\n"
" \\\n"
" lowp vec4 p0q1 = TEX_OFFSET(vec2(offset.x, offset.y - sign(offset.y)), tex, texCoord); \\\n"
" lowp vec4 p1q1 = TEX_OFFSET(vec2(offset.x - sign(offset.x), offset.y - sign(offset.y)), tex, texCoord); \\\n"
" \\\n"
" mediump vec2 interpolationFactor = abs(offset); \\\n"
" lowp vec4 pInterp_q0 = mix( p0q0, p1q0, interpolationFactor.x ); \\\n" // Interpolates top row in X direction.
" lowp vec4 pInterp_q1 = mix( p0q1, p1q1, interpolationFactor.x ); \\\n" // Interpolates bottom row in X direction.
" name = mix( pInterp_q0, pInterp_q1, interpolationFactor.y ); \\\n" // Interpolate in Y direction.
"} \n" "} \n"
; ;
break; break;
@ -1218,89 +1205,60 @@ public:
// Original author: ArthurCarvalho // Original author: ArthurCarvalho
// GLSL implementation: twinaphex, mupen64plus-libretro project. // GLSL implementation: twinaphex, mupen64plus-libretro project.
shaderPart += shaderPart +=
"#define TEX_OFFSET(off, tex, texCoord) texture(tex, texCoord - (off)/texSize) \n" "#define TEX_FILTER(name, tex, tcData) \\\n"
"#define TEX_FILTER(name, tex, texCoord) \\\n"
"{ \\\n" "{ \\\n"
" mediump vec2 texSize = vec2(textureSize(tex,0)); \\\n" " lowp float bottomRightTri = step(1.0, tcData[4].s + tcData[4].t); \\\n"
" mediump vec2 offset = fract(texCoord*texSize - vec2(0.5)); \\\n" " lowp vec4 c00 = texelFetch(tex, ivec2(tcData[0]), 0); \\\n"
" offset -= step(1.0, offset.x + offset.y); \\\n" " lowp vec4 c01 = texelFetch(tex, ivec2(tcData[1]), 0); \\\n"
" lowp vec4 c0 = TEX_OFFSET(offset, tex, texCoord); \\\n" " lowp vec4 c10 = texelFetch(tex, ivec2(tcData[2]), 0); \\\n"
" lowp vec4 c1 = TEX_OFFSET(vec2(offset.x - sign(offset.x), offset.y), tex, texCoord); \\\n" " lowp vec4 c11 = texelFetch(tex, ivec2(tcData[3]), 0); \\\n"
" lowp vec4 c2 = TEX_OFFSET(vec2(offset.x, offset.y - sign(offset.y)), tex, texCoord); \\\n"
" \\\n"
" if(uEnableAlphaTest == 1 ){ \\\n" // Calculate premultiplied color values " if(uEnableAlphaTest == 1 ){ \\\n" // Calculate premultiplied color values
" c0.rgb *= c0.a; \\\n" " c00.rgb *= c00.a; \\\n"
" c1.rgb *= c1.a; \\\n" " c01.rgb *= c01.a; \\\n"
" c2.rgb *= c2.a; \\\n" " c10.rgb *= c10.a; \\\n"
" name = c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0); \\\n" " c11.rgb *= c11.a; \\\n"
" name.rgb /= name.a; \\\n" // Divide alpha to get actual color value
" } \\\n" " } \\\n"
" else name = c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0); \\\n" " lowp vec4 c0 = c00 + tcData[4].s*(c10-c00) + tcData[4].t*(c01-c00); \\\n"
" lowp vec4 c1 = c11 + (1.0-tcData[4].s)*(c01-c11) + (1.0-tcData[4].t)*(c10-c11); \\\n"
" name = c0 + bottomRightTri * (c1-c0); \\\n"
" if(uEnableAlphaTest == 1 ) name.rgb /= name.a; \\\n" // Divide alpha to get actual color value
"} \n" "} \n"
; ;
break; break;
case BILINEAR_STANDARD_WITH_COLOR_BLEEDING_AND_PREMULTIPLIED_ALPHA: case BILINEAR_STANDARD_WITH_COLOR_BLEEDING_AND_PREMULTIPLIED_ALPHA:
shaderPart += shaderPart +=
"#define TEX_OFFSET(off, tex, texCoord) texture(tex, texCoord - (off)/texSize) \n" "#define TEX_FILTER(name, tex, tcData) \\\n"
"#define TEX_FILTER(name, tex, texCoord) \\\n" "{ \\\n"
"{ \\\n" " lowp vec4 c00 = texelFetch(tex, ivec2(tcData[0]), 0); \\\n"
" mediump vec2 texSize = vec2(textureSize(tex,0)); \\\n" " lowp vec4 c01 = texelFetch(tex, ivec2(tcData[1]), 0); \\\n"
" mediump vec2 offset = fract(texCoord*texSize - vec2(0.5)); \\\n" " lowp vec4 c10 = texelFetch(tex, ivec2(tcData[2]), 0); \\\n"
" offset -= step(1.0, offset.x + offset.y); \\\n" " lowp vec4 c11 = texelFetch(tex, ivec2(tcData[3]), 0); \\\n"
" lowp vec4 zero = vec4(0.0); \\\n" " if(uEnableAlphaTest == 1){ \\\n" // Calculate premultiplied color values
" \\\n" " c00.rgb *= c00.a; \\\n"
" lowp vec4 p0q0 = TEX_OFFSET(offset, tex, texCoord); \\\n" " c01.rgb *= c01.a; \\\n"
" lowp vec4 p1q0 = TEX_OFFSET(vec2(offset.x - sign(offset.x), offset.y), tex, texCoord); \\\n" " c10.rgb *= c10.a; \\\n"
" \\\n" " c11.rgb *= c11.a; \\\n"
" lowp vec4 p0q1 = TEX_OFFSET(vec2(offset.x, offset.y - sign(offset.y)), tex, texCoord); \\\n" " } \\\n"
" lowp vec4 p1q1 = TEX_OFFSET(vec2(offset.x - sign(offset.x), offset.y - sign(offset.y)), tex, texCoord); \\\n" " lowp vec4 c0 = c00 + tcData[4].s * (c10-c00); \\\n"
" \\\n" " lowp vec4 c1 = c01 + tcData[4].s * (c11-c01); \\\n"
" if(uEnableAlphaTest == 1){ \\\n" // Calculate premultiplied color values " name = c0 + tcData[4].t * (c1-c0); \\\n"
" p0q0.rgb *= p0q0.a; \\\n" " if(uEnableAlphaTest == 1) name.rgb /= name.a; \\\n"
" p1q0.rgb *= p1q0.a; \\\n" "} \n"
" p0q1.rgb *= p0q1.a; \\\n"
" p1q1.rgb *= p1q1.a; \\\n"
" \\\n"
" mediump vec2 interpolationFactor = abs(offset); \\\n"
" lowp vec4 pInterp_q0 = mix( p0q0, p1q0, interpolationFactor.x ); \\\n" // Interpolates top row in X direction.
" lowp vec4 pInterp_q1 = mix( p0q1, p1q1, interpolationFactor.x ); \\\n" // Interpolates bottom row in X direction.
" name = mix( pInterp_q0, pInterp_q1, interpolationFactor.y ); \\\n" // Interpolate in Y direction.
" name.rgb /= name.a; \\\n" // Divide alpha to get actual color value
" } \\\n"
" else if(uCvgXAlpha == 1){ \\\n" // Use texture bleeding for mk64
" if(p0q0.a > p1q0.a) p1q0.rgb = p0q0.rgb; \\\n"
" if(p1q0.a > p0q0.a) p0q0.rgb = p1q0.rgb; \\\n"
" if(p0q1.a > p1q1.a) p1q1.rgb = p0q1.rgb; \\\n"
" if(p1q1.a > p0q1.a) p0q1.rgb = p1q1.rgb; \\\n"
" if(p0q0.a > p0q1.a) p0q1.rgb = p0q0.rgb; \\\n"
" if(p0q1.a > p0q0.a) p0q0.rgb = p0q1.rgb; \\\n"
" if(p1q0.a > p1q1.a) p1q1.rgb = p1q0.rgb; \\\n"
" if(p1q1.a > p1q0.a) p1q0.rgb = p1q1.rgb; \\\n"
" \\\n"
" mediump vec2 interpolationFactor = abs(offset); \\\n"
" lowp vec4 pInterp_q0 = mix( p0q0, p1q0, interpolationFactor.x ); \\\n" // Interpolates top row in X direction.
" lowp vec4 pInterp_q1 = mix( p0q1, p1q1, interpolationFactor.x ); \\\n" // Interpolates bottom row in X direction.
" name = mix( pInterp_q0, pInterp_q1, interpolationFactor.y ); \\\n"
" } \\\n"
" else{ \\\n"
" mediump vec2 interpolationFactor = abs(offset); \\\n"
" lowp vec4 pInterp_q0 = mix( p0q0, p1q0, interpolationFactor.x ); \\\n" // Interpolates top row in X direction.
" lowp vec4 pInterp_q1 = mix( p0q1, p1q1, interpolationFactor.x ); \\\n" // Interpolates bottom row in X direction.
" name = mix( pInterp_q0, pInterp_q1, interpolationFactor.y ); \\\n" // Interpolate in Y direction.
" } \\\n"
"} \n"
; ;
break; break;
} }
shaderPart += shaderPart +=
"#define READ_TEX(name, tex, texCoord, fbMonochrome, fbFixedAlpha) \\\n" "#define READ_TEX(name, tex, tcData, fbMonochrome, fbFixedAlpha) \\\n"
" { \\\n" " { \\\n"
" if (fbMonochrome == 3) { \\\n" " if (fbMonochrome == 3) { \\\n"
" mediump ivec2 coord = ivec2(gl_FragCoord.xy); \\\n" " mediump ivec2 coord = ivec2(gl_FragCoord.xy); \\\n"
" name = texelFetch(tex, coord, 0); \\\n" " name = texelFetch(tex, coord, 0); \\\n"
" } else { \\\n" " } else { \\\n"
" if (uTextureFilterMode == 0) name = texture(tex, texCoord); \\\n" " if (uTextureFilterMode == 0) \\\n"
" else TEX_FILTER(name, tex, texCoord); \\\n" " { \\\n"
" TEX_NEAREST(name, tex, tcData); \\\n"
" } \\\n"
" else TEX_FILTER(name, tex, tcData); \\\n"
" } \\\n" " } \\\n"
" if (fbMonochrome == 1) name = vec4(name.r); \\\n" " if (fbMonochrome == 1) name = vec4(name.r); \\\n"
" else if (fbMonochrome == 2) \\\n" " else if (fbMonochrome == 2) \\\n"
@ -1329,15 +1287,15 @@ public:
" iconvert.b = icolor.b + (uConvertParams[3]*icolor.r + 128)/256; \\\n" " iconvert.b = icolor.b + (uConvertParams[3]*icolor.r + 128)/256; \\\n"
" iconvert.a = icolor.b; \\\n" " iconvert.a = icolor.b; \\\n"
" name = vec4(iconvert)/255.0; \n" " name = vec4(iconvert)/255.0; \n"
"#define YUVCONVERT_TEX0(name, tex, texCoord, format) \\\n" "#define YUVCONVERT_TEX0(name, tex, tcData, format) \\\n"
" { \\\n" " { \\\n"
" name = texture(tex, texCoord); \\\n" " name = texelFetch(tex, ivec2(tcData[0]), 0); \\\n"
" YUVCONVERT(name, format) \\\n" " YUVCONVERT(name, format) \\\n"
" } \n" " } \n"
"#define YUVCONVERT_TEX1(name, tex, texCoord, format, prev) \\\n" "#define YUVCONVERT_TEX1(name, tex, tcData, format, prev) \\\n"
" { \\\n" " { \\\n"
" if (uTextureConvert != 0) name = prev; \\\n" " if (uTextureConvert != 0) name = prev; \\\n"
" else name = texture(tex, texCoord); \\\n" " else name = texelFetch(tex, ivec2(tcData[0]), 0); \\\n"
" YUVCONVERT(name, format) \\\n" " YUVCONVERT(name, format) \\\n"
" } \n" " } \n"
; ;
@ -1374,13 +1332,13 @@ public:
{ {
if (!_glinfo.isGLES2) { if (!_glinfo.isGLES2) {
m_part = m_part =
"#define READ_TEX(name, tex, texCoord, fbMonochrome, fbFixedAlpha) \\\n" "#define READ_TEX(name, tex, tcData, fbMonochrome, fbFixedAlpha) \\\n"
" { \\\n" " { \\\n"
" if (fbMonochrome == 3) { \\\n" " if (fbMonochrome == 3) { \\\n"
" mediump ivec2 coord = ivec2(gl_FragCoord.xy); \\\n" " mediump ivec2 coord = ivec2(gl_FragCoord.xy); \\\n"
" name = texelFetch(tex, coord, 0); \\\n" " name = texelFetch(tex, coord, 0); \\\n"
" } else { \\\n" " } else { \\\n"
" name = texture(tex, texCoord); \\\n" " name = texelFetch(tex, ivec2(tcData[0]),0); \\\n"
" } \\\n" " } \\\n"
" if (fbMonochrome == 1) name = vec4(name.r); \\\n" " if (fbMonochrome == 1) name = vec4(name.r); \\\n"
" else if (fbMonochrome == 2) \\\n" " else if (fbMonochrome == 2) \\\n"
@ -1468,28 +1426,6 @@ public:
} }
}; };
class ShaderFragmentClampWrapMirrorTex0 : public ShaderPart
{
public:
ShaderFragmentClampWrapMirrorTex0(const opengl::GLInfo & _glinfo)
{
m_part =
" texCoord0 = clampWrapMirror(vTexCoord0, uTexClamp0, uTexWrap0, uTexMirror0, uTexScale0); \n"
;
}
};
class ShaderFragmentClampWrapMirrorTex1 : public ShaderPart
{
public:
ShaderFragmentClampWrapMirrorTex1(const opengl::GLInfo & _glinfo)
{
m_part =
" texCoord1 = clampWrapMirror(vTexCoord1, uTexClamp1, uTexWrap1, uTexMirror1, uTexScale1); \n"
;
}
};
class ShaderFragmentReadTexMipmap : public ShaderPart class ShaderFragmentReadTexMipmap : public ShaderPart
{ {
public: public:
@ -1517,13 +1453,13 @@ public:
m_part = m_part =
" lowp vec4 readtex0; \n" " lowp vec4 readtex0; \n"
" if (uMSTexEnabled[0] == 0) { \n" " if (uMSTexEnabled[0] == 0) { \n"
" READ_TEX(readtex0, uTex0, texCoord0, uFbMonochrome[0], uFbFixedAlpha[0]) \n" " READ_TEX(readtex0, uTex0, tcData0, uFbMonochrome[0], uFbFixedAlpha[0]) \n"
" } else readtex0 = readTexMS(uMSTex0, texCoord0, uFbMonochrome[0], uFbFixedAlpha[0]);\n" " } else readtex0 = readTexMS(uMSTex0, tcData0, uFbMonochrome[0], uFbFixedAlpha[0]);\n"
; ;
} else { } else {
m_part = m_part =
" lowp vec4 readtex0; \n" " lowp vec4 readtex0; \n"
" READ_TEX(readtex0, uTex0, texCoord0, uFbMonochrome[0], uFbFixedAlpha[0]) \n" " READ_TEX(readtex0, uTex0, tcData0, uFbMonochrome[0], uFbFixedAlpha[0]) \n"
; ;
} }
} }
@ -1555,17 +1491,17 @@ public:
if (!g_textureConvert.getBilerp0()) { if (!g_textureConvert.getBilerp0()) {
shaderPart = " lowp vec4 readtex0; \n" shaderPart = " lowp vec4 readtex0; \n"
" YUVCONVERT_TEX0(readtex0, uTex0, texCoord0, uTextureFormat[0]) \n"; " YUVCONVERT_TEX0(readtex0, uTex0, tcData0, uTextureFormat[0]) \n";
} else { } else {
if (config.video.multisampling > 0) { if (config.video.multisampling > 0) {
shaderPart = shaderPart =
" lowp vec4 readtex0; \n" " lowp vec4 readtex0; \n"
" if (uMSTexEnabled[0] == 0) { \n" " if (uMSTexEnabled[0] == 0) { \n"
" READ_TEX(readtex0, uTex0, texCoord0, uFbMonochrome[0], uFbFixedAlpha[0]) \n" " READ_TEX(readtex0, uTex0, tcData0, uFbMonochrome[0], uFbFixedAlpha[0]) \n"
" } else readtex0 = readTexMS(uMSTex0, texCoord0, uFbMonochrome[0], uFbFixedAlpha[0]); \n"; " } else readtex0 = readTexMS(uMSTex0, tcData0, uFbMonochrome[0], uFbFixedAlpha[0]); \n";
} else { } else {
shaderPart = " lowp vec4 readtex0; \n" shaderPart = " lowp vec4 readtex0; \n"
" READ_TEX(readtex0, uTex0, texCoord0, uFbMonochrome[0], uFbFixedAlpha[0]) \n"; " READ_TEX(readtex0, uTex0, tcData0, uFbMonochrome[0], uFbFixedAlpha[0]) \n";
} }
} }
@ -1604,17 +1540,18 @@ public:
if (!g_textureConvert.getBilerp1()) { if (!g_textureConvert.getBilerp1()) {
shaderPart = shaderPart =
" lowp vec4 readtex1; \n" " lowp vec4 readtex1; \n"
" YUVCONVERT_TEX1(readtex1, uTex1, texCoord1, uTextureFormat[1], readtex0) \n"; " YUVCONVERT_TEX1(readtex1, uTex1, tcData1, uTextureFormat[1], readtex0) \n";
} else { } else {
if (config.video.multisampling > 0) { if (config.video.multisampling > 0) {
shaderPart = shaderPart =
" lowp vec4 readtex1; \n" " lowp vec4 readtex1; \n"
" if (uMSTexEnabled[1] == 0) { \n" " if (uMSTexEnabled[1] == 0) { \n"
" READ_TEX(readtex1, uTex1, texCoord1, uFbMonochrome[1], uFbFixedAlpha[1]) \n" " READ_TEX(readtex1, uTex1, tcData1, uFbMonochrome[1], uFbFixedAlpha[1]) \n"
" } else readtex1 = readTexMS(uMSTex1, texCoord1, uFbMonochrome[1], uFbFixedAlpha[1]); \n"; " } else readtex1 = readTexMS(uMSTex1, tcData1, uFbMonochrome[1], uFbFixedAlpha[1]); \n";
} else { } else {
shaderPart = " lowp vec4 readtex1; \n" shaderPart = " lowp vec4 readtex1; \n"
" READ_TEX(readtex1, uTex1, texCoord1, uFbMonochrome[1], uFbFixedAlpha[1]) \n"; " READ_TEX(readtex1, uTex1, tcData1, uFbMonochrome[1], uFbFixedAlpha[1]) \n";
} }
} }
@ -1964,52 +1901,49 @@ public:
} }
} }
else { else {
if (config.texture.bilinearMode == BILINEAR_3POINT)
m_part =
"#define READ_TEX_MIPMAP(name, tex, tcData, lod) \\\n"
"{ \\\n"
" lowp float bottomRightTri = step(1.0, tcData[4].s + tcData[4].t); \\\n"
" lowp vec2 lod_scale = vec2(textureSize(tex,int(lod))) / vec2(textureSize(tex,0)); \\\n"
" lowp vec4 c00 = texelFetch(tex, ivec2(tcData[0]*lod_scale), int(lod)); \\\n"
" lowp vec4 c01 = texelFetch(tex, ivec2(tcData[1]*lod_scale), int(lod)); \\\n"
" lowp vec4 c10 = texelFetch(tex, ivec2(tcData[2]*lod_scale), int(lod)); \\\n"
" lowp vec4 c11 = texelFetch(tex, ivec2(tcData[3]*lod_scale), int(lod)); \\\n"
" lowp vec4 c0 = c00 + tcData[4].s*(c10-c00) + tcData[4].t*(c01-c00); \\\n"
" lowp vec4 c1 = c11 + (1.0-tcData[4].s)*(c01-c11) + (1.0-tcData[4].t)*(c10-c11); \\\n"
" name = c0 + bottomRightTri * (c1-c0); \\\n"
"} \n"
;
else
m_part =
"#define READ_TEX_MIPMAP(name, tex, tcData, lod) \\\n"
"{ \\\n"
" lowp vec2 lod_scale = vec2(textureSize(tex,int(lod))) / vec2(textureSize(tex,0)); \\\n"
" lowp vec4 c00 = texelFetch(tex, ivec2(tcData[0]*lod_scale), int(lod)); \\\n"
" lowp vec4 c01 = texelFetch(tex, ivec2(tcData[1]*lod_scale), int(lod)); \\\n"
" lowp vec4 c10 = texelFetch(tex, ivec2(tcData[2]*lod_scale), int(lod)); \\\n"
" lowp vec4 c11 = texelFetch(tex, ivec2(tcData[3]*lod_scale), int(lod)); \\\n"
" lowp vec4 c0 = c00 + tcData[4].s * (c10-c00); \\\n"
" lowp vec4 c1 = c01 + tcData[4].s * (c11-c01); \\\n"
" name = c0 + tcData[4].t * (c1-c0); \\\n"
"} \n"
;
if (config.generalEmulation.enableLOD == 0) { if (config.generalEmulation.enableLOD == 0) {
// Fake mipmap // Fake mipmap
m_part = m_part +=
"uniform lowp int uMaxTile; \n" "uniform lowp int uMaxTile; \n"
"uniform mediump float uMinLod; \n" "uniform mediump float uMinLod; \n"
" \n" " \n"
"mediump float mipmap(out lowp vec4 readtex0, out lowp vec4 readtex1) { \n" "mediump float mipmap(out lowp vec4 readtex0, out lowp vec4 readtex1) { \n"
" readtex0 = texture(uTex0, texCoord0); \n" " READ_TEX_MIPMAP(readtex0, uTex0, tcData0, 0); \n"
" readtex1 = texture(uTex1, texCoord1); \n" " READ_TEX_MIPMAP(readtex1, uTex1, tcData1, 0); \n"
" if (uMaxTile == 0) return 1.0; \n" " if (uMaxTile == 0) return 1.0; \n"
" return uMinLod; \n" " return uMinLod; \n"
"} \n" "} \n"
; ;
} else { } else {
if (config.texture.bilinearMode == BILINEAR_3POINT)
m_part =
"#define TEX_OFFSET_NORMAL(off, tex, texCoord, lod) texture(tex, texCoord - (off)/texSize) \n"
"#define TEX_OFFSET_MIPMAP(off, tex, texCoord, lod) textureLod(tex, texCoord - (off)/texSize, lod) \n"
"#define READ_TEX_NORMAL(name, tex, texCoord, lod) \\\n"
" { \\\n"
" mediump vec2 texSize = vec2(textureSize(tex, int(lod))); \\\n"
" mediump vec2 offset = fract(texCoord*texSize - vec2(0.5)); \\\n"
" offset -= step(1.0, offset.x + offset.y); \\\n"
" lowp vec4 c0 = TEX_OFFSET_NORMAL(offset, tex, texCoord, lod); \\\n"
" lowp vec4 c1 = TEX_OFFSET_NORMAL(vec2(offset.x - sign(offset.x), offset.y), tex, texCoord, lod); \\\n"
" lowp vec4 c2 = TEX_OFFSET_NORMAL(vec2(offset.x, offset.y - sign(offset.y)), tex, texCoord, lod); \\\n"
" name = c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0); \\\n"
" } \n"
"#define READ_TEX_MIPMAP(name, tex, texCoord, lod) \\\n"
" { \\\n"
" mediump vec2 texSize = vec2(textureSize(tex, int(lod))); \\\n"
" mediump vec2 offset = fract(texCoord*texSize - vec2(0.5)); \\\n"
" offset -= step(1.0, offset.x + offset.y); \\\n"
" lowp vec4 c0 = TEX_OFFSET_MIPMAP(offset, tex, texCoord, lod); \\\n"
" lowp vec4 c1 = TEX_OFFSET_MIPMAP(vec2(offset.x - sign(offset.x), offset.y), tex, texCoord, lod); \\\n"
" lowp vec4 c2 = TEX_OFFSET_MIPMAP(vec2(offset.x, offset.y - sign(offset.y)), tex, texCoord, lod); \\\n"
" name = c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0); \\\n"
" } \n"
;
else
m_part =
"#define TEX_FETCH_NORMAL(tex, texCoord, lod) texture(tex, texCoord) \n"
"#define TEX_FETCH_MIPMAP(tex, texCoord, lod) textureLod(tex, texCoord, lod) \n"
"#define READ_TEX_NORMAL(name, tex, texCoord, lod) name = TEX_FETCH_NORMAL(tex, texCoord, lod) \n"
"#define READ_TEX_MIPMAP(name, tex, texCoord, lod) name = TEX_FETCH_MIPMAP(tex, texCoord, lod) \n"
;
m_part += m_part +=
"uniform lowp int uEnableLod; \n" "uniform lowp int uEnableLod; \n"
"uniform mediump float uMinLod; \n" "uniform mediump float uMinLod; \n"
@ -2017,8 +1951,8 @@ public:
"uniform lowp int uTextureDetail; \n" "uniform lowp int uTextureDetail; \n"
" \n" " \n"
"mediump float mipmap(out lowp vec4 readtex0, out lowp vec4 readtex1) { \n" "mediump float mipmap(out lowp vec4 readtex0, out lowp vec4 readtex1) { \n"
" READ_TEX_NORMAL(readtex0, uTex0, texCoord0, 0.0); \n" " READ_TEX_MIPMAP(readtex0, uTex0, tcData0, 0); \n"
" READ_TEX_MIPMAP(readtex1, uTex1, texCoord1, 0.0); \n" " READ_TEX_MIPMAP(readtex1, uTex1, tcData1, 0); \n"
" \n" " \n"
" mediump float fMaxTile = float(uMaxTile); \n" " mediump float fMaxTile = float(uMaxTile); \n"
" mediump vec2 dx = abs(dFdx(vLodTexCoord)); \n" " mediump vec2 dx = abs(dFdx(vLodTexCoord)); \n"
@ -2048,9 +1982,9 @@ public:
" lowp float lod_tile_m1 = max(0.0, lod_tile - 1.0); \n" " lowp float lod_tile_m1 = max(0.0, lod_tile - 1.0); \n"
" lowp float lod_tile_p1 = min(fMaxTile - 1.0, lod_tile + 1.0); \n" " lowp float lod_tile_p1 = min(fMaxTile - 1.0, lod_tile + 1.0); \n"
" lowp vec4 lodT, lodT_m1, lodT_p1; \n" " lowp vec4 lodT, lodT_m1, lodT_p1; \n"
" READ_TEX_MIPMAP(lodT, uTex1, texCoord1, lod_tile); \n" " READ_TEX_MIPMAP(lodT, uTex1, tcData1, lod_tile); \n"
" READ_TEX_MIPMAP(lodT_m1, uTex1, texCoord1, lod_tile_m1); \n" " READ_TEX_MIPMAP(lodT_m1, uTex1, tcData1, lod_tile_m1); \n"
" READ_TEX_MIPMAP(lodT_p1, uTex1, texCoord1, lod_tile_p1); \n" " READ_TEX_MIPMAP(lodT_p1, uTex1, tcData1, lod_tile_p1); \n"
" if (lod_tile < 1.0) { \n" " if (lod_tile < 1.0) { \n"
" if (magnify) { \n" " if (magnify) { \n"
// !sharpen && !detail // !sharpen && !detail
@ -2212,14 +2146,13 @@ public:
" return texel / float(uMSAASamples); \n" " return texel / float(uMSAASamples); \n"
"} \n" "} \n"
" \n" " \n"
"lowp vec4 readTexMS(in lowp sampler2DMS mstex, in highp vec2 texCoord, in lowp int fbMonochrome, in lowp int fbFixedAlpha) \n" "lowp vec4 readTexMS(in lowp sampler2DMS mstex, in highp vec2[5] tcData, in lowp int fbMonochrome, in lowp int fbFixedAlpha) \n"
"{ \n" "{ \n"
" mediump ivec2 itexCoord; \n" " mediump ivec2 itexCoord; \n"
" if (fbMonochrome == 3) { \n" " if (fbMonochrome == 3) { \n"
" itexCoord = ivec2(gl_FragCoord.xy); \n" " itexCoord = ivec2(gl_FragCoord.xy); \n"
" } else { \n" " } else { \n"
" mediump vec2 msTexSize = vec2(textureSize(mstex)); \n" " itexCoord = ivec2(tcData[0]); \n"
" itexCoord = ivec2(msTexSize * texCoord); \n"
" } \n" " } \n"
" lowp vec4 texColor = sampleMS(mstex, itexCoord); \n" " lowp vec4 texColor = sampleMS(mstex, itexCoord); \n"
" if (fbMonochrome == 1) texColor = vec4(texColor.r); \n" " if (fbMonochrome == 1) texColor = vec4(texColor.r); \n"
@ -2272,14 +2205,13 @@ public:
" return texel / float(uMSAASamples); \n" " return texel / float(uMSAASamples); \n"
"} \n" "} \n"
" \n" " \n"
"lowp vec4 readTexMS(in lowp sampler2DMS mstex, in highp vec2 texCoord, in lowp int fbMonochrome, in lowp int fbFixedAlpha) \n" "lowp vec4 readTexMS(in lowp sampler2DMS mstex, in highp vec2[5] tcData, in lowp int fbMonochrome, in lowp int fbFixedAlpha) \n"
"{ \n" "{ \n"
" mediump ivec2 itexCoord; \n" " mediump ivec2 itexCoord; \n"
" if (fbMonochrome == 3) { \n" " if (fbMonochrome == 3) { \n"
" itexCoord = ivec2(gl_FragCoord.xy); \n" " itexCoord = ivec2(gl_FragCoord.xy); \n"
" } else { \n" " } else { \n"
" mediump vec2 msTexSize = vec2(textureSize(mstex)); \n" " itexCoord = ivec2(tcData[0]); \n"
" itexCoord = ivec2(msTexSize * texCoord); \n"
" } \n" " } \n"
" lowp vec4 texColor = sampleMS(mstex, itexCoord); \n" " lowp vec4 texColor = sampleMS(mstex, itexCoord); \n"
" if (fbMonochrome == 1) texColor = vec4(texColor.r); \n" " if (fbMonochrome == 1) texColor = vec4(texColor.r); \n"
@ -2414,58 +2346,44 @@ public:
} }
}; };
class ShaderClampWrapMirror : public ShaderPart
{
public:
ShaderClampWrapMirror(const opengl::GLInfo & _glinfo)
{
m_part =
"highp vec2 clampWrapMirror(in highp vec2 vTexCoord, in highp vec4 vClamp, \n"
" in highp vec2 vWrap, in lowp vec2 vMirror, in highp vec2 vScale) \n"
"{ \n"
" highp vec2 texCoord = clamp(vTexCoord, vClamp.xy, vClamp.zw); \n"
" lowp vec2 one = vec2(1.0); \n"
" lowp vec2 clamped = step(vClamp.zw, texCoord); \n"
" lowp vec2 notClamped = one - clamped; \n"
" lowp vec2 wrapped = step(vWrap , texCoord); \n"
" lowp vec2 notWrapped = one - wrapped; \n"
" texCoord = clamped * texCoord + notClamped * (wrapped*mod(texCoord, vWrap) + notWrapped*texCoord); \n"
" highp vec2 intPart = floor(texCoord); \n"
" highp vec2 fractPart = fract(texCoord); \n"
" lowp vec2 needMirror = step(vec2(0.5), mod(intPart, vWrap)) * vMirror; \n"
" texCoord = clamped * texCoord + notClamped * fractPart; \n"
" texCoord = (one - vMirror) * texCoord + vMirror * fractPart; \n"
" texCoord = (one - texCoord) * needMirror + texCoord * (one - needMirror); \n"
" texCoord *= vScale; \n"
" return texCoord; \n"
"} \n"
;
}
};
class ShaderTextureEngine : public ShaderPart class ShaderTextureEngine : public ShaderPart
{ {
public: public:
ShaderTextureEngine(const opengl::GLInfo _glinfo) { ShaderTextureEngine(const opengl::GLInfo _glinfo) {
m_part = m_part =
"highp vec2 clampWrapMirror(in highp vec2 vTexCoord, in highp vec2 vWrap, \n"
" in highp vec2 vClamp, in lowp vec2 vWrapEn, in lowp vec2 vClampEn, in lowp vec2 vMirrorEn) \n"
"{ \n"
" highp vec2 texCoord = vTexCoord; \n"
" highp vec2 clampedCoord = clamp(texCoord, vec2(0.0), vClamp); \n"
" texCoord += vClampEn*(clampedCoord-texCoord); \n"
" lowp vec2 needMirror = step(vWrap, mod(texCoord, 2.0*vWrap)); \n"
" highp vec2 invertedCoord = mod(-texCoord-vec2(1.0), vWrap); \n"
" texCoord += vMirrorEn*needMirror*(invertedCoord-texCoord); \n"
" highp vec2 wrappedCoord = mod(texCoord,vWrap); \n"
" texCoord += vWrapEn*(wrappedCoord-texCoord); \n"
" return texCoord; \n"
"} \n"
"highp vec2[5] textureEngine0(in highp vec2 texCoord) \n" "highp vec2[5] textureEngine0(in highp vec2 texCoord) \n"
"{ \n" "{ \n"
" highp vec2[5] tcData; \n" // {tc00, tc01, tc10, tc11, frPart} " highp vec2[5] tcData; \n" // {tc00, tc01, tc10, tc11, frPart}
" mediump vec2 intPart = floor(texCoord); \n" " mediump vec2 intPart = floor(texCoord); \n"
" tcData[0] = clampWrapMirror(intPart, uTexWrap0, uTexClamp0, uTexClampEn0, uTexMirrorEn0); \n" " tcData[0] = clampWrapMirror(intPart, uTexWrap0, uTexClamp0, uTexWrapEn0, uTexClampEn0, uTexMirrorEn0); \n"
" tcData[3] = clampWrapMirror(intPart + vec2(1.0,1.0), uTexWrap0, uTexClamp0, uTexClampEn0, uTexMirrorEn0); \n" " tcData[3] = clampWrapMirror(intPart + vec2(1.0,1.0), uTexWrap0, uTexClamp0, uTexWrapEn0, uTexClampEn0, uTexMirrorEn0); \n"
" tcData[1] = vec2(tcData[0].s, tcData[3].t); \n" " tcData[1] = vec2(tcData[0].s, tcData[3].t); \n"
" tcData[2] = vec2(tcData[3].s, tcData[0].t); \n" " tcData[2] = vec2(tcData[3].s, tcData[0].t); \n"
" tcData[4] = texCoord - intPart; \n" " tcData[4] = texCoord - intPart; \n"
" return tcData;" " return tcData;"
"} \n" "} \n"
"highp vec2[5] textureEngine1(in highp vec2 texCoord) \n" "highp vec2[5] textureEngine1(in highp vec2 texCoord) \n"
"{ \n" "{ \n"
" highp vec2[5] tcData; \n" // {tc00, tc01, tc10, tc11, frPart} " highp vec2[5] tcData; \n" // {tc00, tc01, tc10, tc11, frPart}
" mediump vec2 intPart = floor(texCoord); \n" " mediump vec2 intPart = floor(texCoord); \n"
" tcData[0] = clampWrapMirror(intPart, uTexWrap1, uTexClamp1, uTexClampEn1, uTexMirrorEn1); \n" " tcData[0] = clampWrapMirror(intPart, uTexWrap1, uTexClamp1, uTexWrapEn1, uTexClampEn1, uTexMirrorEn1); \n"
" tcData[3] = clampWrapMirror(intPart + vec2(1.0,1.0), uTexWrap1, uTexClamp1, uTexClampEn1, uTexMirrorEn1); \n" " tcData[3] = clampWrapMirror(intPart + vec2(1.0,1.0), uTexWrap1, uTexClamp1, uTexWrapEn1, uTexClampEn1, uTexMirrorEn1); \n"
" tcData[1] = vec2(tcData[0].s, tcData[3].t); \n" " tcData[1] = vec2(tcData[0].s, tcData[3].t); \n"
" tcData[2] = vec2(tcData[3].s, tcData[0].t); \n" " tcData[2] = vec2(tcData[3].s, tcData[0].t); \n"
" tcData[4] = texCoord - intPart; \n" " tcData[4] = texCoord - intPart; \n"
@ -2664,7 +2582,6 @@ graphics::CombinerProgram * CombinerProgramBuilder::buildCombinerProgram(Combine
m_fragmentHeaderWriteDepth->write(ssShader); m_fragmentHeaderWriteDepth->write(ssShader);
m_fragmentHeaderDepthCompare->write(ssShader); m_fragmentHeaderDepthCompare->write(ssShader);
m_fragmentHeaderReadMSTex->write(ssShader); m_fragmentHeaderReadMSTex->write(ssShader);
m_fragmentHeaderClampWrapMirror->write(ssShader);
m_fragmentHeaderTextureEngine->write(ssShader); m_fragmentHeaderTextureEngine->write(ssShader);
if (bUseLod) if (bUseLod)
m_fragmentHeaderMipMap->write(ssShader); m_fragmentHeaderMipMap->write(ssShader);
@ -2700,12 +2617,10 @@ graphics::CombinerProgram * CombinerProgramBuilder::buildCombinerProgram(Combine
if (bUseTextures) { if (bUseTextures) {
if (combinerInputs.usesTile(0)) if (combinerInputs.usesTile(0))
{ {
m_fragmentClampWrapMirrorTex0->write(ssShader);
m_fragmentTextureEngineTex0->write(ssShader); m_fragmentTextureEngineTex0->write(ssShader);
} }
if (combinerInputs.usesTile(1)) if (combinerInputs.usesTile(1))
{ {
m_fragmentClampWrapMirrorTex1->write(ssShader);
m_fragmentTextureEngineTex1->write(ssShader); m_fragmentTextureEngineTex1->write(ssShader);
} }
@ -2746,7 +2661,6 @@ graphics::CombinerProgram * CombinerProgramBuilder::buildCombinerProgram(Combine
m_shaderCalcLight->write(ssShader); m_shaderCalcLight->write(ssShader);
if (bUseTextures) { if (bUseTextures) {
m_shaderClampWrapMirror->write(ssShader);
m_shaderTextureEngine->write(ssShader); m_shaderTextureEngine->write(ssShader);
if (bUseLod) if (bUseLod)
m_shaderMipmap->write(ssShader); m_shaderMipmap->write(ssShader);
@ -2858,7 +2772,6 @@ CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _glinfo, o
, m_fragmentHeaderWriteDepth(new ShaderFragmentHeaderWriteDepth(_glinfo)) , m_fragmentHeaderWriteDepth(new ShaderFragmentHeaderWriteDepth(_glinfo))
, m_fragmentHeaderCalcLight(new ShaderFragmentHeaderCalcLight(_glinfo)) , m_fragmentHeaderCalcLight(new ShaderFragmentHeaderCalcLight(_glinfo))
, m_fragmentHeaderMipMap(new ShaderFragmentHeaderMipMap(_glinfo)) , m_fragmentHeaderMipMap(new ShaderFragmentHeaderMipMap(_glinfo))
, m_fragmentHeaderClampWrapMirror(new ShaderFragmentHeaderClampWrapMirror(_glinfo))
, m_fragmentHeaderTextureEngine(new ShaderFragmentHeaderTextureEngine(_glinfo)) , m_fragmentHeaderTextureEngine(new ShaderFragmentHeaderTextureEngine(_glinfo))
, m_fragmentHeaderReadMSTex(new ShaderFragmentHeaderReadMSTex(_glinfo)) , m_fragmentHeaderReadMSTex(new ShaderFragmentHeaderReadMSTex(_glinfo))
, m_fragmentHeaderDither(new ShaderFragmentHeaderDither(_glinfo)) , m_fragmentHeaderDither(new ShaderFragmentHeaderDither(_glinfo))
@ -2870,8 +2783,6 @@ CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _glinfo, o
, m_fragmentBlendMux(new ShaderFragmentBlendMux(_glinfo)) , m_fragmentBlendMux(new ShaderFragmentBlendMux(_glinfo))
, m_fragmentReadTex0(new ShaderFragmentReadTex0(_glinfo)) , m_fragmentReadTex0(new ShaderFragmentReadTex0(_glinfo))
, m_fragmentReadTex1(new ShaderFragmentReadTex1(_glinfo)) , m_fragmentReadTex1(new ShaderFragmentReadTex1(_glinfo))
, m_fragmentClampWrapMirrorTex0(new ShaderFragmentClampWrapMirrorTex0(_glinfo))
, m_fragmentClampWrapMirrorTex1(new ShaderFragmentClampWrapMirrorTex1(_glinfo))
, m_fragmentTextureEngineTex0(new ShaderFragmentTextureEngineTex0(_glinfo)) , m_fragmentTextureEngineTex0(new ShaderFragmentTextureEngineTex0(_glinfo))
, m_fragmentTextureEngineTex1(new ShaderFragmentTextureEngineTex1(_glinfo)) , m_fragmentTextureEngineTex1(new ShaderFragmentTextureEngineTex1(_glinfo))
, m_fragmentReadTexCopyMode(new ShaderFragmentReadTexCopyMode(_glinfo)) , m_fragmentReadTexCopyMode(new ShaderFragmentReadTexCopyMode(_glinfo))
@ -2888,7 +2799,6 @@ CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _glinfo, o
, m_shaderReadtexCopyMode(new ShaderReadtexCopyMode(_glinfo)) , m_shaderReadtexCopyMode(new ShaderReadtexCopyMode(_glinfo))
, m_shaderN64DepthCompare(new ShaderN64DepthCompare(_glinfo)) , m_shaderN64DepthCompare(new ShaderN64DepthCompare(_glinfo))
, m_shaderN64DepthRender(new ShaderN64DepthRender(_glinfo)) , m_shaderN64DepthRender(new ShaderN64DepthRender(_glinfo))
, m_shaderClampWrapMirror(new ShaderClampWrapMirror(_glinfo))
, m_shaderTextureEngine(new ShaderTextureEngine(_glinfo)) , m_shaderTextureEngine(new ShaderTextureEngine(_glinfo))
, m_useProgram(_useProgram) , m_useProgram(_useProgram)
, m_combinerOptionsBits(graphics::CombinerProgram::getShaderCombinerOptionsBits()) , m_combinerOptionsBits(graphics::CombinerProgram::getShaderCombinerOptionsBits())

View File

@ -62,7 +62,6 @@ namespace glsl {
ShaderPartPtr m_fragmentHeaderWriteDepth; ShaderPartPtr m_fragmentHeaderWriteDepth;
ShaderPartPtr m_fragmentHeaderCalcLight; ShaderPartPtr m_fragmentHeaderCalcLight;
ShaderPartPtr m_fragmentHeaderMipMap; ShaderPartPtr m_fragmentHeaderMipMap;
ShaderPartPtr m_fragmentHeaderClampWrapMirror;
ShaderPartPtr m_fragmentHeaderTextureEngine; ShaderPartPtr m_fragmentHeaderTextureEngine;
ShaderPartPtr m_fragmentHeaderReadMSTex; ShaderPartPtr m_fragmentHeaderReadMSTex;
ShaderPartPtr m_fragmentHeaderDither; ShaderPartPtr m_fragmentHeaderDither;
@ -74,8 +73,6 @@ namespace glsl {
ShaderPartPtr m_fragmentBlendMux; ShaderPartPtr m_fragmentBlendMux;
ShaderPartPtr m_fragmentReadTex0; ShaderPartPtr m_fragmentReadTex0;
ShaderPartPtr m_fragmentReadTex1; ShaderPartPtr m_fragmentReadTex1;
ShaderPartPtr m_fragmentClampWrapMirrorTex0;
ShaderPartPtr m_fragmentClampWrapMirrorTex1;
ShaderPartPtr m_fragmentTextureEngineTex0; ShaderPartPtr m_fragmentTextureEngineTex0;
ShaderPartPtr m_fragmentTextureEngineTex1; ShaderPartPtr m_fragmentTextureEngineTex1;
ShaderPartPtr m_fragmentReadTexCopyMode; ShaderPartPtr m_fragmentReadTexCopyMode;
@ -93,7 +90,6 @@ namespace glsl {
ShaderPartPtr m_shaderReadtexCopyMode; ShaderPartPtr m_shaderReadtexCopyMode;
ShaderPartPtr m_shaderN64DepthCompare; ShaderPartPtr m_shaderN64DepthCompare;
ShaderPartPtr m_shaderN64DepthRender; ShaderPartPtr m_shaderN64DepthRender;
ShaderPartPtr m_shaderClampWrapMirror;
ShaderPartPtr m_shaderTextureEngine; ShaderPartPtr m_shaderTextureEngine;
std::unique_ptr<CombinerProgramUniformFactory> m_uniformFactory; std::unique_ptr<CombinerProgramUniformFactory> m_uniformFactory;

View File

@ -914,7 +914,7 @@ public:
f32 shiftScaleT = 1.0f; f32 shiftScaleT = 1.0f;
getTextureShiftScale(t, cache, shiftScaleS, shiftScaleT); getTextureShiftScale(t, cache, shiftScaleS, shiftScaleT);
uCacheShiftScale[t].set(shiftScaleS, shiftScaleT, _force); uCacheShiftScale[t].set(shiftScaleS, shiftScaleT, _force);
uCacheScale[t].set(_pTexture->scaleS, _pTexture->scaleT, _force); uCacheScale[t].set(_pTexture->hdRatioS, _pTexture->hdRatioT, _force);
uCacheOffset[t].set(_pTexture->offsetS, _pTexture->offsetT, _force); uCacheOffset[t].set(_pTexture->offsetS, _pTexture->offsetT, _force);
nFB[t] = _pTexture->frameBufferTexture; nFB[t] = _pTexture->frameBufferTexture;
} }
@ -934,30 +934,33 @@ private:
iv2Uniform uCacheFrameBuffer; iv2Uniform uCacheFrameBuffer;
}; };
class UClampWrapMirrorTex : public UniformGroup class UTextureEngine : public UniformGroup
{ {
public: public:
UClampWrapMirrorTex(GLuint _program, bool _useT0, bool _useT1) UTextureEngine(GLuint _program, bool _useT0, bool _useT1)
{ {
m_useTile[0] = _useT0; m_useTile[0] = _useT0;
m_useTile[1] = _useT1; m_useTile[1] = _useT1;
LocateUniform(uTexClamp0);
LocateUniform(uTexClamp1);
LocateUniform(uTexWrap0); LocateUniform(uTexWrap0);
LocateUniform(uTexWrap1); LocateUniform(uTexWrap1);
LocateUniform(uTexMirror0); LocateUniform(uTexClamp0);
LocateUniform(uTexMirror1); LocateUniform(uTexClamp1);
LocateUniform(uTexScale0); LocateUniform(uTexWrapEn0);
LocateUniform(uTexScale1); LocateUniform(uTexWrapEn1);
LocateUniform(uTexClampEn0);
LocateUniform(uTexClampEn1);
LocateUniform(uTexMirrorEn0);
LocateUniform(uTexMirrorEn1);
} }
void update(bool _force) override void update(bool _force) override
{ {
std::array<f32, 4> aTexClamp[2] = { { -10000.0f, -10000.0f, 10000.0f, 10000.0f }, std::array<f32, 2> aTexWrap[2] = { {0.0f,0.0f}, {0.0f,0.0f} };
{ -10000.0f, -10000.0f, 10000.0f, 10000.0f } }; std::array<f32, 2> aTexClamp[2] = { { 0.0f,0.0f },{ 0.0f,0.0f } };
std::array<f32, 2> aTexWrap[2] = { { 10000.0f, 10000.0f }, { 10000.0f, 10000.0f } }; std::array<f32, 2> aTexWrapEn[2] = { { 0.0f,0.0f },{ 0.0f,0.0f } };
std::array<f32, 2> aTexMirror[2] = { { 0.0f, 0.0f}, { 0.0f, 0.0f } }; std::array<f32, 2> aTexClampEn[2] = { { 0.0f,0.0f },{ 0.0f,0.0f } };
std::array<f32, 2> aTexScale[2] = { { 1.0f, 1.0f },{ 1.0f, 1.0f } }; std::array<f32, 2> aTexMirrorEn[2] = { { 0.0f,0.0f },{ 0.0f,0.0f } };
TextureCache & cache = textureCache(); TextureCache & cache = textureCache();
const bool replaceTex1ByTex0 = needReplaceTex1ByTex0(); const bool replaceTex1ByTex0 = needReplaceTex1ByTex0();
for (u32 t = 0; t < 2; ++t) { for (u32 t = 0; t < 2; ++t) {
@ -969,75 +972,62 @@ public:
CachedTexture * pTexture = cache.current[tile]; CachedTexture * pTexture = cache.current[tile];
if (pTile == nullptr || pTexture == nullptr) if (pTile == nullptr || pTexture == nullptr)
continue; continue;
/* Not sure if special treatment of framebuffer textures is correct */
if (pTexture->frameBufferTexture != CachedTexture::fbNone)
{
aTexWrap[t][0] = 1.0;
aTexWrap[t][1] = 1.0;
aTexClamp[t][0] = f32(pTexture->width) - 1.0;
aTexClamp[t][1] = f32(pTexture->height) - 1.0;
aTexWrapEn[t][0] = 0.0;
aTexWrapEn[t][1] = 0.0;
aTexClampEn[t][0] = 1.0;
aTexClampEn[t][1] = 1.0;
aTexMirrorEn[t][0] = 0.0;
aTexMirrorEn[t][1] = 0.0;
if (gDP.otherMode.cycleType != G_CYC_COPY) {
if (pTexture->clampS) {
aTexClamp[t][0] = 0.0f; // S lower bound
if (pTexture->frameBufferTexture != CachedTexture::fbNone ||
pTile->textureMode == TEXTUREMODE_BGIMAGE)
aTexClamp[t][2] = 1.0f;
else {
u32 tileWidth = ((pTile->lrs - pTile->uls) & 0x03FF) + 1;
if (pTile->size > pTexture->size)
tileWidth <<= pTile->size - pTexture->size;
// aTexClamp[t][2] = f32(tileWidth) / (pTexture->mirrorS ? f32(pTexture->width) : f32(pTexture->clampWidth)); // S upper bound
aTexClamp[t][2] = f32(tileWidth) / f32(pTexture->width); // S upper bound
}
}
if (pTexture->clampT) {
aTexClamp[t][1] = 0.0f; // T lower bound
if (pTexture->frameBufferTexture != CachedTexture::fbNone ||
pTile->textureMode == TEXTUREMODE_BGIMAGE)
aTexClamp[t][3] = 1.0f;
else {
const u32 tileHeight = ((pTile->lrt - pTile->ult) & 0x03FF) + 1;
// aTexClamp[t][3] = f32(tileHeight) / (pTexture->mirrorT ? f32(pTexture->height) : f32(pTexture->clampHeight)); // T upper bound
aTexClamp[t][3] = f32(tileHeight) / f32(pTexture->height); // T upper bound
}
}
} }
if (pTexture->maskS) { else
const f32 wrapWidth = static_cast<f32>(1 << pTile->originalMaskS); {
const f32 pow2Width = static_cast<f32>(pow2(pTexture->width)); aTexWrap[t][0] = f32(1 << pTile->masks) * pTexture->hdRatioS;
aTexWrap[t][0] = wrapWidth / pow2Width; aTexWrap[t][1] = f32(1 << pTile->maskt) * pTexture->hdRatioT;
aTexScale[t][0] = pow2Width / f32(pTexture->width); aTexClamp[t][0] = (pTile->flrs - pTile->fuls + 1.0) * pTexture->hdRatioS - 1.0;
} aTexClamp[t][1] = (pTile->flrt - pTile->fult + 1.0) * pTexture->hdRatioT - 1.0;
if (pTexture->maskT) { aTexWrapEn[t][0] = f32(pTile->masks == 0 ? 0 : 1);
const f32 wrapHeight = static_cast<f32>(1 << pTile->originalMaskT); aTexWrapEn[t][1] = f32(pTile->maskt == 0 ? 0 : 1);
const f32 pow2Height = static_cast<f32>(pow2(pTexture->height)); aTexClampEn[t][0] = f32(pTile->masks == 0 ? 1 : pTile->clamps);
aTexWrap[t][1] = wrapHeight / pow2Height; aTexClampEn[t][1] = f32(pTile->maskt == 0 ? 1 : pTile->clampt);
aTexScale[t][1] = pow2Height / f32(pTexture->height); aTexMirrorEn[t][0] = f32(pTile->masks == 0 ? 0 : pTile->mirrors);
} aTexMirrorEn[t][1] = f32(pTile->maskt == 0 ? 0 : pTile->mirrort);
if (pTexture->mirrorS) {
aTexMirror[t][0] = 1.0f;
aTexWrap[t][0] *= 2.0f;
}
if (pTexture->mirrorT) {
aTexMirror[t][1] = 1.0f;
aTexWrap[t][1] *= 2.0f;
} }
} }
uTexClamp0.set(aTexClamp[0].data(), _force);
uTexClamp1.set(aTexClamp[1].data(), _force);
uTexWrap0.set(aTexWrap[0][0], aTexWrap[0][1], _force); uTexWrap0.set(aTexWrap[0][0], aTexWrap[0][1], _force);
uTexWrap1.set(aTexWrap[1][0], aTexWrap[1][1], _force); uTexWrap1.set(aTexWrap[1][0], aTexWrap[1][1], _force);
uTexMirror0.set(aTexMirror[0][0], aTexMirror[0][1], _force); uTexClamp0.set(aTexClamp[0][0], aTexClamp[0][1], _force);
uTexMirror1.set(aTexMirror[1][0], aTexMirror[1][1], _force); uTexClamp1.set(aTexClamp[1][0], aTexClamp[1][1], _force);
uTexScale0.set(aTexScale[0][0], aTexScale[0][1], _force); uTexWrapEn0.set(aTexWrapEn[0][0], aTexWrapEn[0][1], _force);
uTexScale1.set(aTexScale[1][0], aTexScale[1][1], _force); uTexWrapEn1.set(aTexWrapEn[1][0], aTexWrapEn[1][1], _force);
uTexClampEn0.set(aTexClampEn[0][0], aTexClampEn[0][1], _force);
uTexClampEn1.set(aTexClampEn[1][0], aTexClampEn[1][1], _force);
uTexMirrorEn0.set(aTexMirrorEn[0][0], aTexMirrorEn[0][1], _force);
uTexMirrorEn1.set(aTexMirrorEn[1][0], aTexMirrorEn[1][1], _force);
} }
private: private:
bool m_useTile[2]; bool m_useTile[2];
fv4Uniform uTexClamp0;
fv4Uniform uTexClamp1;
fv2Uniform uTexWrap0; fv2Uniform uTexWrap0;
fv2Uniform uTexWrap1; fv2Uniform uTexWrap1;
fv2Uniform uTexMirror0; fv2Uniform uTexClamp0;
fv2Uniform uTexMirror1; fv2Uniform uTexClamp1;
fv2Uniform uTexScale0; fv2Uniform uTexWrapEn0;
fv2Uniform uTexScale1; fv2Uniform uTexWrapEn1;
fv2Uniform uTexClampEn0;
fv2Uniform uTexClampEn1;
fv2Uniform uTexMirrorEn0;
fv2Uniform uTexMirrorEn1;
}; };
class ULights : public UniformGroup class ULights : public UniformGroup
@ -1107,7 +1097,7 @@ void CombinerProgramUniformFactory::buildUniforms(GLuint _program,
if (!_key.isRectKey()) if (!_key.isRectKey())
_uniforms.emplace_back(new UTextureParams(_program, _inputs.usesTile(0), _inputs.usesTile(1))); _uniforms.emplace_back(new UTextureParams(_program, _inputs.usesTile(0), _inputs.usesTile(1)));
_uniforms.emplace_back(new UClampWrapMirrorTex(_program, _inputs.usesTile(0), _inputs.usesTile(1))); _uniforms.emplace_back(new UTextureEngine(_program, _inputs.usesTile(0), _inputs.usesTile(1)));
} }
_uniforms.emplace_back(new UFog(_program)); _uniforms.emplace_back(new UFog(_program));

View File

@ -1342,10 +1342,19 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
} }
} }
texST[t].s0 *= cache.current[t]->scaleS; if (gDP.otherMode.textureFilter != G_TF_POINT && gDP.otherMode.cycleType != G_CYC_COPY) {
texST[t].t0 *= cache.current[t]->scaleT; texST[t].s0 -= 0.5f;
texST[t].s1 *= cache.current[t]->scaleS; texST[t].t0 -= 0.5f;
texST[t].t1 *= cache.current[t]->scaleT; texST[t].s1 -= 0.5f;
texST[t].t1 -= 0.5f;
}
texST[t].s0 *= cache.current[t]->hdRatioS;
texST[t].t0 *= cache.current[t]->hdRatioT;
texST[t].s1 *= cache.current[t]->hdRatioS;
texST[t].t1 *= cache.current[t]->hdRatioT;
} }
} }

View File

@ -446,6 +446,8 @@ void TextureCache::_initDummyTexture(CachedTexture * _pDummy)
_pDummy->maskT = 0; _pDummy->maskT = 0;
_pDummy->scaleS = 0.5f; _pDummy->scaleS = 0.5f;
_pDummy->scaleT = 0.5f; _pDummy->scaleT = 0.5f;
_pDummy->hdRatioS = 1.0f;
_pDummy->hdRatioT = 1.0f;
_pDummy->shiftScaleS = 1.0f; _pDummy->shiftScaleS = 1.0f;
_pDummy->shiftScaleT = 1.0f; _pDummy->shiftScaleT = 1.0f;
_pDummy->textureBytes = 2 * 2 * 4; _pDummy->textureBytes = 2 * 2 * 4;
@ -670,6 +672,9 @@ void _updateCachedTexture(const GHQTexInfo & _info, CachedTexture *_pTexture, u1
_pTexture->scaleS = 1.0f / (_pTexture->maskS ? f32(pow2(widthOrg)) : f32(widthOrg)); _pTexture->scaleS = 1.0f / (_pTexture->maskS ? f32(pow2(widthOrg)) : f32(widthOrg));
_pTexture->scaleT = 1.0f / (_pTexture->maskT ? f32(pow2(heightOrg)) : f32(heightOrg)); _pTexture->scaleT = 1.0f / (_pTexture->maskT ? f32(pow2(heightOrg)) : f32(heightOrg));
_pTexture->hdRatioS = f32(_info.width / _pTexture->width);
_pTexture->hdRatioT = f32(_info.height / _pTexture->height);
_pTexture->bHDTexture = true; _pTexture->bHDTexture = true;
} }
@ -1416,6 +1421,9 @@ void TextureCache::_updateBackground()
pCurrent->scaleS = 1.0f / (f32)(pCurrent->width); pCurrent->scaleS = 1.0f / (f32)(pCurrent->width);
pCurrent->scaleT = 1.0f / (f32)(pCurrent->height); pCurrent->scaleT = 1.0f / (f32)(pCurrent->height);
pCurrent->hdRatioS = 1.0f;
pCurrent->hdRatioT = 1.0f;
pCurrent->shiftScaleS = 1.0f; pCurrent->shiftScaleS = 1.0f;
pCurrent->shiftScaleT = 1.0f; pCurrent->shiftScaleT = 1.0f;
@ -1571,6 +1579,9 @@ void TextureCache::update(u32 _t)
pCurrent->scaleS = 1.0f / (pCurrent->maskS ? f32(pow2(pCurrent->width)) : f32(pCurrent->width)); pCurrent->scaleS = 1.0f / (pCurrent->maskS ? f32(pow2(pCurrent->width)) : f32(pCurrent->width));
pCurrent->scaleT = 1.0f / (pCurrent->maskT ? f32(pow2(pCurrent->height)) : f32(pCurrent->height)); pCurrent->scaleT = 1.0f / (pCurrent->maskT ? f32(pow2(pCurrent->height)) : f32(pCurrent->height));
pCurrent->hdRatioS = 1.0f;
pCurrent->hdRatioT = 1.0f;
pCurrent->offsetS = 0.0f; pCurrent->offsetS = 0.0f;
pCurrent->offsetT = 0.0f; pCurrent->offsetT = 0.0f;

View File

@ -33,6 +33,7 @@ struct CachedTexture
u16 width, height; // N64 width and height u16 width, height; // N64 width and height
u16 clampWidth, clampHeight; // Size to clamp to u16 clampWidth, clampHeight; // Size to clamp to
f32 scaleS, scaleT; // Scale to map to 0.0-1.0 f32 scaleS, scaleT; // Scale to map to 0.0-1.0
f32 hdRatioS, hdRatioT; // HD / N64 width and height
f32 shiftScaleS, shiftScaleT; // Scale to shift f32 shiftScaleS, shiftScaleT; // Scale to shift
u32 textureBytes; u32 textureBytes;