diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp index d9b6c983..69a42292 100644 --- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp @@ -2122,32 +2122,75 @@ public: 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" + "#define READ_TEX0_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" + "#define READ_TEX1_MIPMAP(name, tex, tcData, tile) \\\n" + "{ \\\n" + // Fetch from texture atlas + // First 8 texels contain info about tile size and offset, 1 texel per tile + " mediump vec4 texWdthAndOff0 = 255.0 * texelFetch(tex, ivec2(0, 0), 0); \\\n" + " mediump vec4 texWdthAndOff = 255.0 * texelFetch(tex, ivec2(int(tile), 0), 0); \\\n" + " mediump vec2 lod_scale = texWdthAndOff.ba / texWdthAndOff0.ba; \\\n" + " mediump int offset = int(texWdthAndOff.r) + int(texWdthAndOff.g) * 256; \\\n" + " mediump int width = int(texWdthAndOff.b); \\\n" + " mediump ivec2 iCoords00 = ivec2(tcData[0] * lod_scale); \\\n" + " lowp vec4 c00 = texelFetch(tex, ivec2(offset + width * iCoords00.t + iCoords00.s, 0), 0); \\\n" + " mediump ivec2 iCoords01 = ivec2(tcData[1] * lod_scale); \\\n" + " lowp vec4 c01 = texelFetch(tex, ivec2(offset + width * iCoords01.t + iCoords01.s, 0), 0); \\\n" + " mediump ivec2 iCoords10 = ivec2(tcData[2] * lod_scale); \\\n" + " lowp vec4 c10 = texelFetch(tex, ivec2(offset + width * iCoords10.t + iCoords10.s, 0), 0); \\\n" + " mediump ivec2 iCoords11 = ivec2(tcData[3] * lod_scale); \\\n" + " lowp vec4 c11 = texelFetch(tex, ivec2(offset + width * iCoords11.t + iCoords11.s, 0), 0); \\\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" + " lowp float bottomRightTri = step(1.0, tcData[4].s + tcData[4].t); \\\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" + "#define READ_TEX0_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" + "#define READ_TEX1_MIPMAP(name, tex, tcData, tile) \\\n" + "{ \\\n" + // Fetch from texture atlas + // First 8 texels contain info about tile size and offset, 1 texel per tile + " mediump vec4 texWdthAndOff0 = 255.0 * texelFetch(tex, ivec2(0, 0), 0); \\\n" + " mediump vec4 texWdthAndOff = 255.0 * texelFetch(tex, ivec2(int(tile), 0), 0); \\\n" + " mediump vec2 lod_scale = texWdthAndOff.ba / texWdthAndOff0.ba; \\\n" + " mediump int offset = int(texWdthAndOff.r) + int(texWdthAndOff.g) * 256; \\\n" + " mediump int width = int(texWdthAndOff.b); \\\n" + " mediump ivec2 iCoords00 = ivec2(tcData[0] * lod_scale); \\\n" + " lowp vec4 c00 = texelFetch(tex, ivec2(offset + width * iCoords00.t + iCoords00.s, 0), 0); \\\n" + " mediump ivec2 iCoords01 = ivec2(tcData[1] * lod_scale); \\\n" + " lowp vec4 c01 = texelFetch(tex, ivec2(offset + width * iCoords01.t + iCoords01.s, 0), 0); \\\n" + " mediump ivec2 iCoords10 = ivec2(tcData[2] * lod_scale); \\\n" + " lowp vec4 c10 = texelFetch(tex, ivec2(offset + width * iCoords10.t + iCoords10.s, 0), 0); \\\n" + " mediump ivec2 iCoords11 = ivec2(tcData[3] * lod_scale); \\\n" + " lowp vec4 c11 = texelFetch(tex, ivec2(offset + width * iCoords11.t + iCoords11.s, 0), 0); \\\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) { // Fake mipmap @@ -2156,8 +2199,8 @@ public: "uniform mediump float uMinLod; \n" " \n" "mediump float mipmap(out lowp vec4 readtex0, out lowp vec4 readtex1) { \n" - " READ_TEX_MIPMAP(readtex0, uTex0, tcData0, 0); \n" - " READ_TEX_MIPMAP(readtex1, uTex1, tcData1, 0); \n" + " READ_TEX_MIPMAP0(readtex0, uTex0, tcData0, 0); \n" + " READ_TEX_MIPMAP0(readtex1, uTex1, tcData1, 0); \n" " if (uMaxTile == 0) return 1.0; \n" " return uMinLod; \n" "} \n" @@ -2170,13 +2213,14 @@ public: "uniform lowp int uTextureDetail; \n" " \n" "mediump float mipmap(out lowp vec4 readtex0, out lowp vec4 readtex1) { \n" - " READ_TEX_MIPMAP(readtex0, uTex0, tcData0, 0); \n" - " READ_TEX_MIPMAP(readtex1, uTex1, tcData1, 0); \n" + " READ_TEX0_MIPMAP(readtex0, uTex0, tcData0, 0) \n" + " if (uMaxTile > 1) READ_TEX1_MIPMAP(readtex1, uTex1, tcData1, 0) \n" + " else READ_TEX0_MIPMAP(readtex1, uTex1, tcData1, 0) \n" " \n" " mediump float fMaxTile = float(uMaxTile); \n" - " mediump vec2 dx = abs(dFdx(vLodTexCoord)); \n" - " dx *= uScreenScale; \n" - " mediump float lod = max(dx.x, dx.y); \n" + " mediump vec2 dx = abs(dFdx(vLodTexCoord)) * uScreenScale; \n" + " mediump vec2 dy = abs(dFdy(vLodTexCoord)) * uScreenScale; \n" + " mediump float lod = max(max(dx.x, dx.y), max(dy.x, dy.y)); \n" " bool magnify = lod < 1.0; \n" " mediump float lod_tile = magnify ? 0.0 : floor(log2(floor(lod))); \n" " bool distant = lod > 128.0 || lod_tile >= fMaxTile; \n" @@ -2201,9 +2245,9 @@ public: " 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 vec4 lodT, lodT_m1, lodT_p1; \n" - " READ_TEX_MIPMAP(lodT, uTex1, tcData1, lod_tile); \n" - " READ_TEX_MIPMAP(lodT_m1, uTex1, tcData1, lod_tile_m1); \n" - " READ_TEX_MIPMAP(lodT_p1, uTex1, tcData1, lod_tile_p1); \n" + " READ_TEX1_MIPMAP(lodT, uTex1, tcData1, lod_tile); \n" + " READ_TEX1_MIPMAP(lodT_m1, uTex1, tcData1, lod_tile_m1); \n" + " READ_TEX1_MIPMAP(lodT_p1, uTex1, tcData1, lod_tile_p1); \n" " if (lod_tile < 1.0) { \n" " if (magnify) { \n" // !sharpen && !detail diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp index 668cedb9..43771cdd 100644 --- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "glsl_CombinerProgramUniformFactory.h" @@ -15,6 +16,10 @@ #include #include +#ifdef min +#undef min +#endif + namespace glsl { /*---------------Uniform-------------*/ @@ -588,7 +593,11 @@ public: void update(bool _force) override { uMinLod.set(gDP.primColor.m, _force); - uMaxTile.set(gSP.texture.level, _force); + const CachedTexture * _pTexture = textureCache().current[1]; + if (_pTexture == nullptr) + uMaxTile.set(gSP.texture.level, _force); + else + uMaxTile.set(_pTexture->max_level > 0 ? gSP.texture.level : std::min(gSP.texture.level, 1u), _force); } private: diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_ShaderStorage.h b/src/Graphics/OpenGLContext/GLSL/glsl_ShaderStorage.h index a56ca2de..0fce4232 100644 --- a/src/Graphics/OpenGLContext/GLSL/glsl_ShaderStorage.h +++ b/src/Graphics/OpenGLContext/GLSL/glsl_ShaderStorage.h @@ -20,7 +20,7 @@ namespace glsl { bool _saveCombinerKeys(const graphics::Combiners & _combiners) const; bool _loadFromCombinerKeys(graphics::Combiners & _combiners); - const u32 m_formatVersion = 0x36U; + const u32 m_formatVersion = 0x37U; const u32 m_keysFormatVersion = 0x05; const opengl::GLInfo & m_glinfo; opengl::CachedUseProgram * m_useProgram; diff --git a/src/Textures.cpp b/src/Textures.cpp index eeb16723..0a79d0d1 100644 --- a/src/Textures.cpp +++ b/src/Textures.cpp @@ -1106,27 +1106,14 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture) if (_loadHiresTexture(_tile, _pTexture, ricecrc)) return; - s32 mipLevel = 0; bool force32bitFormat = false; _pTexture->max_level = 0; - if (config.generalEmulation.enableLOD != 0 && gSP.texture.level > 1) { - if (_tile == 0) { - _pTexture->max_level = 0; - } else { - _pTexture->max_level = static_cast(gSP.texture.level - 1); - const u16 dim = std::max(_pTexture->width, _pTexture->height); - while (dim < static_cast(1 << _pTexture->max_level)) - --_pTexture->max_level; - - auto texFormat = gDP.tiles[gSP.texture.tile + 1].format; - auto texSize = gDP.tiles[gSP.texture.tile + 1].size; - u32 tileMipLevel = gSP.texture.tile + 2; - while (!force32bitFormat && (tileMipLevel < gSP.texture.tile + gSP.texture.level)) { - gDPTile const& mipTile = gDP.tiles[tileMipLevel++]; - force32bitFormat = texFormat != mipTile.format || texSize != mipTile.size; - } - } + if (config.generalEmulation.enableLOD != 0 && gSP.texture.level > 1 && _tile > 0) { + _pTexture->max_level = gDP.otherMode.textureDetail == G_TD_DETAIL ? + static_cast(gSP.texture.level) : + static_cast(gSP.texture.level - 1); + force32bitFormat = _pTexture->max_level > 0; } u32 sizeShift = 1; @@ -1158,7 +1145,7 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture) } private: u32 *pData = NULL; - } texData(_pTexture->textureBytes); + } texData((_pTexture->textureBytes + 8*sizeof(u32)) * (_pTexture->max_level + 1)); GetTexelFunc GetTexel; InternalColorFormatParam glInternalFormat; @@ -1183,32 +1170,71 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture) CachedTexture tmptex = *_pTexture; u16 line = tmptex.line; - while (true) { - getLoadParams(tmptex.format, tmptex.size); + if (_pTexture->max_level > 0) + { + u32 mipLevel = 0; + u32 texDataOffset = 8; // number of gDP.tiles + + // Load all tiles into one 1D texture atlas. + while (true) { + const u32 tileSizePacked = texDataOffset | (tmptex.width << 16) | (tmptex.height << 24); + texData.get()[mipLevel] = tileSizePacked; + + getLoadParams(tmptex.format, tmptex.size); + _getTextureDestData(tmptex, texData.get() + texDataOffset, glInternalFormat, GetTexel, &line); + + if (m_toggleDumpTex && + config.textureFilter.txHiresEnable != 0 && + config.hotkeys.enabledKeys[Config::HotKey::hkTexDump] != 0) { + txfilter_dmptx((u8*)texData.get() + texDataOffset, tmptex.width, tmptex.height, + tmptex.width, (u16)u32(glInternalFormat), + (unsigned short)(_pTexture->format << 8 | _pTexture->size), + ricecrc); + } + + texDataOffset += tmptex.width * tmptex.height; + if (mipLevel == _pTexture->max_level) + break; + ++mipLevel; const u32 tileMipLevel = gSP.texture.tile + mipLevel + 1; gDPTile & mipTile = gDP.tiles[tileMipLevel]; - if (tmptex.max_level > 1 && - tmptex.width == (mipTile.lrs - mipTile.uls + 1) * 2 && - tmptex.height == (mipTile.lrt - mipTile.ult + 1) * 2) - { - // Special case for Southern Swamp grass texture, Zelda MM. See #2315 - const u16 texWidth = tmptex.width; - const u16 texHeight = tmptex.height; - tmptex.width = mipTile.lrs - mipTile.uls + 1; - tmptex.height = mipTile.lrt - mipTile.ult + 1; - _getTextureDestData(tmptex, texData.get(), glInternalFormat, GetTexel, &line); - if (sizeShift == 2) - doubleTexture(texData.get(), tmptex.width, tmptex.height); - else - doubleTexture((u16*)texData.get(), tmptex.width, tmptex.height); - tmptex.width = texWidth; - tmptex.height = texHeight; - } else { - _getTextureDestData(tmptex, texData.get(), glInternalFormat, GetTexel, &line); - } + gDPTile & prevMipTile = gDP.tiles[tileMipLevel - 1]; + line = mipTile.line; + tmptex.tMem = mipTile.tmem; + tmptex.palette = mipTile.palette; + tmptex.maskS = mipTile.masks; + tmptex.maskT = mipTile.maskt; + tmptex.format = mipTile.format; + tmptex.size = mipTile.size; + TileSizes sizes; + _calcTileSizes(tileMipLevel, sizes, nullptr); + tmptex.width = sizes.width; + tmptex.height = sizes.height; + tmptex.clampWidth = sizes.clampWidth; + tmptex.clampHeight = sizes.clampHeight; + _pTexture->textureBytes += (tmptex.width * tmptex.height) << sizeShift; } + Context::InitTextureParams params; + params.handle = _pTexture->name; + params.textureUnitIndex = textureIndices::Tex[_tile]; + params.mipMapLevel = 0; + params.mipMapLevels =1; + params.msaaLevel = 0; + params.width = texDataOffset; + params.height = 1; + params.internalFormat = gfxContext.convertInternalTextureFormat(u32(glInternalFormat)); + params.format = colorFormat::RGBA; + params.dataType = glType; + params.data = texData.get(); + gfxContext.init2DTexture(params); + } + else + { + getLoadParams(tmptex.format, tmptex.size); + _getTextureDestData(tmptex, texData.get(), glInternalFormat, GetTexel, &line); + if ((config.generalEmulation.hacks&hack_LoadDepthTextures) != 0 && gDP.colorImage.address == gDP.depthImageAddress) { _loadDepthTexture(_pTexture, (u16*)texData.get()); return; @@ -1276,8 +1302,8 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture) Context::InitTextureParams params; params.handle = _pTexture->name; params.textureUnitIndex = textureIndices::Tex[_tile]; - params.mipMapLevel = mipLevel; - params.mipMapLevels = _pTexture->max_level + 1; + params.mipMapLevel = 0; + params.mipMapLevels = 1; params.msaaLevel = 0; params.width = tmptex.width; params.height = tmptex.height; @@ -1287,28 +1313,6 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture) params.data = texData.get(); gfxContext.init2DTexture(params); } - if (mipLevel == _pTexture->max_level) - break; - ++mipLevel; - const u32 tileMipLevel = gSP.texture.tile + mipLevel + 1; - gDPTile & mipTile = gDP.tiles[tileMipLevel]; - line = mipTile.line; - tmptex.tMem = mipTile.tmem; - tmptex.palette = mipTile.palette; - tmptex.maskS = mipTile.masks; - tmptex.maskT = mipTile.maskt; - tmptex.format = mipTile.format; - tmptex.size = mipTile.size; - TileSizes sizes; - _calcTileSizes(tileMipLevel, sizes, nullptr); - tmptex.clampWidth = sizes.clampWidth; - tmptex.clampHeight = sizes.clampHeight; - // Insure mip-map levels size consistency. - if (tmptex.width > 1) - tmptex.width >>= 1; - if (tmptex.height > 1) - tmptex.height >>= 1; - _pTexture->textureBytes += (tmptex.width * tmptex.height) << sizeShift; } if (m_curUnpackAlignment > 1) gfxContext.setTextureUnpackAlignment(m_curUnpackAlignment);