1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-06-30 08:24:05 +00:00

Add a new "fast" shader path that doesn't use texelFetch in glsl

This commit is contained in:
fzurita 2021-10-11 19:22:23 -04:00
parent 466401cd02
commit 3d5a39e647
33 changed files with 6998 additions and 4096 deletions

View File

@ -309,8 +309,14 @@ copy /Y "$(OutDir)$(TargetName).*" "$(Mupen64PluginsDir_x64)")</Command>
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLFunctions.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerInputs.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilder.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilderCommon.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilderAccurate.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilderFast.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramImpl.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactory.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactoryCommon.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactoryAccurate.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactoryFast.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_FXAA.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_ShaderStorage.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_SpecialShadersFactory.cpp" />
@ -465,8 +471,14 @@ copy /Y "$(OutDir)$(TargetName).*" "$(Mupen64PluginsDir_x64)")</Command>
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLFunctions.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerInputs.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilder.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilderCommon.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilderAccurate.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilderFast.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramImpl.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactory.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactoryCommon.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactoryAccurate.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactoryFast.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_FXAA.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_ShaderPart.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_ShaderStorage.h" />

View File

@ -221,6 +221,9 @@
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilder.cpp">
<Filter>Source Files\Graphics\OpenGL\GLSL</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilderCommon.cpp">
<Filter>Source Files\Graphics\OpenGL\GLSL</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramImpl.cpp">
<Filter>Source Files\Graphics\OpenGL\GLSL</Filter>
</ClCompile>
@ -236,6 +239,9 @@
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactory.cpp">
<Filter>Source Files\Graphics\OpenGL\GLSL</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactoryCommon.cpp">
<Filter>Source Files\Graphics\OpenGL\GLSL</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerInputs.cpp">
<Filter>Source Files\Graphics\OpenGL\GLSL</Filter>
</ClCompile>
@ -425,6 +431,18 @@
<ClCompile Include="..\..\src\BufferCopy\BlueNoiseTexture.cpp">
<Filter>Source Files\BufferCopy</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilderAccurate.cpp">
<Filter>Source Files\Graphics\OpenGL\GLSL</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilderFast.cpp">
<Filter>Source Files\Graphics\OpenGL\GLSL</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactoryAccurate.cpp">
<Filter>Source Files\Graphics\OpenGL\GLSL</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactoryFast.cpp">
<Filter>Source Files\Graphics\OpenGL\GLSL</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\3DMath.h">
@ -787,6 +805,24 @@
<ClInclude Include="..\..\src\resource.h">
<Filter>Resource Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilderCommon.h">
<Filter>Header Files\Graphics\OpenGL\GLSL</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilderAccurate.h">
<Filter>Header Files\Graphics\OpenGL\GLSL</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilderFast.h">
<Filter>Header Files\Graphics\OpenGL\GLSL</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactoryCommon.h">
<Filter>Header Files\Graphics\OpenGL\GLSL</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactoryAccurate.h">
<Filter>Header Files\Graphics\OpenGL\GLSL</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactoryFast.h">
<Filter>Header Files\Graphics\OpenGL\GLSL</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\src\GLideN64.rc">

View File

@ -89,8 +89,14 @@ set(GLideN64_SOURCES
Graphics/OpenGLContext/opengl_Utils.cpp
Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.cpp
Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp
Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilderCommon.cpp
Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilderAccurate.cpp
Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilderFast.cpp
Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.cpp
Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp
Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactoryCommon.cpp
Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactoryAccurate.cpp
Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactoryFast.cpp
Graphics/OpenGLContext/GLSL/glsl_FXAA.cpp
Graphics/OpenGLContext/GLSL/glsl_ShaderStorage.cpp
Graphics/OpenGLContext/GLSL/glsl_SpecialShadersFactory.cpp

View File

@ -51,6 +51,7 @@ void Config::resetToDefaults()
generalEmulation.enableShadersStorage = 1;
generalEmulation.enableLegacyBlending = 0;
generalEmulation.enableHybridFilter = 1;
generalEmulation.enableInaccurateTextureCoordinates = 0;
generalEmulation.hacks = 0;
#if defined(OS_ANDROID) || defined(OS_IOS)
generalEmulation.enableFragmentDepthWrite = 0;

View File

@ -65,6 +65,7 @@ struct Config
u32 enableShadersStorage;
u32 enableLegacyBlending;
u32 enableHybridFilter;
u32 enableInaccurateTextureCoordinates;
u32 enableFragmentDepthWrite;
u32 hacks;
#if defined(OS_ANDROID) || defined(OS_IOS)

View File

@ -223,6 +223,7 @@ void ConfigDialog::_init(bool reInit, bool blockCustomSettings)
// Emulation settings
ui->emulateLodCheckBox->setChecked(config.generalEmulation.enableLOD != 0);
ui->enableInaccurateTextureCoordinatesCheckBox->setChecked(config.generalEmulation.enableInaccurateTextureCoordinates != 0);
ui->enableHWLightingCheckBox->setChecked(config.generalEmulation.enableHWLighting != 0);
ui->enableCoverageCheckBox->setChecked(config.generalEmulation.enableCoverage != 0);
ui->enableShadersStorageCheckBox->setChecked(config.generalEmulation.enableShadersStorage != 0);
@ -562,6 +563,7 @@ void ConfigDialog::accept(bool justSave) {
// Emulation settings
config.generalEmulation.enableLOD = ui->emulateLodCheckBox->isChecked() ? 1 : 0;
config.generalEmulation.enableInaccurateTextureCoordinates = ui->enableInaccurateTextureCoordinatesCheckBox->isChecked() ? 1 : 0;
config.generalEmulation.enableHWLighting = ui->enableHWLightingCheckBox->isChecked() ? 1 : 0;
config.generalEmulation.enableCoverage = ui->enableCoverageCheckBox->isChecked() ? 1 : 0;
config.generalEmulation.enableShadersStorage = ui->enableShadersStorageCheckBox->isChecked() ? 1 : 0;

View File

@ -48,6 +48,7 @@ void _loadSettings(QSettings & settings)
config.generalEmulation.enableHiresNoiseDithering = settings.value("enableHiresNoiseDithering", config.generalEmulation.enableHiresNoiseDithering).toInt();
config.generalEmulation.rdramImageDitheringMode = settings.value("rdramImageDitheringMode", config.generalEmulation.rdramImageDitheringMode).toInt();
config.generalEmulation.enableLOD = settings.value("enableLOD", config.generalEmulation.enableLOD).toInt();
config.generalEmulation.enableInaccurateTextureCoordinates = settings.value("enableFastInaccurateShaders", config.generalEmulation.enableInaccurateTextureCoordinates).toInt();
config.generalEmulation.enableHWLighting = settings.value("enableHWLighting", config.generalEmulation.enableHWLighting).toInt();
config.generalEmulation.enableCoverage = settings.value("enableCoverage", config.generalEmulation.enableCoverage).toInt();
config.generalEmulation.enableShadersStorage = settings.value("enableShadersStorage", config.generalEmulation.enableShadersStorage).toInt();
@ -193,6 +194,7 @@ void _writeSettingsToFile(const QString & filename)
settings.setValue("enableHiresNoiseDithering", config.generalEmulation.enableHiresNoiseDithering);
settings.setValue("rdramImageDitheringMode", config.generalEmulation.rdramImageDitheringMode);
settings.setValue("enableLOD", config.generalEmulation.enableLOD);
settings.setValue("enableFastInaccurateShaders", config.generalEmulation.enableInaccurateTextureCoordinates);
settings.setValue("enableHWLighting", config.generalEmulation.enableHWLighting);
settings.setValue("enableCoverage", config.generalEmulation.enableCoverage);
settings.setValue("enableShadersStorage", config.generalEmulation.enableShadersStorage);
@ -359,8 +361,8 @@ void resetSettings(const QString & _strIniFolder)
static
u32 Adler32(u32 crc, const void *buffer, u32 count)
{
register u32 s1 = crc & 0xFFFF;
register u32 s2 = (crc >> 16) & 0xFFFF;
u32 s1 = crc & 0xFFFF;
u32 s2 = (crc >> 16) & 0xFFFF;
int k;
const u8 *Buffer = (const u8*)buffer;
@ -465,6 +467,7 @@ void saveCustomRomSettings(const QString & _strIniFolder, const char * _strRomNa
WriteCustomSetting(generalEmulation, enableHiresNoiseDithering);
WriteCustomSetting(generalEmulation, rdramImageDitheringMode);
WriteCustomSetting(generalEmulation, enableLOD);
WriteCustomSetting(generalEmulation, enableInaccurateTextureCoordinates);
WriteCustomSetting(generalEmulation, enableHWLighting);
WriteCustomSetting(generalEmulation, enableCoverage);
WriteCustomSetting(generalEmulation, enableShadersStorage);
@ -540,11 +543,11 @@ void saveCustomRomSettings(const QString & _strIniFolder, const char * _strRomNa
settings.beginGroup("hotkeys");
for (u32 idx = 0; idx < Config::HotKey::hkTotal; ++idx) {
if (origConfig.hotkeys.keys[idx] != config.hotkeys.keys[idx] ||
if (origConfig.hotkeys.keys[idx] != config.hotkeys.keys[idx] ||
origConfig.hotkeys.keys[idx] != settings.value(Config::hotkeyIniName(idx), config.hotkeys.keys[idx]).toInt()) {
settings.setValue(Config::hotkeyIniName(idx), config.hotkeys.keys[idx]);
}
if (origConfig.hotkeys.enabledKeys[idx] != config.hotkeys.enabledKeys[idx] ||
if (origConfig.hotkeys.enabledKeys[idx] != config.hotkeys.enabledKeys[idx] ||
origConfig.hotkeys.enabledKeys[idx] != settings.value(Config::enabledHotkeyIniName(idx), config.hotkeys.enabledKeys[idx]).toInt()) {
settings.setValue(Config::enabledHotkeyIniName(idx), config.hotkeys.enabledKeys[idx]);
}

View File

@ -1098,6 +1098,16 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="enableInaccurateTextureCoordinatesCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Enable inaccurate texture coordinates. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;Enables inaccurate texture coordinate calculations. This can improve performance and texture pack compatibity at the cost of accuracy.&lt;/p&gt;&lt;p&gt;[Recommended: Unchecked, unless performance is hurt or for texture pack compatibility]&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Enable inaccurate texture coordinates</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="enableShadersStorageCheckBox">
<property name="toolTip">

View File

@ -21,6 +21,7 @@ namespace graphics {
vecOptions.push_back(config.frameBufferEmulation.N64DepthCompare == Config::dcCompatible ? 1 : 0);
vecOptions.push_back(config.generalEmulation.enableLegacyBlending);
vecOptions.push_back(config.generalEmulation.enableFragmentDepthWrite);
vecOptions.push_back(config.generalEmulation.enableInaccurateTextureCoordinates);
u32 optionsSet = 0;
for (u32 i = 0; i < vecOptions.size(); ++i)
optionsSet |= vecOptions[i] << i;

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,8 @@
#include <memory>
#include <Combiner.h>
#include <Graphics/OpenGLContext/opengl_GLInfo.h>
#include "glsl_CombinerProgramUniformFactory.h"
#include "glsl_ShaderPart.h"
namespace graphics {
class CombinerProgram;
@ -12,98 +14,121 @@ namespace opengl {
}
namespace glsl {
class ShaderPart;
class CombinerInputs;
class CombinerProgramUniformFactory;
}
class CombinerProgramBuilder
{
public:
CombinerProgramBuilder(const opengl::GLInfo & _glinfo, opengl::CachedUseProgram * _useProgram);
~CombinerProgramBuilder();
namespace glsl {
graphics::CombinerProgram * buildCombinerProgram(Combiner & _color, Combiner & _alpha, const CombinerKey & _key);
class TextureConvert {
public:
void setMode(u32 _mode) {
m_mode = _mode;
}
const ShaderPart * getVertexShaderHeader() const;
bool getBilerp1() const {
return (m_mode & 1) != 0;
}
const ShaderPart * getFragmentShaderHeader() const;
bool getBilerp0() const {
return (m_mode & 2) != 0;
}
const ShaderPart * getFragmentShaderEnd() const;
bool useYUVCoversion() const {
return (m_mode & 3) != 3;
}
bool isObsolete() const;
bool useTextureFiltering() const {
return (m_mode & 3) != 0;
}
private:
CombinerInputs compileCombiner(const CombinerKey & _key, Combiner & _color, Combiner & _alpha, std::string & _strShader);
private:
u32 m_mode;
};
typedef std::unique_ptr<ShaderPart> ShaderPartPtr;
ShaderPartPtr m_blender1;
ShaderPartPtr m_blender2;
ShaderPartPtr m_blenderAlpha;
ShaderPartPtr m_legacyBlender;
ShaderPartPtr m_clamp;
ShaderPartPtr m_signExtendColorC;
ShaderPartPtr m_signExtendAlphaC;
ShaderPartPtr m_signExtendColorABD;
ShaderPartPtr m_signExtendAlphaABD;
ShaderPartPtr m_alphaTest;
ShaderPartPtr m_callDither;
class CombinerProgramBuilder
{
public:
using ShaderPartPtr = std::unique_ptr<ShaderPart>;
ShaderPartPtr m_vertexHeader;
ShaderPartPtr m_vertexEnd;
ShaderPartPtr m_vertexRect;
ShaderPartPtr m_vertexTexturedRect;
ShaderPartPtr m_vertexTriangle;
ShaderPartPtr m_vertexTexturedTriangle;
CombinerProgramBuilder(const opengl::GLInfo & _glinfo, opengl::CachedUseProgram * _useProgram,
std::unique_ptr<CombinerProgramUniformFactory> _uniformFactory);
virtual ~CombinerProgramBuilder();
ShaderPartPtr m_fragmentHeader;
ShaderPartPtr m_fragmentGlobalVariablesTex;
ShaderPartPtr m_fragmentGlobalVariablesNotex;
ShaderPartPtr m_fragmentHeaderNoise;
ShaderPartPtr m_fragmentHeaderWriteDepth;
ShaderPartPtr m_fragmentHeaderCalcLight;
ShaderPartPtr m_fragmentHeaderMipMap;
ShaderPartPtr m_fragmentHeaderTextureEngine;
ShaderPartPtr m_fragmentHeaderReadMSTex;
ShaderPartPtr m_fragmentHeaderDither;
ShaderPartPtr m_fragmentHeaderDepthCompare;
ShaderPartPtr m_fragmentHeaderReadTex;
ShaderPartPtr m_fragmentHeaderReadTexCopyMode;
ShaderPartPtr m_fragmentMain;
ShaderPartPtr m_fragmentMain2Cycle;
ShaderPartPtr m_fragmentBlendMux;
ShaderPartPtr m_fragmentReadTex0;
ShaderPartPtr m_fragmentReadTex1;
ShaderPartPtr m_fragmentCorrectTexCoords;
ShaderPartPtr m_fragmentTextureEngineTex0;
ShaderPartPtr m_fragmentTextureEngineTex1;
ShaderPartPtr m_fragmentReadTexCopyMode;
ShaderPartPtr m_fragmentReadTexMipmap;
ShaderPartPtr m_fragmentCallN64Depth;
ShaderPartPtr m_fragmentRenderTarget;
ShaderPartPtr m_shaderFragmentMainEnd;
graphics::CombinerProgram * buildCombinerProgram(Combiner & _color, Combiner & _alpha, const CombinerKey & _key);
ShaderPartPtr m_shaderNoise;
ShaderPartPtr m_shaderDither;
ShaderPartPtr m_shaderWriteDepth;
ShaderPartPtr m_shaderMipmap;
ShaderPartPtr m_shaderCalcLight;
ShaderPartPtr m_shaderReadtex;
ShaderPartPtr m_shaderReadtexCopyMode;
ShaderPartPtr m_shaderN64DepthCompare;
ShaderPartPtr m_shaderN64DepthRender;
ShaderPartPtr m_shaderTextureEngine;
ShaderPartPtr m_shaderCoverage;
virtual const ShaderPart * getVertexShaderHeader() const = 0;
std::unique_ptr<CombinerProgramUniformFactory> m_uniformFactory;
virtual const ShaderPart * getFragmentShaderHeader() const = 0;
GLuint m_vertexShaderRect;
GLuint m_vertexShaderTriangle;
GLuint m_vertexShaderTexturedRect;
GLuint m_vertexShaderTexturedTriangle;
opengl::CachedUseProgram * m_useProgram;
u32 m_combinerOptionsBits;
bool m_useCoverage = false;
};
virtual const ShaderPart * getFragmentShaderEnd() const = 0;
virtual bool isObsolete() const = 0;
static u32 s_cycleType;
static TextureConvert s_textureConvert;
private:
CombinerInputs compileCombiner(const CombinerKey & _key, Combiner & _color, Combiner & _alpha, std::string & _strShader);
virtual void _writeSignExtendAlphaC(std::stringstream& ssShader) const = 0;
virtual void _writeSignExtendAlphaABD(std::stringstream& ssShader) const = 0;
virtual void _writeAlphaTest(std::stringstream& ssShader) const = 0;
virtual void _writeSignExtendColorC(std::stringstream& ssShader) const = 0;
virtual void _writeSignExtendColorABD(std::stringstream& ssShader) const = 0;
virtual void _writeClamp(std::stringstream& ssShader) const = 0;
virtual void _writeCallDither(std::stringstream& ssShader) const = 0;
virtual void _writeBlender1(std::stringstream& ssShader) const = 0;
virtual void _writeBlender2(std::stringstream& ssShader) const = 0;
virtual void _writeBlenderAlpha(std::stringstream& ssShader) const = 0;
virtual void _writeLegacyBlender(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentHeader(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentGlobalVariablesTex(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentHeaderDither(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentHeaderNoise(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentHeaderWriteDepth(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentHeaderDepthCompare(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentHeaderReadMSTex(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentHeaderClampWrapMirrorEngine(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentHeaderMipMap(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentHeaderReadTex(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentHeaderReadTexCopyMode(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentGlobalVariablesNotex(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentHeaderCalcLight(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentMain2Cycle(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentMain(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentBlendMux(std::stringstream& ssShader) const = 0;
virtual void _writeShaderCoverage(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentCorrectTexCoords(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentClampWrapMirrorEngineTex0(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentClampWrapMirrorEngineTex1(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentReadTexMipmap(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentReadTex0(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentReadTex1(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentReadTexCopyMode(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentCallN64Depth(std::stringstream& ssShader) const = 0;
virtual void _writeFragmentRenderTarget(std::stringstream& ssShader) const = 0;
virtual void _writeShaderFragmentMainEnd(std::stringstream& ssShader) const = 0;
virtual void _writeShaderCalcLight(std::stringstream& ssShader) const = 0;
virtual void _writeShaderClampWrapMirrorEngine(std::stringstream& ssShader) const = 0;
virtual void _writeShaderMipmap(std::stringstream& ssShader) const = 0;
virtual void _writeShaderReadtex(std::stringstream& ssShader) const = 0;
virtual void _writeShaderReadtexCopyMode(std::stringstream& ssShader) const = 0;
virtual void _writeShaderNoise(std::stringstream& ssShader) const = 0;
virtual void _writeShaderDither(std::stringstream& ssShader) const = 0;
virtual void _writeShaderWriteDepth(std::stringstream& ssShader) const = 0;
virtual void _writeShaderN64DepthCompare(std::stringstream& ssShader) const = 0;
virtual void _writeShaderN64DepthRender(std::stringstream& ssShader) const = 0;
virtual GLuint _getVertexShaderRect() const = 0;
virtual GLuint _getVertexShaderTriangle() const = 0;
virtual GLuint _getVertexShaderTexturedRect() const = 0;
virtual GLuint _getVertexShaderTexturedTriangle() const = 0;
std::unique_ptr<CombinerProgramUniformFactory> m_uniformFactory;
opengl::CachedUseProgram * m_useProgram;
bool m_useCoverage = false;
};
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
#pragma once
#include <Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilderCommon.h>
namespace glsl {
class CombinerProgramUniformFactory;
class CombinerProgramBuilderAccurate : public glsl::CombinerProgramBuilderCommon
{
public:
CombinerProgramBuilderAccurate(const opengl::GLInfo & _glinfo, opengl::CachedUseProgram * _useProgram);
private:
void _writeFragmentGlobalVariablesTex(std::stringstream& ssShader) const override;
void _writeFragmentHeaderReadMSTex(std::stringstream& ssShader) const override;
void _writeFragmentHeaderReadTex(std::stringstream& ssShader) const override;
void _writeFragmentHeaderReadTexCopyMode(std::stringstream& ssShader) const override;
void _writeFragmentHeaderClampWrapMirrorEngine(std::stringstream& ssShader) const override;
void _writeFragmentClampWrapMirrorEngineTex0(std::stringstream& ssShader) const override;
void _writeFragmentClampWrapMirrorEngineTex1(std::stringstream& ssShader) const override;
void _writeFragmentReadTex0(std::stringstream& ssShader) const override;
void _writeFragmentReadTex1(std::stringstream& ssShader) const override;
void _writeFragmentReadTexCopyMode(std::stringstream& ssShader) const override;
void _writeShaderClampWrapMirrorEngine(std::stringstream& ssShader) const override;
void _writeShaderMipmap(std::stringstream& ssShader) const override;
void _writeShaderReadtex(std::stringstream& ssShader) const override;
void _writeShaderReadtexCopyMode(std::stringstream& ssShader) const override;
ShaderPartPtr m_fragmentGlobalVariablesTex;
ShaderPartPtr m_fragmentHeaderTextureEngine;
ShaderPartPtr m_fragmentHeaderReadMSTex;
ShaderPartPtr m_fragmentHeaderReadTex;
ShaderPartPtr m_fragmentHeaderReadTexCopyMode;
ShaderPartPtr m_fragmentReadTexCopyMode;
ShaderPartPtr m_fragmentReadTex0;
ShaderPartPtr m_fragmentReadTex1;
ShaderPartPtr m_shaderMipmap;
ShaderPartPtr m_shaderReadtex;
ShaderPartPtr m_shaderReadtexCopyMode;
ShaderPartPtr m_shaderTextureEngine;
ShaderPartPtr m_fragmentTextureEngineTex0;
ShaderPartPtr m_fragmentTextureEngineTex1;
};
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
#pragma once
#include <Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.h>
namespace glsl {
class CombinerProgramUniformFactory;
class CombinerProgramBuilderCommon : public glsl::CombinerProgramBuilder
{
public:
CombinerProgramBuilderCommon(const opengl::GLInfo & _glinfo, opengl::CachedUseProgram * _useProgram,
std::unique_ptr<CombinerProgramUniformFactory> _uniformFactory,
std::unique_ptr<ShaderPart> _vertexTexturedTriangle);
~CombinerProgramBuilderCommon();
const ShaderPart * getVertexShaderHeader() const override;
const ShaderPart * getFragmentShaderHeader() const override;
const ShaderPart * getFragmentShaderEnd() const override;
bool isObsolete() const override;
private:
GLuint _getVertexShaderRect() const override;
GLuint _getVertexShaderTriangle() const override;
GLuint _getVertexShaderTexturedRect() const override;
GLuint _getVertexShaderTexturedTriangle() const override;
void _writeSignExtendAlphaC(std::stringstream& ssShader) const override;
void _writeSignExtendAlphaABD(std::stringstream& ssShader) const override;
void _writeAlphaTest(std::stringstream& ssShader) const override;
void _writeSignExtendColorC(std::stringstream& ssShader) const override;
void _writeSignExtendColorABD(std::stringstream& ssShader) const override;
void _writeClamp(std::stringstream& ssShader) const override;
void _writeCallDither(std::stringstream& ssShader) const override;
void _writeBlender1(std::stringstream& ssShader) const override;
void _writeBlender2(std::stringstream& ssShader) const override;
void _writeBlenderAlpha(std::stringstream& ssShader) const override;
void _writeLegacyBlender(std::stringstream& ssShader) const override;
void _writeFragmentHeader(std::stringstream& ssShader) const override;
void _writeFragmentHeaderDither(std::stringstream& ssShader) const override;
void _writeFragmentHeaderNoise(std::stringstream& ssShader) const override;
void _writeFragmentHeaderWriteDepth(std::stringstream& ssShader) const override;
void _writeFragmentHeaderDepthCompare(std::stringstream& ssShader) const override;
void _writeFragmentHeaderMipMap(std::stringstream& ssShader) const override;
void _writeFragmentGlobalVariablesNotex(std::stringstream& ssShader) const override;
void _writeFragmentHeaderCalcLight(std::stringstream& ssShader) const override;
void _writeFragmentMain2Cycle(std::stringstream& ssShader) const override;
void _writeFragmentMain(std::stringstream& ssShader) const override;
void _writeFragmentBlendMux(std::stringstream& ssShader) const override;
void _writeShaderCoverage(std::stringstream& ssShader) const override;
void _writeFragmentCorrectTexCoords(std::stringstream& ssShader) const override;
void _writeFragmentReadTexMipmap(std::stringstream& ssShader) const override;
void _writeFragmentCallN64Depth(std::stringstream& ssShader) const override;
void _writeFragmentRenderTarget(std::stringstream& ssShader) const override;
void _writeShaderFragmentMainEnd(std::stringstream& ssShader) const override;
void _writeShaderCalcLight(std::stringstream& ssShader) const override;
void _writeShaderNoise(std::stringstream& ssShader) const override;
void _writeShaderDither(std::stringstream& ssShader) const override;
void _writeShaderWriteDepth(std::stringstream& ssShader) const override;
void _writeShaderN64DepthCompare(std::stringstream& ssShader) const override;
void _writeShaderN64DepthRender(std::stringstream& ssShader) const override;
ShaderPartPtr m_blender1;
ShaderPartPtr m_blender2;
ShaderPartPtr m_blenderAlpha;
ShaderPartPtr m_legacyBlender;
ShaderPartPtr m_clamp;
ShaderPartPtr m_signExtendColorC;
ShaderPartPtr m_signExtendAlphaC;
ShaderPartPtr m_signExtendColorABD;
ShaderPartPtr m_signExtendAlphaABD;
ShaderPartPtr m_alphaTest;
ShaderPartPtr m_callDither;
ShaderPartPtr m_vertexHeader;
ShaderPartPtr m_vertexEnd;
ShaderPartPtr m_vertexRect;
ShaderPartPtr m_vertexTexturedRect;
ShaderPartPtr m_vertexTriangle;
ShaderPartPtr m_fragmentHeader;
ShaderPartPtr m_fragmentGlobalVariablesNotex;
ShaderPartPtr m_fragmentHeaderNoise;
ShaderPartPtr m_fragmentHeaderWriteDepth;
ShaderPartPtr m_fragmentHeaderCalcLight;
ShaderPartPtr m_fragmentHeaderMipMap;
ShaderPartPtr m_fragmentHeaderDither;
ShaderPartPtr m_fragmentHeaderDepthCompare;
ShaderPartPtr m_fragmentMain;
ShaderPartPtr m_fragmentMain2Cycle;
ShaderPartPtr m_fragmentBlendMux;
ShaderPartPtr m_fragmentCorrectTexCoords;
ShaderPartPtr m_fragmentReadTexMipmap;
ShaderPartPtr m_fragmentCallN64Depth;
ShaderPartPtr m_fragmentRenderTarget;
ShaderPartPtr m_shaderFragmentMainEnd;
ShaderPartPtr m_shaderNoise;
ShaderPartPtr m_shaderDither;
ShaderPartPtr m_shaderWriteDepth;
ShaderPartPtr m_shaderCalcLight;
ShaderPartPtr m_shaderN64DepthCompare;
ShaderPartPtr m_shaderN64DepthRender;
ShaderPartPtr m_shaderCoverage;
u32 m_combinerOptionsBits;
GLuint m_vertexShaderRect;
GLuint m_vertexShaderTriangle;
GLuint m_vertexShaderTexturedRect;
GLuint m_vertexShaderTexturedTriangle;
};
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,47 @@
#pragma once
#include <Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilderCommon.h>
namespace glsl {
class CombinerProgramUniformFactory;
class CombinerProgramBuilderFast : public glsl::CombinerProgramBuilderCommon
{
public:
CombinerProgramBuilderFast(const opengl::GLInfo & _glinfo, opengl::CachedUseProgram * _useProgram);
private:
void _writeFragmentGlobalVariablesTex(std::stringstream& ssShader) const override;
void _writeFragmentHeaderReadMSTex(std::stringstream& ssShader) const override;
void _writeFragmentHeaderReadTex(std::stringstream& ssShader) const override;
void _writeFragmentHeaderReadTexCopyMode(std::stringstream& ssShader) const override;
void _writeFragmentHeaderClampWrapMirrorEngine(std::stringstream& ssShader) const override;
void _writeFragmentClampWrapMirrorEngineTex0(std::stringstream& ssShader) const override;
void _writeFragmentClampWrapMirrorEngineTex1(std::stringstream& ssShader) const override;
void _writeFragmentReadTex0(std::stringstream& ssShader) const override;
void _writeFragmentReadTex1(std::stringstream& ssShader) const override;
void _writeFragmentReadTexCopyMode(std::stringstream& ssShader) const override;
void _writeShaderClampWrapMirrorEngine(std::stringstream& ssShader) const override;
void _writeShaderMipmap(std::stringstream& ssShader) const override;
void _writeShaderReadtex(std::stringstream& ssShader) const override;
void _writeShaderReadtexCopyMode(std::stringstream& ssShader) const override;
ShaderPartPtr m_fragmentGlobalVariablesTex;
ShaderPartPtr m_fragmentHeaderClampWrapMirror;
ShaderPartPtr m_fragmentHeaderReadMSTex;
ShaderPartPtr m_fragmentHeaderReadTex;
ShaderPartPtr m_fragmentHeaderReadTexCopyMode;
ShaderPartPtr m_fragmentReadTex0;
ShaderPartPtr m_fragmentReadTex1;
ShaderPartPtr m_fragmentClampWrapMirrorTex0;
ShaderPartPtr m_fragmentClampWrapMirrorTex1;
ShaderPartPtr m_fragmentReadTexCopyMode;
ShaderPartPtr m_shaderMipmap;
ShaderPartPtr m_shaderReadtex;
ShaderPartPtr m_shaderReadtexCopyMode;
ShaderPartPtr m_shaderClampWrapMirror;
};
}

View File

@ -4,18 +4,85 @@
namespace glsl {
class CombinerProgramUniformFactory
{
public:
CombinerProgramUniformFactory(const opengl::GLInfo & _glInfo);
class CombinerProgramUniformFactory {
public:
CombinerProgramUniformFactory(const opengl::GLInfo & _glInfo);
virtual ~CombinerProgramUniformFactory();
void buildUniforms(GLuint _program,
const CombinerInputs & _inputs,
const CombinerKey & _key,
UniformGroups & _uniforms);
void buildUniforms(GLuint _program,
const CombinerInputs &_inputs,
const CombinerKey &_key,
UniformGroups &_uniforms);
private:
const opengl::GLInfo & m_glInfo;
};
private:
virtual void _addNoiseTex(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addScreenSpaceTriangleInfo(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addRasterInfo(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addViewportInfo(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addDepthTex(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addDepthScale(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addTextures(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addMSAATextures(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addFrameBufferInfo(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addMipmap(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addMipmap2(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addTextureFetchMode(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addTexturePersp(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addTextureSize(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const = 0;
virtual void _addTextureParams(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const = 0;
virtual void _addClampWrapMirrorEngine(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const = 0;
virtual void _addFog(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addBlendMode1Cycle(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addBlendMode2Cycle(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addBlendCvg(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addDitherMode(GLuint _program, UniformGroups &_uniforms, bool _usesNoise) const = 0;
virtual void _addScreenScale(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addAlphaTestInfo(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addZLutTexture(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addDepthInfo(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addDepthSource(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addRenderTarget(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addClampMode(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addPolygonOffset(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addScreenCoordsScale(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addColors(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addRectColor(GLuint _program, UniformGroups &_uniforms) const = 0;
virtual void _addLights(GLuint _program, UniformGroups &_uniforms) const = 0;
protected:
const opengl::GLInfo & m_glInfo;
};
}

View File

@ -0,0 +1,397 @@
#include <algorithm>
#include <cmath>
#include <Config.h>
#include "glsl_CombinerProgramUniformFactoryAccurate.h"
#include <Graphics/Parameters.h>
#include <Graphics/Context.h>
#include <Textures.h>
#include <NoiseTexture.h>
#include <FrameBuffer.h>
#include <DisplayWindow.h>
#include <Debugger.h>
#include <GBI.h>
#include <RSP.h>
#include <gSP.h>
#include <gDP.h>
#include <VI.h>
#ifdef min
#undef min
#endif
namespace glsl {
class URasterInfo : public UniformGroup {
public:
URasterInfo(GLuint _program) {
LocateUniform(uVertexOffset);
LocateUniform(uTexCoordOffset[0]);
LocateUniform(uTexCoordOffset[1]);
LocateUniform(uUseTexCoordBounds);
LocateUniform(uTexCoordBounds0);
LocateUniform(uTexCoordBounds1);
}
void update(bool _force) override {
const bool isNativeRes = config.frameBufferEmulation.nativeResFactor == 1 && config.video.multisampling == 0;
const bool isTexRect = dwnd().getDrawer().getDrawingState() == DrawingState::TexRect;
const bool useTexCoordBounds = isTexRect && !isNativeRes && config.graphics2D.enableTexCoordBounds;
/* At rasterization stage, the N64 places samples on the top left of the fragment while OpenGL */
/* places them in the fragment center. As a result, a normal approach results in shifted texture */
/* coordinates. In native resolution, this difference can be negated by shifting vertices by 0.5. */
/* In higher resolutions, there are more samples than the game intends, so shifting is not very */
/* effective. Still, an heuristic is applied to render texture rectangles as correctly as possible */
/* in higher resolutions too. See issue #2324 for details. */
const float vertexOffset = isNativeRes ? 0.5f : 0.0f;
float texCoordOffset[2][2] = { 0.0f, 0.0f };
if (isTexRect && !isNativeRes) {
float scale[2] = { 0.0f, 0.0f };
if (config.graphics2D.enableNativeResTexrects != 0 && gDP.otherMode.textureFilter != G_TF_POINT) {
scale[0] = scale[1] = 1.0f;
} else {
scale[0] = scale[1] = static_cast<float>(config.frameBufferEmulation.nativeResFactor);
}
for (int t = 0; t < 2; t++) {
const CachedTexture* _pTexture = textureCache().current[t];
if (_pTexture != nullptr) {
if (config.frameBufferEmulation.nativeResFactor != 0) {
if (gDP.otherMode.textureFilter != G_TF_POINT && gDP.otherMode.cycleType != G_CYC_COPY) {
texCoordOffset[t][0] = -0.5f * gDP.lastTexRectInfo.dsdx;
texCoordOffset[t][1] = -0.5f * gDP.lastTexRectInfo.dtdy;
} else {
texCoordOffset[t][0] = (gDP.lastTexRectInfo.dsdx >= 0.0f ? -0.5f / scale[0] : -1.0f + 0.5f / scale[0]) * gDP.lastTexRectInfo.dsdx;
texCoordOffset[t][1] = (gDP.lastTexRectInfo.dtdy >= 0.0f ? -0.5f / scale[1] : -1.0f + 0.5f / scale[1]) * gDP.lastTexRectInfo.dtdy;
}
} else {
texCoordOffset[t][0] = (gDP.lastTexRectInfo.dsdx >= 0.0f ? 0.0f : -1.0f) * gDP.lastTexRectInfo.dsdx;
texCoordOffset[t][1] = (gDP.lastTexRectInfo.dtdy >= 0.0f ? 0.0f : -1.0f) * gDP.lastTexRectInfo.dtdy;
if (gDP.otherMode.textureFilter != G_TF_POINT && gDP.otherMode.cycleType != G_CYC_COPY) {
texCoordOffset[t][0] -= 0.5f;
texCoordOffset[t][1] -= 0.5f;
}
}
}
}
}
/* Hack for framebuffer textures. See #519 and #2112 */
if ((config.generalEmulation.hacks & hack_fbTextureOffset) != 0) {
for (int t = 0; t < 2; t++) {
const CachedTexture* _pTexture = textureCache().current[t];
if (_pTexture != nullptr) {
if (gDP.otherMode.textureFilter != G_TF_POINT && _pTexture->frameBufferTexture != CachedTexture::fbNone) {
texCoordOffset[t][0] -= 1.0f;
texCoordOffset[t][1] -= 1.0f;
}
}
}
}
float tcbounds[2][4] = {};
if (useTexCoordBounds) {
f32 uls, lrs, ult, lrt, S, T;
for (int t = 0; t < 2; t++) {
const CachedTexture * _pTexture = textureCache().current[t];
if (_pTexture != nullptr) {
S = _FIXED2FLOAT(gDP.lastTexRectInfo.s, 5);
T = _FIXED2FLOAT(gDP.lastTexRectInfo.t, 5);
uls = S + (ceilf(gDP.lastTexRectInfo.ulx) - gDP.lastTexRectInfo.ulx) * gDP.lastTexRectInfo.dsdx;
lrs = S + (ceilf(gDP.lastTexRectInfo.lrx) - gDP.lastTexRectInfo.ulx - 1.0f) * gDP.lastTexRectInfo.dsdx;
ult = T + (ceilf(gDP.lastTexRectInfo.uly) - gDP.lastTexRectInfo.uly) * gDP.lastTexRectInfo.dtdy;
lrt = T + (ceilf(gDP.lastTexRectInfo.lry) - gDP.lastTexRectInfo.uly - 1.0f) * gDP.lastTexRectInfo.dtdy;
tcbounds[t][0] = fmin(uls, lrs);
tcbounds[t][1] = fmin(ult, lrt);
tcbounds[t][2] = fmax(uls, lrs);
tcbounds[t][3] = fmax(ult, lrt);
}
}
}
uVertexOffset.set(vertexOffset, vertexOffset, _force);
uTexCoordOffset[0].set(texCoordOffset[0][0], texCoordOffset[0][1], _force);
uTexCoordOffset[1].set(texCoordOffset[1][0], texCoordOffset[1][1], _force);
uUseTexCoordBounds.set(useTexCoordBounds ? 1 : 0, _force);
uTexCoordBounds0.set(tcbounds[0], _force);
uTexCoordBounds1.set(tcbounds[1], _force);
}
private:
fv2Uniform uVertexOffset;
fv2Uniform uTexCoordOffset[2];
iUniform uUseTexCoordBounds;
fv4Uniform uTexCoordBounds0;
fv4Uniform uTexCoordBounds1;
};
class UMipmap : public UniformGroup
{
public:
UMipmap(GLuint _program) {
LocateUniform(uMinLod);
LocateUniform(uMaxTile);
LocateUniform(uEnableLod);
LocateUniform(uTextureDetail);
}
void update(bool _force) override
{
uMinLod.set(gDP.primColor.m, _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);
const int uCalcLOD = (gDP.otherMode.textureLOD == G_TL_LOD) ? 1 : 0;
uEnableLod.set(uCalcLOD, _force);
uTextureDetail.set(gDP.otherMode.textureDetail, _force);
}
private:
fUniform uMinLod;
iUniform uMaxTile;
iUniform uEnableLod;
iUniform uTextureDetail;
};
class UTextureSize : public UniformGroup
{
public:
UTextureSize(GLuint _program, bool _useT0, bool _useT1)
: m_useT0(_useT0)
, m_useT1(_useT1)
{
LocateUniform(uTextureSize[0]);
LocateUniform(uTextureSize[1]);
}
void update(bool _force) override
{
TextureCache & cache = textureCache();
if (m_useT0 && cache.current[0] != nullptr)
uTextureSize[0].set(static_cast<float>(cache.current[0]->width),
static_cast<float>(cache.current[0]->height), _force);
if (m_useT1 && cache.current[1] != nullptr) {
CachedTexture * pTexture = cache.current[1];
if (pTexture->max_level == 0)
uTextureSize[1].set(static_cast<float>(pTexture->width),
static_cast<float>(pTexture->height), _force);
else
uTextureSize[1].set(static_cast<float>(pTexture->mipmapAtlasWidth),
static_cast<float>(pTexture->mipmapAtlasHeight), _force);
}
}
private:
fv2Uniform uTextureSize[2];
bool m_useT0;
bool m_useT1;
};
class UTextureParams : public UniformGroup
{
public:
UTextureParams(GLuint _program, bool _useT0, bool _useT1)
{
m_useTile[0] = _useT0;
m_useTile[1] = _useT1;
LocateUniform(uTexScale);
LocateUniform(uCacheFrameBuffer);
}
void update(bool _force) override
{
int nFB[2] = { 0, 0 };
TextureCache & cache = textureCache();
for (u32 t = 0; t < 2; ++t) {
if (!m_useTile[t])
continue;
CachedTexture *_pTexture = cache.current[t];
if (_pTexture != nullptr) {
nFB[t] = _pTexture->frameBufferTexture;
}
}
uCacheFrameBuffer.set(nFB[0], nFB[1], _force);
uTexScale.set(gSP.texture.scales, gSP.texture.scalet, _force);
}
private:
bool m_useTile[2];
fv2Uniform uTexScale;
iv2Uniform uCacheFrameBuffer;
};
class UTextureEngine : public UniformGroup
{
public:
UTextureEngine(GLuint _program, bool _useT0, bool _useT1)
{
m_useTile[0] = _useT0;
m_useTile[1] = _useT1;
LocateUniform(uTexWrap[0]);
LocateUniform(uTexWrap[1]);
LocateUniform(uTexClamp[0]);
LocateUniform(uTexClamp[1]);
LocateUniform(uTexWrapEn[0]);
LocateUniform(uTexWrapEn[1]);
LocateUniform(uTexClampEn[0]);
LocateUniform(uTexClampEn[1]);
LocateUniform(uTexMirrorEn[0]);
LocateUniform(uTexMirrorEn[1]);
LocateUniform(uTexSize[0]);
LocateUniform(uTexSize[1]);
LocateUniform(uShiftScale[0]);
LocateUniform(uShiftScale[1]);
LocateUniform(uTexOffset[0]);
LocateUniform(uTexOffset[1]);
LocateUniform(uHDRatio[0]);
LocateUniform(uHDRatio[1]);
LocateUniform(uCacheOffset[0]);
LocateUniform(uCacheOffset[1]);
LocateUniform(uBilinearOffset);
}
void update(bool _force) override
{
std::array<f32, 2> aTexWrap[2] = { { 1024.0f, 1024.0f }, { 1024.0f, 1024.0f } };
std::array<f32, 2> aTexClamp[2] = { { 1024.0f, 1024.0f }, { 1024.0f, 1024.0f } };
std::array<f32, 2> aTexWrapEn[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> aTexMirrorEn[2] = { { 0.0f, 0.0f }, { 0.0f,0.0f }};
std::array<f32, 2> aTexSize[2] = { { 1024.0f, 1024.0f }, { 1024.0f, 1024.0f } };
std::array<f32, 2> aShiftScale[2] = { { 1.0f, 1.0f }, { 1.0f,1.0f } };
std::array<f32, 2> aTexOffset[2] = { { 0.0f, 0.0f }, { 0.0f, 0.0f } };
std::array<f32, 2> aHDRatio[2] = { { 1.0f, 1.0f }, { 1.0f, 1.0f } };
std::array<f32, 2> aCacheOffset[2] = { { 0.0f, 0.0f }, { 0.0f, 0.0f } };
const float bilinearOffset = gDP.otherMode.textureFilter != G_TF_POINT && gDP.otherMode.cycleType != G_CYC_COPY ? 0.5f : 0.0f;
uBilinearOffset.set(bilinearOffset, bilinearOffset, _force);
TextureCache & cache = textureCache();
for (u32 t = 0; t < 2; ++t) {
if (!m_useTile[t])
continue;
const gDPTile * pTile = gSP.textureTile[t];
CachedTexture * pTexture = cache.current[t];
if (pTile == nullptr || pTexture == nullptr)
continue;
aTexSize[t][0] = pTexture->width * pTexture->hdRatioS;
aTexSize[t][1] = pTexture->height * pTexture->hdRatioT;
aShiftScale[t][0] = pTile->shifts > 10 ? static_cast<f32>(1 << (16 - pTile->shifts)) : 1.0f / static_cast<f32>(1 << pTile->shifts);
aShiftScale[t][1] = pTile->shiftt > 10 ? static_cast<f32>(1 << (16 - pTile->shiftt)) : 1.0f / static_cast<f32>(1 << pTile->shiftt);
if (pTile->textureMode != TEXTUREMODE_BGIMAGE && pTile->textureMode != TEXTUREMODE_FRAMEBUFFER_BG) {
aTexOffset[t][0] = pTile->fuls;
aTexOffset[t][1] = pTile->fult;
}
aHDRatio[t][0] = pTexture->hdRatioS;
aHDRatio[t][1] = pTexture->hdRatioT;
aCacheOffset[t][0] = pTexture->offsetS * pTexture->hdRatioS;
aCacheOffset[t][1] = pTexture->offsetT * pTexture->hdRatioT;
/* Not sure if special treatment of framebuffer textures is correct */
if (pTexture->frameBufferTexture != CachedTexture::fbNone)
{
aTexClamp[t][0] = f32(pTexture->width) * pTexture->hdRatioS - 1.0f;
aTexClamp[t][1] = f32(pTexture->height) * pTexture->hdRatioT - 1.0f;
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;
} else if (pTile->textureMode != TEXTUREMODE_NORMAL || g_debugger.isDebugMode()) {
aTexWrapEn[t][0] = 0.0;
aTexWrapEn[t][1] = 0.0;
aTexClampEn[t][0] = 0.0;
aTexClampEn[t][1] = 0.0;
aTexMirrorEn[t][0] = 0.0;
aTexMirrorEn[t][1] = 0.0;
} else {
aTexWrap[t][0] = f32(1 << pTile->masks) * pTexture->hdRatioS;
aTexWrap[t][1] = f32(1 << pTile->maskt) * pTexture->hdRatioT;
aTexClamp[t][0] = f32(pTile->lrs - pTile->uls + 1) * pTexture->hdRatioS - 1.0f;
aTexClamp[t][1] = f32(pTile->lrt - pTile->ult + 1) * pTexture->hdRatioT - 1.0f;
aTexWrapEn[t][0] = f32(pTile->masks == 0 ? 0 : 1);
aTexWrapEn[t][1] = f32(pTile->maskt == 0 ? 0 : 1);
aTexClampEn[t][0] = f32(gDP.otherMode.cycleType == G_CYC_COPY ? 0 : (pTile->masks == 0 ? 1 : pTile->clamps));
aTexClampEn[t][1] = f32(gDP.otherMode.cycleType == G_CYC_COPY ? 0 : (pTile->maskt == 0 ? 1 : pTile->clampt));
aTexMirrorEn[t][0] = f32(pTile->masks == 0 ? 0 : pTile->mirrors);
aTexMirrorEn[t][1] = f32(pTile->maskt == 0 ? 0 : pTile->mirrort);
}
uTexWrap[t].set(aTexWrap[t][0], aTexWrap[t][1], _force);
uTexClamp[t].set(aTexClamp[t][0], aTexClamp[t][1], _force);
uTexWrapEn[t].set(aTexWrapEn[t][0], aTexWrapEn[t][1], _force);
uTexWrapEn[t].set(aTexWrapEn[t][0], aTexWrapEn[t][1], _force);
uTexClampEn[t].set(aTexClampEn[t][0], aTexClampEn[t][1], _force);
uTexMirrorEn[t].set(aTexMirrorEn[t][0], aTexMirrorEn[t][1], _force);
uTexSize[t].set(aTexSize[t][0], aTexSize[t][1], _force);
uShiftScale[t].set(aShiftScale[t][0], aShiftScale[t][1], _force);
uTexOffset[t].set(aTexOffset[t][0], aTexOffset[t][1], _force);
uHDRatio[t].set(aHDRatio[t][0], aHDRatio[t][1], _force);
uCacheOffset[t].set(aCacheOffset[t][0], aCacheOffset[t][1], _force);
}
}
private:
bool m_useTile[2];
fv2Uniform uTexWrap[2];
fv2Uniform uTexClamp[2];
fv2Uniform uTexWrapEn[2];
fv2Uniform uTexClampEn[2];
fv2Uniform uTexMirrorEn[2];
fv2Uniform uTexSize[2];
fv2Uniform uShiftScale[2];
fv2Uniform uTexOffset[2];
fv2Uniform uHDRatio[2];
fv2Uniform uCacheOffset[2];
fv2Uniform uBilinearOffset;
};
/*---------------CombinerProgramUniformFactoryCommon-------------*/
void CombinerProgramUniformFactoryAccurate::_addRasterInfo(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new URasterInfo(_program));
}
void CombinerProgramUniformFactoryAccurate::_addMipmap(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UMipmap(_program));
}
void CombinerProgramUniformFactoryAccurate::_addMipmap2(GLuint _program, UniformGroups &_uniforms) const
{
}
void CombinerProgramUniformFactoryAccurate::_addTextureSize(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const
{
_uniforms.emplace_back(new UTextureSize(_program, _usesTile0, _usesTile1));
}
void CombinerProgramUniformFactoryAccurate::_addTextureParams(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const
{
_uniforms.emplace_back(new UTextureParams(_program, _usesTile0, _usesTile1));
}
void CombinerProgramUniformFactoryAccurate::_addClampWrapMirrorEngine(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const
{
_uniforms.emplace_back(new UTextureEngine(_program, _usesTile0, _usesTile1));
}
CombinerProgramUniformFactoryAccurate::CombinerProgramUniformFactoryAccurate(const opengl::GLInfo & _glInfo)
: CombinerProgramUniformFactoryCommon(_glInfo)
, m_glInfo(_glInfo)
{
}
}

View File

@ -0,0 +1,28 @@
#pragma once
#include <Graphics/OpenGLContext/opengl_GLInfo.h>
#include "glsl_CombinerProgramImpl.h"
#include "glsl_CombinerProgramUniformFactoryCommon.h"
namespace glsl {
class CombinerProgramUniformFactoryAccurate : public CombinerProgramUniformFactoryCommon {
public:
CombinerProgramUniformFactoryAccurate(const opengl::GLInfo & _glInfo);
private:
virtual void _addRasterInfo(GLuint _program, UniformGroups &_uniforms) const override;
virtual void _addMipmap(GLuint _program, UniformGroups &_uniforms) const override;
virtual void _addMipmap2(GLuint _program, UniformGroups &_uniforms) const override;
virtual void _addTextureSize(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const override;
virtual void _addTextureParams(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const override;
virtual void _addClampWrapMirrorEngine(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const override;
const opengl::GLInfo &m_glInfo;
};
}

View File

@ -0,0 +1,914 @@
#include <Config.h>
#include "glsl_CombinerProgramUniformFactoryCommon.h"
#include <Graphics/Parameters.h>
#include <Graphics/Context.h>
#include <Textures.h>
#include <NoiseTexture.h>
#include <FrameBuffer.h>
#include <DisplayWindow.h>
#include <Debugger.h>
#include <GBI.h>
#include <RSP.h>
#include <gSP.h>
#include <gDP.h>
#include <VI.h>
namespace glsl {
/*---------------UniformGroup-------------*/
class UNoiseTex : public UniformGroup
{
public:
UNoiseTex(GLuint _program) {
LocateUniform(uTexNoise);
}
void update(bool _force) override
{
uTexNoise.set(int(graphics::textureIndices::NoiseTex), _force);
}
private:
iUniform uTexNoise;
};
class UDepthTex : public UniformGroup
{
public:
UDepthTex(GLuint _program) {
LocateUniform(uDepthTex);
}
void update(bool _force) override
{
uDepthTex.set(int(graphics::textureIndices::DepthTex), _force);
}
private:
iUniform uDepthTex;
};
class UZLutTexture : public UniformGroup
{
public:
UZLutTexture(GLuint _program) {
LocateUniform(uZlutImage);
}
void update(bool _force) override
{
uZlutImage.set(int(graphics::textureIndices::ZLUTTex), _force);
}
private:
iUniform uZlutImage;
};
class UTextures : public UniformGroup
{
public:
UTextures(GLuint _program) {
LocateUniform(uTex0);
LocateUniform(uTex1);
}
void update(bool _force) override
{
uTex0.set(0, _force);
uTex1.set(1, _force);
}
private:
iUniform uTex0;
iUniform uTex1;
};
class UMSAATextures : public UniformGroup
{
public:
UMSAATextures(GLuint _program) {
LocateUniform(uMSTex0);
LocateUniform(uMSTex1);
LocateUniform(uMSAASamples);
}
void update(bool _force) override
{
uMSTex0.set(int(graphics::textureIndices::MSTex[0]), _force);
uMSTex1.set(int(graphics::textureIndices::MSTex[1]), _force);
uMSAASamples.set(config.video.multisampling, _force);
}
private:
iUniform uMSTex0;
iUniform uMSTex1;
iUniform uMSAASamples;
};
class UScreenSpaceTriangleInfo : public UniformGroup
{
public:
UScreenSpaceTriangleInfo(GLuint _program) {
LocateUniform(uScreenSpaceTriangle);
}
void update(bool _force) override
{
uScreenSpaceTriangle.set(
(dwnd().getDrawer().getDrawingState() == DrawingState::ScreenSpaceTriangle) ? 1 : 0, _force);
}
private:
iUniform uScreenSpaceTriangle;
};
class UFrameBufferInfo : public UniformGroup
{
public:
UFrameBufferInfo(GLuint _program) {
LocateUniform(uFbMonochrome);
LocateUniform(uFbFixedAlpha);
LocateUniform(uMSTexEnabled);
}
void update(bool _force) override
{
int nFbMonochromeMode0 = 0, nFbMonochromeMode1 = 0;
int nFbFixedAlpha0 = 0, nFbFixedAlpha1 = 0;
int nMSTex0Enabled = 0, nMSTex1Enabled = 0;
TextureCache & cache = textureCache();
if (cache.current[0] != nullptr && cache.current[0]->frameBufferTexture != CachedTexture::fbNone) {
if (cache.current[0]->size == G_IM_SIZ_8b) {
nFbMonochromeMode0 = 1;
if (gDP.otherMode.imageRead == 0)
nFbFixedAlpha0 = 1;
} else if (gSP.textureTile[0]->size == G_IM_SIZ_16b && gSP.textureTile[0]->format == G_IM_FMT_IA) {
nFbMonochromeMode0 = 2;
} else if ((config.generalEmulation.hacks & hack_ZeldaMonochrome) != 0 &&
cache.current[0]->size == G_IM_SIZ_16b &&
gSP.textureTile[0]->size == G_IM_SIZ_8b &&
gSP.textureTile[0]->format == G_IM_FMT_CI) {
// Zelda monochrome effect
nFbMonochromeMode0 = 3;
nFbMonochromeMode1 = 3;
}
nMSTex0Enabled = cache.current[0]->frameBufferTexture == CachedTexture::fbMultiSample ? 1 : 0;
}
if (cache.current[1] != nullptr && cache.current[1]->frameBufferTexture != CachedTexture::fbNone) {
if (cache.current[1]->size == G_IM_SIZ_8b) {
nFbMonochromeMode1 = 1;
if (gDP.otherMode.imageRead == 0)
nFbFixedAlpha1 = 1;
}
else if (gSP.textureTile[1]->size == G_IM_SIZ_16b && gSP.textureTile[1]->format == G_IM_FMT_IA)
nFbMonochromeMode1 = 2;
nMSTex1Enabled = cache.current[1]->frameBufferTexture == CachedTexture::fbMultiSample ? 1 : 0;
}
uFbMonochrome.set(nFbMonochromeMode0, nFbMonochromeMode1, _force);
uFbFixedAlpha.set(nFbFixedAlpha0, nFbFixedAlpha1, _force);
uMSTexEnabled.set(nMSTex0Enabled, nMSTex1Enabled, _force);
gDP.changed &= ~CHANGED_FB_TEXTURE;
}
private:
iv2Uniform uFbMonochrome;
iv2Uniform uFbFixedAlpha;
iv2Uniform uMSTexEnabled;
};
class UFog : public UniformGroup
{
public:
UFog(GLuint _program) {
LocateUniform(uFogUsage);
LocateUniform(uFogScale);
}
void update(bool _force) override
{
if (RSP.LLE) {
uFogUsage.set(0, _force);
return;
}
int nFogUsage = ((gSP.geometryMode & G_FOG) != 0) ? 1 : 0;
if (GBI.getMicrocodeType() == F3DAM) {
const s16 fogMode = ((gSP.geometryMode >> 13) & 9) + 0xFFF8;
if (fogMode == 0)
nFogUsage = 1;
else if (fogMode > 0)
nFogUsage = 2;
}
uFogUsage.set(nFogUsage, _force);
uFogScale.set(gSP.fog.multiplierf, gSP.fog.offsetf, _force);
}
private:
iUniform uFogUsage;
fv2Uniform uFogScale;
};
class UBlendMode1Cycle : public UniformGroup
{
public:
UBlendMode1Cycle(GLuint _program) {
LocateUniform(uBlendMux1);
LocateUniform(uForceBlendCycle1);
}
void update(bool _force) override
{
uBlendMux1.set(gDP.otherMode.c1_m1a,
gDP.otherMode.c1_m1b,
gDP.otherMode.c1_m2a,
gDP.otherMode.c1_m2b,
_force);
const int forceBlend1 = (int)gDP.otherMode.forceBlender;
uForceBlendCycle1.set(forceBlend1, _force);
}
private:
i4Uniform uBlendMux1;
iUniform uForceBlendCycle1;
};
class UBlendMode2Cycle : public UniformGroup
{
public:
UBlendMode2Cycle(GLuint _program) {
LocateUniform(uBlendMux1);
LocateUniform(uBlendMux2);
LocateUniform(uForceBlendCycle1);
LocateUniform(uForceBlendCycle2);
}
void update(bool _force) override
{
uBlendMux1.set(gDP.otherMode.c1_m1a,
gDP.otherMode.c1_m1b,
gDP.otherMode.c1_m2a,
gDP.otherMode.c1_m2b,
_force);
uBlendMux2.set(gDP.otherMode.c2_m1a,
gDP.otherMode.c2_m1b,
gDP.otherMode.c2_m2a,
gDP.otherMode.c2_m2b,
_force);
const int forceBlend1 = 1;
uForceBlendCycle1.set(forceBlend1, _force);
const int forceBlend2 = gDP.otherMode.forceBlender;
uForceBlendCycle2.set(forceBlend2, _force);
if (!(graphics::Context::DualSourceBlending || graphics::Context::FramebufferFetchColor) || dwnd().getDrawer().isTexrectDrawerMode()) {
// Modes, which shader blender can't emulate
const u32 mode = _SHIFTR(gDP.otherMode.l, 16, 16);
switch (mode) {
case 0x0040:
// Mia Hamm Soccer
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_in + clr_in * (1-a)
case 0x0050:
// A Bug's Life
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_in + clr_mem * (1-a)
uForceBlendCycle1.set(0, _force);
uForceBlendCycle2.set(0, _force);
break;
case 0x0150:
// Tony Hawk
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_fog + clr_mem * (1-a_fog)
if ((config.generalEmulation.hacks & hack_TonyHawk) != 0) {
uForceBlendCycle1.set(0, _force);
uForceBlendCycle2.set(0, _force);
}
break;
}
}
}
private:
i4Uniform uBlendMux1;
i4Uniform uBlendMux2;
iUniform uForceBlendCycle1;
iUniform uForceBlendCycle2;
};
class UBlendCvg : public UniformGroup
{
public:
UBlendCvg(GLuint _program) {
LocateUniform(uCvgDest);
LocateUniform(uBlendAlphaMode);
}
void update(bool _force) override
{
uCvgDest.set(gDP.otherMode.cvgDest, _force);
if (dwnd().getDrawer().isTexrectDrawerMode())
uBlendAlphaMode.set(2, _force); // No alpha blend in texrect drawing mode
else
uBlendAlphaMode.set(gDP.otherMode.forceBlender, _force);
}
private:
iUniform uCvgDest;
iUniform uBlendAlphaMode;
};
class UDitherMode : public UniformGroup
{
public:
UDitherMode(GLuint _program, bool _usesNoise)
: m_usesNoise(_usesNoise)
{
LocateUniform(uAlphaCompareMode);
LocateUniform(uAlphaDitherMode);
LocateUniform(uColorDitherMode);
}
void update(bool _force) override
{
if (gDP.otherMode.cycleType < G_CYC_COPY) {
uAlphaCompareMode.set(gDP.otherMode.alphaCompare, _force);
uAlphaDitherMode.set(gDP.otherMode.alphaDither, _force);
uColorDitherMode.set(gDP.otherMode.colorDither, _force);
}
else {
uAlphaCompareMode.set(0, _force);
uAlphaDitherMode.set(0, _force);
uColorDitherMode.set(0, _force);
}
bool updateNoiseTex = m_usesNoise;
updateNoiseTex |= (gDP.otherMode.cycleType < G_CYC_COPY) && (gDP.otherMode.colorDither == G_CD_NOISE || gDP.otherMode.alphaDither == G_AD_NOISE || gDP.otherMode.alphaCompare == G_AC_DITHER);
if (updateNoiseTex)
g_noiseTexture.update();
}
private:
iUniform uAlphaCompareMode;
iUniform uAlphaDitherMode;
iUniform uColorDitherMode;
bool m_usesNoise;
};
class UScreenScale : public UniformGroup
{
public:
UScreenScale(GLuint _program) {
LocateUniform(uScreenScale);
}
void update(bool _force) override
{
if (dwnd().getDrawer().isTexrectDrawerMode()) {
uScreenScale.set(1.0f, 1.0f, _force);
return;
}
FrameBuffer * pBuffer = frameBufferList().getCurrent();
if (pBuffer == nullptr)
uScreenScale.set(dwnd().getScaleX(), dwnd().getScaleY(), _force);
else
uScreenScale.set(pBuffer->m_scale, pBuffer->m_scale, _force);
}
private:
fv2Uniform uScreenScale;
};
class UTexturePersp : public UniformGroup
{
public:
UTexturePersp(GLuint _program) {
LocateUniform(uTexturePersp);
}
void update(bool _force) override
{
const u32 texturePersp = (RSP.LLE || GBI.isTexturePersp()) ? gDP.otherMode.texturePersp : 1U;
uTexturePersp.set(texturePersp, _force);
}
private:
iUniform uTexturePersp;
};
class UTextureFetchMode : public UniformGroup
{
public:
UTextureFetchMode(GLuint _program) {
LocateUniform(uTextureFilterMode);
LocateUniform(uTextureFormat);
LocateUniform(uTextureConvert);
LocateUniform(uConvertParams);
}
void update(bool _force) override
{
int textureFilter = gDP.otherMode.textureFilter;
uTextureFilterMode.set(textureFilter, _force);
uTextureFormat.set(gSP.textureTile[0]->format, gSP.textureTile[1]->format, _force);
uTextureConvert.set(gDP.otherMode.convert_one, _force);
if (gDP.otherMode.bi_lerp0 == 0 || gDP.otherMode.bi_lerp1 == 0)
uConvertParams.set(gDP.convert.k0, gDP.convert.k1, gDP.convert.k2, gDP.convert.k3, _force);
}
private:
iUniform uTextureFilterMode;
iv2Uniform uTextureFormat;
iUniform uTextureConvert;
i4Uniform uConvertParams;
};
class UAlphaTestInfo : public UniformGroup
{
public:
UAlphaTestInfo(GLuint _program) {
LocateUniform(uEnableAlphaTest);
LocateUniform(uAlphaCvgSel);
LocateUniform(uCvgXAlpha);
LocateUniform(uAlphaTestValue);
}
void update(bool _force) override
{
if (gDP.otherMode.cycleType == G_CYC_FILL) {
uEnableAlphaTest.set(0, _force);
uAlphaCvgSel.set(0, _force);
} else if (gDP.otherMode.cycleType == G_CYC_COPY) {
uAlphaCvgSel.set(0, _force);
if (gDP.otherMode.alphaCompare & G_AC_THRESHOLD) {
uEnableAlphaTest.set(1, _force);
uAlphaTestValue.set(0.5f, _force);
} else {
uEnableAlphaTest.set(0, _force);
}
} else if ((gDP.otherMode.alphaCompare & G_AC_THRESHOLD) != 0) {
uEnableAlphaTest.set(1, _force);
uAlphaTestValue.set(gDP.blendColor.a, _force);
uAlphaCvgSel.set(gDP.otherMode.alphaCvgSel, _force);
} else {
uEnableAlphaTest.set(0, _force);
uAlphaCvgSel.set(gDP.otherMode.alphaCvgSel, _force);
}
uCvgXAlpha.set(gDP.otherMode.cvgXAlpha, _force);
}
private:
iUniform uEnableAlphaTest;
iUniform uAlphaCvgSel;
iUniform uCvgXAlpha;
fUniform uAlphaTestValue;
};
class UViewportInfo : public UniformGroup
{
public:
UViewportInfo(GLuint _program) {
LocateUniform(uVTrans);
LocateUniform(uVScale);
LocateUniform(uAdjustTrans);
LocateUniform(uAdjustScale);
}
void update(bool _force) override
{
const bool isOrthographicProjection = gSP.matrix.projection[3][2] == -1.f;
float adjustTrans[2] = { 0.0f, 0.0f };
float adjustScale[2] = { 1.0f, 1.0f };
if (dwnd().isAdjustScreen() && (gDP.colorImage.width > VI.width * 98 / 100)) {
if (isOrthographicProjection) {
adjustScale[1] = 1.0f / dwnd().getAdjustScale();
adjustTrans[1] = static_cast<f32>(gDP.colorImage.width) * 3.0f / 4.0f * (1.0f - adjustScale[1]) / 2.0f;
} else {
adjustScale[0] = dwnd().getAdjustScale();
adjustTrans[0] = static_cast<f32>(gDP.colorImage.width) * (1.0f - adjustScale[0]) / 2.0f;
}
}
uVTrans.set(gSP.viewport.vtrans[0], gSP.viewport.vtrans[1], _force);
uVScale.set(gSP.viewport.vscale[0], -gSP.viewport.vscale[1], _force);
uAdjustTrans.set(adjustTrans[0], adjustTrans[1], _force);
uAdjustScale.set(adjustScale[0], adjustScale[1], _force);
}
private:
fv2Uniform uVTrans;
fv2Uniform uVScale;
fv2Uniform uAdjustTrans;
fv2Uniform uAdjustScale;
};
class UDepthScale : public UniformGroup
{
public:
UDepthScale(GLuint _program) {
LocateUniform(uDepthScale);
}
void update(bool _force) override
{
if (RSP.LLE)
uDepthScale.set(0.5f, 0.5f, _force);
else
uDepthScale.set(gSP.viewport.vscale[2], gSP.viewport.vtrans[2], _force);
}
private:
fv2Uniform uDepthScale;
};
class UDepthInfo : public UniformGroup
{
public:
UDepthInfo(GLuint _program) {
LocateUniform(uEnableDepth);
LocateUniform(uEnableDepthCompare);
LocateUniform(uEnableDepthUpdate);
LocateUniform(uDepthMode);
LocateUniform(uDepthSource);
LocateUniform(uPrimDepth);
LocateUniform(uDeltaZ);
}
void update(bool _force) override
{
FrameBuffer * pBuffer = frameBufferList().getCurrent();
if (pBuffer == nullptr || pBuffer->m_pDepthBuffer == nullptr)
return;
const bool nDepthEnabled = ((gSP.geometryMode & G_ZBUFFER) || gDP.otherMode.depthSource == G_ZS_PRIM) &&
gDP.otherMode.cycleType <= G_CYC_2CYCLE;
uEnableDepth.set(nDepthEnabled ? 1 : 0, _force);
if (nDepthEnabled) {
uEnableDepthCompare.set(gDP.otherMode.depthCompare, _force);
uEnableDepthUpdate.set(gDP.otherMode.depthUpdate, _force);
} else {
uEnableDepthCompare.set(0, _force);
uEnableDepthUpdate.set(0, _force);
}
uDepthMode.set(gDP.otherMode.depthMode, _force);
uDepthSource.set(gDP.otherMode.depthSource, _force);
if (gDP.otherMode.depthSource == G_ZS_PRIM) {
uDeltaZ.set(gDP.primDepth.deltaZ, _force);
uPrimDepth.set(gDP.primDepth.z, _force);
}
}
private:
iUniform uEnableDepth;
iUniform uEnableDepthCompare;
iUniform uEnableDepthUpdate;
iUniform uDepthMode;
iUniform uDepthSource;
fUniform uPrimDepth;
fUniform uDeltaZ;
};
class UDepthSource : public UniformGroup
{
public:
UDepthSource(GLuint _program) {
LocateUniform(uDepthSource);
LocateUniform(uPrimDepth);
}
void update(bool _force) override
{
uDepthSource.set(gDP.otherMode.depthSource, _force);
if (gDP.otherMode.depthSource == G_ZS_PRIM)
uPrimDepth.set(gDP.primDepth.z, _force);
}
private:
iUniform uDepthSource;
fUniform uPrimDepth;
};
class URenderTarget : public UniformGroup
{
public:
URenderTarget(GLuint _program) {
LocateUniform(uRenderTarget);
}
void update(bool _force) override
{
int renderTarget = 0;
if (isCurrentColorImageDepthImage()) {
renderTarget = isDepthCompareEnabled() ? 2 : 1;
}
uRenderTarget.set(renderTarget, _force);
}
private:
iUniform uRenderTarget;
};
class UClampMode : public UniformGroup
{
public:
UClampMode(GLuint _program) {
LocateUniform(uClampMode);
}
void update(bool _force) override
{
int clampMode = -1;
switch (gfxContext.getClampMode())
{
case graphics::ClampMode::ClippingEnabled:
clampMode = 0;
break;
case graphics::ClampMode::NoNearPlaneClipping:
clampMode = 1;
break;
case graphics::ClampMode::NoClipping:
clampMode = 2;
break;
}
uClampMode.set(clampMode, _force);
}
private:
iUniform uClampMode;
};
class UPolygonOffset : public UniformGroup
{
public:
UPolygonOffset(GLuint _program) {
LocateUniform(uPolygonOffset);
}
void update(bool _force) override
{
f32 offset = gfxContext.isEnabled(graphics::enable::POLYGON_OFFSET_FILL) ? 0.003f : 0.0f;
uPolygonOffset.set(offset, _force);
}
private:
fUniform uPolygonOffset;
};
class UScreenCoordsScale : public UniformGroup
{
public:
UScreenCoordsScale(GLuint _program) {
LocateUniform(uScreenCoordsScale);
}
void update(bool _force) override
{
f32 scaleX, scaleY;
calcCoordsScales(frameBufferList().getCurrent(), scaleX, scaleY);
uScreenCoordsScale.set(2.0f*scaleX, -2.0f*scaleY, _force);
}
private:
fv2Uniform uScreenCoordsScale;
};
class UColors : public UniformGroup
{
public:
UColors(GLuint _program) {
LocateUniform(uFogColor);
LocateUniform(uCenterColor);
LocateUniform(uScaleColor);
LocateUniform(uBlendColor);
LocateUniform(uEnvColor);
LocateUniform(uPrimColor);
LocateUniform(uPrimLod);
LocateUniform(uK4);
LocateUniform(uK5);
}
void update(bool _force) override
{
uFogColor.set(&gDP.fogColor.r, _force);
uCenterColor.set(&gDP.key.center.r, _force);
uScaleColor.set(&gDP.key.scale.r, _force);
uBlendColor.set(&gDP.blendColor.r, _force);
uEnvColor.set(&gDP.envColor.r, _force);
uPrimColor.set(&gDP.primColor.r, _force);
uPrimLod.set(gDP.primColor.l, _force);
uK4.set(_FIXED2FLOATCOLOR(gDP.convert.k4, 8 ), _force);
uK5.set(_FIXED2FLOATCOLOR(gDP.convert.k5, 8 ), _force);
}
private:
fv4Uniform uFogColor;
fv4Uniform uCenterColor;
fv4Uniform uScaleColor;
fv4Uniform uBlendColor;
fv4Uniform uEnvColor;
fv4Uniform uPrimColor;
fUniform uPrimLod;
fUniform uK4;
fUniform uK5;
};
class URectColor : public UniformGroup
{
public:
URectColor(GLuint _program) {
LocateUniform(uRectColor);
}
void update(bool _force) override
{
uRectColor.set(&gDP.rectColor.r, _force);
}
private:
fv4Uniform uRectColor;
};
class ULights : public UniformGroup
{
public:
ULights(GLuint _program)
{
char buf[32];
for (s32 i = 0; i < 8; ++i) {
sprintf(buf, "uLightDirection[%d]", i);
uLightDirection[i].loc = glGetUniformLocation(_program, buf);
sprintf(buf, "uLightColor[%d]", i);
uLightColor[i].loc = glGetUniformLocation(_program, buf);
}
}
void update(bool _force) override
{
for (u32 i = 0; i <= gSP.numLights; ++i) {
uLightDirection[i].set(gSP.lights.xyz[i], _force);
uLightColor[i].set(gSP.lights.rgb[i], _force);
}
}
private:
fv3Uniform uLightDirection[8];
fv3Uniform uLightColor[8];
};
/*---------------CombinerProgramUniformFactoryCommon-------------*/
void CombinerProgramUniformFactoryCommon::_addNoiseTex(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UNoiseTex(_program));
}
void CombinerProgramUniformFactoryCommon::_addScreenSpaceTriangleInfo(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UScreenSpaceTriangleInfo(_program));
}
void CombinerProgramUniformFactoryCommon::_addRasterInfo(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UScreenSpaceTriangleInfo(_program));
}
void CombinerProgramUniformFactoryCommon::_addViewportInfo(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UViewportInfo(_program));
}
void CombinerProgramUniformFactoryCommon::_addDepthTex(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UDepthTex(_program));
}
void CombinerProgramUniformFactoryCommon::_addDepthScale(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UDepthScale(_program));
}
void CombinerProgramUniformFactoryCommon::_addTextures(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UTextures(_program));
}
void CombinerProgramUniformFactoryCommon::_addMSAATextures(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UMSAATextures(_program));
}
void CombinerProgramUniformFactoryCommon::_addFrameBufferInfo(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UFrameBufferInfo(_program));
}
void CombinerProgramUniformFactoryCommon::_addTextureFetchMode(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UTextureFetchMode(_program));
}
void CombinerProgramUniformFactoryCommon::_addTexturePersp(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UTexturePersp(_program));
}
void CombinerProgramUniformFactoryCommon::_addFog(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UFog(_program));
}
void CombinerProgramUniformFactoryCommon::_addBlendMode1Cycle(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UBlendMode1Cycle(_program));
}
void CombinerProgramUniformFactoryCommon::_addBlendMode2Cycle(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UBlendMode2Cycle(_program));
}
void CombinerProgramUniformFactoryCommon::_addBlendCvg(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UBlendCvg(_program));
}
void CombinerProgramUniformFactoryCommon::_addDitherMode(GLuint _program, UniformGroups &_uniforms, bool _usesNoise) const
{
_uniforms.emplace_back(new UDitherMode(_program, _usesNoise));
}
void CombinerProgramUniformFactoryCommon::_addScreenScale(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UScreenScale(_program));
}
void CombinerProgramUniformFactoryCommon::_addAlphaTestInfo(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UAlphaTestInfo(_program));
}
void CombinerProgramUniformFactoryCommon::_addZLutTexture(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UZLutTexture(_program));
}
void CombinerProgramUniformFactoryCommon::_addDepthInfo(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UDepthInfo(_program));
}
void CombinerProgramUniformFactoryCommon::_addDepthSource(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UDepthSource(_program));
}
void CombinerProgramUniformFactoryCommon::_addRenderTarget(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new URenderTarget(_program));
}
void CombinerProgramUniformFactoryCommon::_addClampMode(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UClampMode(_program));
}
void CombinerProgramUniformFactoryCommon::_addPolygonOffset(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UPolygonOffset(_program));
}
void CombinerProgramUniformFactoryCommon::_addScreenCoordsScale(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UScreenCoordsScale(_program));
}
void CombinerProgramUniformFactoryCommon::_addColors(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UColors(_program));
}
void CombinerProgramUniformFactoryCommon::_addRectColor(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new URectColor(_program));
}
void CombinerProgramUniformFactoryCommon::_addLights(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new ULights(_program));
}
CombinerProgramUniformFactoryCommon::CombinerProgramUniformFactoryCommon(const opengl::GLInfo & _glInfo)
: CombinerProgramUniformFactory(_glInfo)
{
}
}

View File

@ -0,0 +1,161 @@
#pragma once
#include "glsl_CombinerProgramUniformFactory.h"
namespace glsl {
/*---------------Uniform-------------*/
struct iUniform {
GLint loc = -1;
int val = -999;
void set(int _val, bool _force) {
if (loc >= 0 && (_force || val != _val)) {
val = _val;
glUniform1i(loc, _val);
}
}
};
struct fUniform {
GLint loc = -1;
float val = -9999.9f;
void set(float _val, bool _force) {
if (loc >= 0 && (_force || val != _val)) {
val = _val;
glUniform1f(loc, _val);
}
}
};
struct fv2Uniform {
GLint loc = -1;
float val1 = -9999.9f, val2 = -9999.9f;
void set(float _val1, float _val2, bool _force) {
if (loc >= 0 && (_force || val1 != _val1 || val2 != _val2)) {
val1 = _val1;
val2 = _val2;
glUniform2f(loc, _val1, _val2);
}
}
};
struct fv3Uniform {
GLint loc = -1;
float val[3];
void set(float * _pVal, bool _force) {
const size_t szData = sizeof(float)* 3;
if (loc >= 0 && (_force || memcmp(val, _pVal, szData) != 0)) {
memcpy(val, _pVal, szData);
glUniform3fv(loc, 1, _pVal);
}
}
};
struct fv4Uniform {
GLint loc = -1;
float val[4];
void set(float * _pVal, bool _force) {
const size_t szData = sizeof(float)* 4;
if (loc >= 0 && (_force || memcmp(val, _pVal, szData) != 0)) {
memcpy(val, _pVal, szData);
glUniform4fv(loc, 1, _pVal);
}
}
};
struct iv2Uniform {
GLint loc = -1;
int val1 = -999, val2 = -999;
void set(int _val1, int _val2, bool _force) {
if (loc >= 0 && (_force || val1 != _val1 || val2 != _val2)) {
val1 = _val1;
val2 = _val2;
glUniform2i(loc, _val1, _val2);
}
}
};
struct i4Uniform {
GLint loc = -1;
int val0 = -999, val1 = -999, val2 = -999, val3 = -999;
void set(int _val0, int _val1, int _val2, int _val3, bool _force) {
if (loc < 0)
return;
if (_force || _val0 != val0 || _val1 != val1 || _val2 != val2 || _val3 != val3) {
val0 = _val0;
val1 = _val1;
val2 = _val2;
val3 = _val3;
glUniform4i(loc, val0, val1, val2, val3);
}
}
};
#define LocateUniform(A) \
A.loc = glGetUniformLocation(_program, #A);
class CombinerProgramUniformFactoryCommon : public CombinerProgramUniformFactory
{
public:
CombinerProgramUniformFactoryCommon(const opengl::GLInfo & _glInfo);
private:
void _addNoiseTex(GLuint _program, UniformGroups &_uniforms) const override;
void _addScreenSpaceTriangleInfo(GLuint _program, UniformGroups &_uniforms) const override;
void _addRasterInfo(GLuint _program, UniformGroups &_uniforms) const override;
void _addViewportInfo(GLuint _program, UniformGroups &_uniforms) const override;
void _addDepthTex(GLuint _program, UniformGroups &_uniforms) const override;
void _addDepthScale(GLuint _program, UniformGroups &_uniforms) const override;
void _addTextures(GLuint _program, UniformGroups &_uniforms) const override;
void _addMSAATextures(GLuint _program, UniformGroups &_uniforms) const override;
void _addFrameBufferInfo(GLuint _program, UniformGroups &_uniforms) const override;
void _addTextureFetchMode(GLuint _program, UniformGroups &_uniforms) const override;
void _addTexturePersp(GLuint _program, UniformGroups &_uniforms) const override;
void _addFog(GLuint _program, UniformGroups &_uniforms) const override;
void _addBlendMode1Cycle(GLuint _program, UniformGroups &_uniforms) const override;
void _addBlendMode2Cycle(GLuint _program, UniformGroups &_uniforms) const override;
void _addBlendCvg(GLuint _program, UniformGroups &_uniforms) const override;
void _addDitherMode(GLuint _program, UniformGroups &_uniforms, bool _usesNoise) const override;
void _addScreenScale(GLuint _program, UniformGroups &_uniforms) const override;
void _addAlphaTestInfo(GLuint _program, UniformGroups &_uniforms) const override;
void _addZLutTexture(GLuint _program, UniformGroups &_uniforms) const override;
void _addDepthInfo(GLuint _program, UniformGroups &_uniforms) const override;
void _addDepthSource(GLuint _program, UniformGroups &_uniforms) const override;
void _addRenderTarget(GLuint _program, UniformGroups &_uniforms) const override;
void _addClampMode(GLuint _program, UniformGroups &_uniforms) const override;
void _addPolygonOffset(GLuint _program, UniformGroups &_uniforms) const override;
void _addScreenCoordsScale(GLuint _program, UniformGroups &_uniforms) const override;
void _addColors(GLuint _program, UniformGroups &_uniforms) const override;
void _addRectColor(GLuint _program, UniformGroups &_uniforms) const override;
void _addLights(GLuint _program, UniformGroups &_uniforms) const override;
};
}

View File

@ -0,0 +1,433 @@
#include <algorithm>
#include <cmath>
#include <Config.h>
#include "glsl_CombinerProgramUniformFactoryFast.h"
#include <Graphics/Parameters.h>
#include <Graphics/Context.h>
#include <Textures.h>
#include <NoiseTexture.h>
#include <FrameBuffer.h>
#include <DisplayWindow.h>
#include <Debugger.h>
#include <GBI.h>
#include <RSP.h>
#include <gSP.h>
#include <gDP.h>
#include <VI.h>
#ifdef min
#undef min
#endif
namespace glsl {
class URasterInfoFast : public UniformGroup {
public:
URasterInfoFast(GLuint _program) {
LocateUniform(uVertexOffset);
LocateUniform(uTexCoordOffset[0]);
LocateUniform(uTexCoordOffset[1]);
LocateUniform(uUseTexCoordBounds);
LocateUniform(uTexCoordBounds0);
LocateUniform(uTexCoordBounds1);
}
void update(bool _force) override {
const bool isNativeRes = config.frameBufferEmulation.nativeResFactor == 1 && config.video.multisampling == 0;
const bool isTexRect = dwnd().getDrawer().getDrawingState() == DrawingState::TexRect;
const bool useTexCoordBounds = isTexRect && !isNativeRes && config.graphics2D.enableTexCoordBounds;
/* At rasterization stage, the N64 places samples on the top left of the fragment while OpenGL */
/* places them in the fragment center. As a result, a normal approach results in shifted texture */
/* coordinates. In native resolution, this difference can be negated by shifting vertices by 0.5. */
/* In higher resolutions, there are more samples than the game intends, so shifting is not very */
/* effective. Still, an heuristic is applied to render texture rectangles as correctly as possible */
/* in higher resolutions too. See issue #2324 for details. */
const float vertexOffset = isNativeRes ? 0.5f : 0.0f;
float texCoordOffset[2][2] = { 0.0f, 0.0f };
if (isTexRect && !isNativeRes) {
float scale[2] = { 0.0f, 0.0f };
if (config.graphics2D.enableNativeResTexrects != 0 && gDP.otherMode.textureFilter != G_TF_POINT) {
scale[0] = scale[1] = 1.0f;
} else {
scale[0] = scale[1] = static_cast<float>(config.frameBufferEmulation.nativeResFactor);
}
for (int t = 0; t < 2; t++) {
const CachedTexture* _pTexture = textureCache().current[t];
if (_pTexture != nullptr) {
if (config.frameBufferEmulation.nativeResFactor != 0) {
texCoordOffset[t][0] = (gDP.lastTexRectInfo.dsdx >= 0.0f ? -0.5f / scale[0] : -1.0f + 0.5f / scale[0]) * gDP.lastTexRectInfo.dsdx * _pTexture->hdRatioS;
texCoordOffset[t][1] = (gDP.lastTexRectInfo.dtdy >= 0.0f ? -0.5f / scale[1] : -1.0f + 0.5f / scale[1]) * gDP.lastTexRectInfo.dtdy * _pTexture->hdRatioT;
} else {
texCoordOffset[t][0] = (gDP.lastTexRectInfo.dsdx >= 0.0f ? 0.0f : -1.0f) * gDP.lastTexRectInfo.dsdx * _pTexture->hdRatioS;
texCoordOffset[t][1] = (gDP.lastTexRectInfo.dtdy >= 0.0f ? 0.0f : -1.0f) * gDP.lastTexRectInfo.dtdy * _pTexture->hdRatioT;
if (gDP.otherMode.textureFilter != G_TF_POINT && gDP.otherMode.cycleType != G_CYC_COPY) {
texCoordOffset[t][0] -= 0.5f;
texCoordOffset[t][1] -= 0.5f;
}
}
}
}
}
/* Hack for framebuffer textures. See #519 and #2112 */
if ((config.generalEmulation.hacks & hack_fbTextureOffset) != 0) {
for (int t = 0; t < 2; t++) {
const CachedTexture* _pTexture = textureCache().current[t];
if (_pTexture != nullptr) {
if (gDP.otherMode.textureFilter != G_TF_POINT && _pTexture->frameBufferTexture != CachedTexture::fbNone) {
texCoordOffset[t][0] -= 1.0f;
texCoordOffset[t][1] -= 1.0f;
}
}
}
}
float tcbounds[2][4] = {};
if (useTexCoordBounds) {
f32 uls, lrs, ult, lrt, S, T, shiftScaleS, shiftScaleT;
s16 shiftedS, shiftedT;
u32 shifts, shiftt;
for (int t = 0; t < 2; t++) {
const CachedTexture * _pTexture = textureCache().current[t];
const gDPTile * _pTile = gSP.textureTile[t];
if (_pTexture != nullptr && _pTile != nullptr){
if (_pTile->shifts > 10) {
shifts = 16 - _pTile->shifts;
shiftedS = static_cast<s16>(gDP.lastTexRectInfo.s << shifts);
shiftScaleS = static_cast<f32>(1 << shifts);
} else {
shifts = _pTile->shifts;
shiftedS = static_cast<s16>(gDP.lastTexRectInfo.s >> shifts);
shiftScaleS = 1.0f / static_cast<f32>(1 << shifts);
}
if (_pTile->shiftt > 10) {
shiftt = 16 - _pTile->shiftt;
shiftedT = static_cast<s16>(gDP.lastTexRectInfo.t << shiftt);
shiftScaleT = static_cast<f32>(1 << shiftt);
} else {
shiftt = _pTile->shiftt;
shiftedT = static_cast<s16>(gDP.lastTexRectInfo.t >> shiftt);
shiftScaleT = 1.0f / static_cast<f32>(1 << shiftt);
}
S = _FIXED2FLOAT(shiftedS, 5);
T = _FIXED2FLOAT(shiftedT, 5);
uls = S + (ceilf(gDP.lastTexRectInfo.ulx) - gDP.lastTexRectInfo.ulx) * gDP.lastTexRectInfo.dsdx * shiftScaleS;
lrs = S + (ceilf(gDP.lastTexRectInfo.lrx) - gDP.lastTexRectInfo.ulx - 1.0f) * gDP.lastTexRectInfo.dsdx * shiftScaleS;
ult = T + (ceilf(gDP.lastTexRectInfo.uly) - gDP.lastTexRectInfo.uly) * gDP.lastTexRectInfo.dtdy * shiftScaleT;
lrt = T + (ceilf(gDP.lastTexRectInfo.lry) - gDP.lastTexRectInfo.uly - 1.0f) * gDP.lastTexRectInfo.dtdy * shiftScaleT;
tcbounds[t][0] = (fmin(uls, lrs) - _pTile->fuls) * _pTexture->hdRatioS;
tcbounds[t][1] = (fmin(ult, lrt) - _pTile->fult) * _pTexture->hdRatioT;
tcbounds[t][2] = (fmax(uls, lrs) - _pTile->fuls) * _pTexture->hdRatioS;
tcbounds[t][3] = (fmax(ult, lrt) - _pTile->fult) * _pTexture->hdRatioT;
if (_pTexture->frameBufferTexture != CachedTexture::fbNone) {
tcbounds[t][0] += _pTexture->offsetS * _pTexture->hdRatioS;
tcbounds[t][1] += _pTexture->offsetT * _pTexture->hdRatioT;
tcbounds[t][2] += _pTexture->offsetS * _pTexture->hdRatioS;
tcbounds[t][3] += _pTexture->offsetT * _pTexture->hdRatioT;
}
}
}
}
uVertexOffset.set(vertexOffset, vertexOffset, _force);
uTexCoordOffset[0].set(texCoordOffset[0][0], texCoordOffset[0][1], _force);
uTexCoordOffset[1].set(texCoordOffset[1][0], texCoordOffset[1][1], _force);
uUseTexCoordBounds.set(useTexCoordBounds ? 1 : 0, _force);
uTexCoordBounds0.set(tcbounds[0], _force);
uTexCoordBounds1.set(tcbounds[1], _force);
}
private:
fv2Uniform uVertexOffset;
fv2Uniform uTexCoordOffset[2];
iUniform uUseTexCoordBounds;
fv4Uniform uTexCoordBounds0;
fv4Uniform uTexCoordBounds1;
};
class UMipmap1 : public UniformGroup
{
public:
UMipmap1(GLuint _program) {
LocateUniform(uMinLod);
LocateUniform(uMaxTile);
}
void update(bool _force) override
{
uMinLod.set(gDP.primColor.m, _force);
uMaxTile.set(gSP.texture.level, _force);
}
private:
fUniform uMinLod;
iUniform uMaxTile;
};
class UMipmap2 : public UniformGroup
{
public:
UMipmap2(GLuint _program) {
LocateUniform(uEnableLod);
LocateUniform(uTextureDetail);
}
void update(bool _force) override
{
const int uCalcLOD = (gDP.otherMode.textureLOD == G_TL_LOD) ? 1 : 0;
uEnableLod.set(uCalcLOD, _force);
uTextureDetail.set(gDP.otherMode.textureDetail, _force);
}
private:
iUniform uEnableLod;
iUniform uTextureDetail;
};
class UTextureSizeFast : public UniformGroup
{
public:
UTextureSizeFast(GLuint _program, bool _useT0, bool _useT1)
: m_useT0(_useT0)
, m_useT1(_useT1)
{
LocateUniform(uTextureSize[0]);
LocateUniform(uTextureSize[1]);
}
void update(bool _force) override
{
TextureCache & cache = textureCache();
if (m_useT0 && cache.current[0] != NULL)
uTextureSize[0].set((float)cache.current[0]->width, (float)cache.current[0]->height, _force);
if (m_useT1 && cache.current[1] != NULL)
uTextureSize[1].set((float)cache.current[1]->width, (float)cache.current[1]->height, _force);
}
private:
fv2Uniform uTextureSize[2];
bool m_useT0;
bool m_useT1;
};
class UTextureParamsFast : public UniformGroup
{
public:
UTextureParamsFast(GLuint _program, bool _useT0, bool _useT1)
{
m_useTile[0] = _useT0;
m_useTile[1] = _useT1;
LocateUniform(uTexOffset[0]);
LocateUniform(uTexOffset[1]);
LocateUniform(uCacheShiftScale[0]);
LocateUniform(uCacheShiftScale[1]);
LocateUniform(uCacheScale[0]);
LocateUniform(uCacheScale[1]);
LocateUniform(uCacheOffset[0]);
LocateUniform(uCacheOffset[1]);
LocateUniform(uTexScale);
LocateUniform(uCacheFrameBuffer);
}
void update(bool _force) override
{
int nFB[2] = { 0, 0 };
TextureCache & cache = textureCache();
for (u32 t = 0; t < 2; ++t) {
if (!m_useTile[t])
continue;
gDPTile * pTile = gSP.textureTile[t];
if (pTile != nullptr) {
if (pTile->textureMode == TEXTUREMODE_BGIMAGE || pTile->textureMode == TEXTUREMODE_FRAMEBUFFER_BG)
uTexOffset[t].set(0.0f, 0.0f, _force);
else {
float fuls = pTile->fuls;
float fult = pTile->fult;
if (pTile->frameBufferAddress > 0) {
FrameBuffer * pBuffer = frameBufferList().getBuffer(pTile->frameBufferAddress);
if (pBuffer != nullptr) {
if (pTile->masks > 0 && pTile->clamps == 0)
fuls = float(pTile->uls % (1 << pTile->masks));
if (pTile->maskt > 0 && pTile->clampt == 0)
fult = float(pTile->ult % (1 << pTile->maskt));
} else {
pTile->frameBufferAddress = 0;
}
}
uTexOffset[t].set(fuls, fult, _force);
}
}
CachedTexture *_pTexture = cache.current[t];
if (_pTexture != nullptr) {
f32 shiftScaleS = 1.0f;
f32 shiftScaleT = 1.0f;
getTextureShiftScale(t, cache, shiftScaleS, shiftScaleT);
uCacheShiftScale[t].set(shiftScaleS, shiftScaleT, _force);
uCacheScale[t].set(_pTexture->scaleS, _pTexture->scaleT, _force);
uCacheOffset[t].set(_pTexture->offsetS, _pTexture->offsetT, _force);
nFB[t] = _pTexture->frameBufferTexture;
}
}
uCacheFrameBuffer.set(nFB[0], nFB[1], _force);
uTexScale.set(gSP.texture.scales, gSP.texture.scalet, _force);
}
private:
bool m_useTile[2];
fv2Uniform uTexOffset[2];
fv2Uniform uCacheShiftScale[2];
fv2Uniform uCacheScale[2];
fv2Uniform uCacheOffset[2];
fv2Uniform uTexScale;
iv2Uniform uCacheFrameBuffer;
};
class UClampWrapMirrorTex : public UniformGroup
{
public:
UClampWrapMirrorTex(GLuint _program, bool _useT0, bool _useT1)
{
m_useTile[0] = _useT0;
m_useTile[1] = _useT1;
LocateUniform(uTexClamp0);
LocateUniform(uTexClamp1);
LocateUniform(uTexWrap0);
LocateUniform(uTexWrap1);
LocateUniform(uTexMirror0);
LocateUniform(uTexMirror1);
LocateUniform(uTexScale0);
LocateUniform(uTexScale1);
}
void update(bool _force) override
{
std::array<f32, 4> aTexClamp[2] = { { -10000.0f, -10000.0f, 10000.0f, 10000.0f },
{ -10000.0f, -10000.0f, 10000.0f, 10000.0f } };
std::array<f32, 2> aTexWrap[2] = { { 10000.0f, 10000.0f }, { 10000.0f, 10000.0f } };
std::array<f32, 2> aTexMirror[2] = { { 0.0f, 0.0f}, { 0.0f, 0.0f } };
std::array<f32, 2> aTexScale[2] = { { 1.0f, 1.0f },{ 1.0f, 1.0f } };
TextureCache & cache = textureCache();
const bool replaceTex1ByTex0 = needReplaceTex1ByTex0();
for (u32 t = 0; t < 2; ++t) {
if (!m_useTile[t])
continue;
const u32 tile = replaceTex1ByTex0 ? 0 : t;
const gDPTile * pTile = gSP.textureTile[tile];
CachedTexture * pTexture = cache.current[tile];
if (pTile == nullptr || pTexture == nullptr)
continue;
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) {
const f32 wrapWidth = static_cast<f32>(1 << pTile->originalMaskS);
const f32 pow2Width = static_cast<f32>(pow2(pTexture->width));
aTexWrap[t][0] = wrapWidth / pow2Width;
aTexScale[t][0] = pow2Width / f32(pTexture->width);
}
if (pTexture->maskT) {
const f32 wrapHeight = static_cast<f32>(1 << pTile->originalMaskT);
const f32 pow2Height = static_cast<f32>(pow2(pTexture->height));
aTexWrap[t][1] = wrapHeight / pow2Height;
aTexScale[t][1] = pow2Height / f32(pTexture->height);
}
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);
uTexWrap1.set(aTexWrap[1][0], aTexWrap[1][1], _force);
uTexMirror0.set(aTexMirror[0][0], aTexMirror[0][1], _force);
uTexMirror1.set(aTexMirror[1][0], aTexMirror[1][1], _force);
uTexScale0.set(aTexScale[0][0], aTexScale[0][1], _force);
uTexScale1.set(aTexScale[1][0], aTexScale[1][1], _force);
}
private:
bool m_useTile[2];
fv4Uniform uTexClamp0;
fv4Uniform uTexClamp1;
fv2Uniform uTexWrap0;
fv2Uniform uTexWrap1;
fv2Uniform uTexMirror0;
fv2Uniform uTexMirror1;
fv2Uniform uTexScale0;
fv2Uniform uTexScale1;
};
/*---------------CombinerProgramUniformFactoryCommon-------------*/
void CombinerProgramUniformFactoryFast::_addRasterInfo(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new URasterInfoFast(_program));
}
void CombinerProgramUniformFactoryFast::_addMipmap(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UMipmap1(_program));
}
void CombinerProgramUniformFactoryFast::_addMipmap2(GLuint _program, UniformGroups &_uniforms) const
{
_uniforms.emplace_back(new UMipmap2(_program));
}
void CombinerProgramUniformFactoryFast::_addTextureSize(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const
{
_uniforms.emplace_back(new UTextureSizeFast(_program, _usesTile0, _usesTile1));
}
void CombinerProgramUniformFactoryFast::_addTextureParams(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const
{
_uniforms.emplace_back(new UTextureParamsFast(_program, _usesTile0, _usesTile1));
}
void CombinerProgramUniformFactoryFast::_addClampWrapMirrorEngine(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const
{
_uniforms.emplace_back(new UClampWrapMirrorTex(_program, _usesTile0, _usesTile1));
}
CombinerProgramUniformFactoryFast::CombinerProgramUniformFactoryFast(const opengl::GLInfo & _glInfo)
: CombinerProgramUniformFactoryCommon(_glInfo)
{
}
}

View File

@ -0,0 +1,26 @@
#pragma once
#include <Graphics/OpenGLContext/opengl_GLInfo.h>
#include "glsl_CombinerProgramImpl.h"
#include "glsl_CombinerProgramUniformFactoryCommon.h"
namespace glsl {
class CombinerProgramUniformFactoryFast : public CombinerProgramUniformFactoryCommon {
public:
CombinerProgramUniformFactoryFast(const opengl::GLInfo & _glInfo);
private:
virtual void _addRasterInfo(GLuint _program, UniformGroups &_uniforms) const override;
virtual void _addMipmap(GLuint _program, UniformGroups &_uniforms) const override;
virtual void _addMipmap2(GLuint _program, UniformGroups &_uniforms) const override;
virtual void _addTextureSize(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const override;
virtual void _addTextureParams(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const override;
virtual void _addClampWrapMirrorEngine(GLuint _program, UniformGroups &_uniforms, bool _usesTile0, bool _usesTile1) const override;
};
}

View File

@ -14,10 +14,12 @@
#include <Combiner.h>
#include <DisplayLoadProgress.h>
#include <osal_files.h>
#include <Config.h>
#include "glsl_Utils.h"
#include "glsl_ShaderStorage.h"
#include "glsl_CombinerProgramImpl.h"
#include "glsl_CombinerProgramUniformFactory.h"
#include "glsl_CombinerProgramUniformFactoryAccurate.h"
#include "glsl_CombinerProgramUniformFactoryFast.h"
using namespace glsl;
@ -203,7 +205,7 @@ bool ShaderStorage::saveShadersStorage(const graphics::Combiners & _combiners) c
static
CombinerProgramImpl * _readCombinerProgramFromStream(std::istream & _is,
CombinerKey& _cmbKey,
CombinerProgramUniformFactory & _uniformFactory,
std::unique_ptr<CombinerProgramUniformFactory> & _uniformFactory,
opengl::CachedUseProgram * _useProgram)
{
int inputs;
@ -226,7 +228,7 @@ CombinerProgramImpl * _readCombinerProgramFromStream(std::istream & _is,
}
UniformGroups uniforms;
_uniformFactory.buildUniforms(program, cmbInputs, _cmbKey, uniforms);
_uniformFactory->buildUniforms(program, cmbInputs, _cmbKey, uniforms);
return new CombinerProgramImpl(_cmbKey, program, _useProgram, cmbInputs, std::move(uniforms));
}
@ -336,7 +338,14 @@ bool ShaderStorage::loadShadersStorage(graphics::Combiners & _combiners)
return _loadFromCombinerKeys(_combiners);
displayLoadProgress(L"LOAD COMBINER SHADERS %.1f%%", 0.0f);
CombinerProgramUniformFactory uniformFactory(m_glinfo);
std::unique_ptr<CombinerProgramUniformFactory> uniformFactory;
if (config.generalEmulation.enableInaccurateTextureCoordinates) {
uniformFactory = std::make_unique<CombinerProgramUniformFactoryFast>(m_glinfo);
} else {
uniformFactory = std::make_unique<CombinerProgramUniformFactoryAccurate>(m_glinfo);
}
fin.read((char*)&len, sizeof(len));
const f32 percent = len / 100.0f;

View File

@ -20,7 +20,7 @@ namespace glsl {
bool _saveCombinerKeys(const graphics::Combiners & _combiners) const;
bool _loadFromCombinerKeys(graphics::Combiners & _combiners);
const u32 m_formatVersion = 0x37U;
const u32 m_formatVersion = 0x38U;
const u32 m_keysFormatVersion = 0x05;
const opengl::GLInfo & m_glinfo;
opengl::CachedUseProgram * m_useProgram;

View File

@ -13,7 +13,8 @@
#endif
#include "opengl_ColorBufferReaderWithReadPixels.h"
#include "opengl_Utils.h"
#include "GLSL/glsl_CombinerProgramBuilder.h"
#include "GLSL/glsl_CombinerProgramBuilderAccurate.h"
#include "GLSL/glsl_CombinerProgramBuilderFast.h"
#include "GLSL/glsl_SpecialShadersFactory.h"
#include "GLSL/glsl_ShaderStorage.h"
@ -408,7 +409,13 @@ void ContextImpl::resetCombinerProgramBuilder()
{
if (!isCombinerProgramBuilderObsolete())
return;
m_combinerProgramBuilder.reset(new glsl::CombinerProgramBuilder(m_glInfo, m_cachedFunctions->getCachedUseProgram()));
if (config.generalEmulation.enableInaccurateTextureCoordinates) {
m_combinerProgramBuilder = std::make_unique<glsl::CombinerProgramBuilderFast>(m_glInfo, m_cachedFunctions->getCachedUseProgram());
} else {
m_combinerProgramBuilder = std::make_unique<glsl::CombinerProgramBuilderAccurate>(m_glInfo, m_cachedFunctions->getCachedUseProgram());
}
m_specialShadersFactory.reset(new glsl::SpecialShadersFactory(m_glInfo,
m_cachedFunctions->getCachedUseProgram(),
m_combinerProgramBuilder->getVertexShaderHeader(),

View File

@ -1277,15 +1277,59 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
for (u32 t = 0; t < 2; ++t) {
if (pCurrentCombiner->usesTile(t) && cache.current[t] && gSP.textureTile[t]) {
const f32 uls = _FIXED2FLOAT(_params.s, 5);
const f32 lrs = uls + offsetX;
const f32 ult = _FIXED2FLOAT(_params.t, 5);
const f32 lrt = ult + offsetY;
texST[t].s0 = uls;
texST[t].s1 = lrs;
texST[t].t0 = ult;
texST[t].t1 = lrt;
if (config.generalEmulation.enableInaccurateTextureCoordinates) {
f32 shiftScaleS = 1.0f;
f32 shiftScaleT = 1.0f;
s16 S = _params.s;
if (gSP.textureTile[t]->shifts > 10) {
const u32 shifts = 16 - gSP.textureTile[t]->shifts;
S = static_cast<s16>(S << shifts);
shiftScaleS = static_cast<f32>(1 << shifts);
} else if (gSP.textureTile[t]->shifts > 0) {
const u32 shifts = gSP.textureTile[t]->shifts;
S = static_cast<s16>(S >> shifts);
shiftScaleS /= static_cast<f32>(1 << shifts);
}
const f32 uls = _FIXED2FLOAT(S, 5);
const f32 lrs = uls + offsetX * shiftScaleS;
s16 T = _params.t;
if (gSP.textureTile[t]->shiftt > 10) {
const u32 shiftt = 16 - gSP.textureTile[t]->shiftt;
T = static_cast<s16>(T << shiftt);
shiftScaleT = static_cast<f32>(1 << shiftt);
} else if (gSP.textureTile[t]->shiftt > 0) {
const u32 shiftt = gSP.textureTile[t]->shiftt;
T = static_cast<s16>(T >> shiftt);
shiftScaleT /= static_cast<f32>(1 << shiftt);
}
const f32 ult = _FIXED2FLOAT(T, 5);
const f32 lrt = ult + offsetY * shiftScaleT;
texST[t].s0 = uls - gSP.textureTile[t]->fuls;
texST[t].s1 = lrs - gSP.textureTile[t]->fuls;
texST[t].t0 = ult - gSP.textureTile[t]->fult;
texST[t].t1 = lrt - gSP.textureTile[t]->fult;
if (cache.current[t]->frameBufferTexture != CachedTexture::fbNone) {
texST[t].s0 = cache.current[t]->offsetS + texST[t].s0;
texST[t].t0 = cache.current[t]->offsetT + texST[t].t0;
texST[t].s1 = cache.current[t]->offsetS + texST[t].s1;
texST[t].t1 = cache.current[t]->offsetT + texST[t].t1;
}
} else {
const f32 uls = _FIXED2FLOAT(_params.s, 5);
const f32 lrs = uls + offsetX;
const f32 ult = _FIXED2FLOAT(_params.t, 5);
const f32 lrt = ult + offsetY;
texST[t].s0 = uls;
texST[t].s1 = lrs;
texST[t].t0 = ult;
texST[t].t1 = lrt;
}
if (cache.current[t]->frameBufferTexture != CachedTexture::fbMultiSample) {
Context::TexParameters texParams;
@ -1310,6 +1354,13 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
gfxContext.setTextureParameters(texParams);
}
}
if (config.generalEmulation.enableInaccurateTextureCoordinates) {
texST[t].s0 *= cache.current[t]->scaleS;
texST[t].t0 *= cache.current[t]->scaleT;
texST[t].s1 *= cache.current[t]->scaleS;
texST[t].t1 *= cache.current[t]->scaleT;
}
}
}

View File

@ -1100,7 +1100,206 @@ void doubleTexture(T* pTex, u32 width, u32 height)
}
}
void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
void TextureCache::_loadFast(u32 _tile, CachedTexture *_pTexture)
{
u64 ricecrc = 0;
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<u8>(gSP.texture.level - 1);
const u16 dim = std::max(_pTexture->width, _pTexture->height);
while (dim < static_cast<u16>(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;
}
}
}
u32 sizeShift = 1;
{
const TextureLoadParameters & loadParams =
ImageFormat::get().tlp[gDP.otherMode.textureLUT][_pTexture->size][_pTexture->format];
if (force32bitFormat || loadParams.autoFormat == internalcolorFormat::RGBA8)
sizeShift = 2;
}
_pTexture->textureBytes = (_pTexture->width * _pTexture->height) << sizeShift;
unsigned int totalTexSize = std::max(static_cast<u32>(_pTexture->textureBytes/sizeof(u32) + 8), MIPMAP_TILE_WIDTH)
* (_pTexture->max_level + 1);
if (m_tempTextureHolder.size() < totalTexSize) {
m_tempTextureHolder.resize(totalTexSize);
}
GetTexelFunc GetTexel;
InternalColorFormatParam glInternalFormat;
DatatypeParam glType;
auto getLoadParams = [&](u16 _format, u16 _size)
{
const TextureLoadParameters & loadParams =
ImageFormat::get().tlp[gDP.otherMode.textureLUT][_size][_format];
if (force32bitFormat || loadParams.autoFormat == internalcolorFormat::RGBA8) {
GetTexel = loadParams.Get32;
glInternalFormat = loadParams.glInternalFormat32;
glType = loadParams.glType32;
}
else {
GetTexel = loadParams.Get16;
glInternalFormat = loadParams.glInternalFormat16;
glType = loadParams.glType16;
}
};
CachedTexture tmptex = *_pTexture;
u16 line = tmptex.line;
while (true) {
getLoadParams(tmptex.format, tmptex.size);
{
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, m_tempTextureHolder.data(), glInternalFormat, GetTexel, &line);
if (sizeShift == 2)
doubleTexture<u32>(m_tempTextureHolder.data(), tmptex.width, tmptex.height);
else
doubleTexture<u16>((u16*)m_tempTextureHolder.data(), tmptex.width, tmptex.height);
tmptex.width = texWidth;
tmptex.height = texHeight;
} else {
_getTextureDestData(tmptex, m_tempTextureHolder.data(), glInternalFormat, GetTexel, &line);
}
}
if ((config.generalEmulation.hacks&hack_LoadDepthTextures) != 0 && gDP.colorImage.address == gDP.depthImageAddress) {
_loadDepthTexture(_pTexture, (u16*)m_tempTextureHolder.data());
return;
}
if (m_toggleDumpTex &&
config.textureFilter.txHiresEnable != 0 &&
config.hotkeys.enabledKeys[Config::HotKey::hkTexDump] != 0) {
txfilter_dmptx((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height,
tmptex.width, (u16)u32(glInternalFormat),
(unsigned short)(_pTexture->format << 8 | _pTexture->size),
ricecrc);
}
bool bLoaded = false;
bool needEnhance = (config.textureFilter.txEnhancementMode | config.textureFilter.txFilterMode) != 0 &&
_pTexture->max_level == 0 &&
TFH.isInited();
if (needEnhance) {
if (config.textureFilter.txFilterIgnoreBG != 0) {
switch (GBI.getMicrocodeType()) {
case S2DEX_1_07:
case S2DEX_1_03:
case S2DEX_1_05:
needEnhance = RSP.cmd != 0x01 && RSP.cmd != 0x02;
break;
case S2DEX2:
needEnhance = RSP.cmd != 0x09 && RSP.cmd != 0x0A;
break;
}
}
}
if (needEnhance) {
GHQTexInfo ghqTexInfo;
if (txfilter_filter((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height,
(u16)u32(glInternalFormat), (uint64)_pTexture->crc,
&ghqTexInfo) != 0 && ghqTexInfo.data != nullptr) {
if (ghqTexInfo.width % 2 != 0 &&
ghqTexInfo.format != u32(internalcolorFormat::RGBA8) &&
m_curUnpackAlignment > 1)
gfxContext.setTextureUnpackAlignment(2);
ghqTexInfo.format = gfxContext.convertInternalTextureFormat(ghqTexInfo.format);
Context::InitTextureParams params;
params.handle = _pTexture->name;
params.textureUnitIndex = textureIndices::Tex[_tile];
params.mipMapLevel = 0;
params.msaaLevel = 0;
params.width = ghqTexInfo.width;
params.height = ghqTexInfo.height;
params.internalFormat = InternalColorFormatParam(ghqTexInfo.format);
params.format = ColorFormatParam(ghqTexInfo.texture_format);
params.dataType = DatatypeParam(ghqTexInfo.pixel_type);
params.data = ghqTexInfo.data;
gfxContext.init2DTexture(params);
_updateCachedTexture(ghqTexInfo, _pTexture, tmptex.width, tmptex.height);
bLoaded = true;
}
}
if (!bLoaded) {
if (tmptex.width % 2 != 0 &&
glInternalFormat != internalcolorFormat::RGBA8 &&
m_curUnpackAlignment > 1)
gfxContext.setTextureUnpackAlignment(2);
Context::InitTextureParams params;
params.handle = _pTexture->name;
params.textureUnitIndex = textureIndices::Tex[_tile];
params.mipMapLevel = mipLevel;
params.mipMapLevels = _pTexture->max_level + 1;
params.msaaLevel = 0;
params.width = tmptex.width;
params.height = tmptex.height;
params.internalFormat = gfxContext.convertInternalTextureFormat(u32(glInternalFormat));
params.format = colorFormat::RGBA;
params.dataType = glType;
params.data = m_tempTextureHolder.data();
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);
}
void TextureCache::_loadAccurate(u32 _tile, CachedTexture *_pTexture)
{
u64 ricecrc = 0;
if (_loadHiresTexture(_tile, _pTexture, ricecrc))
@ -1125,28 +1324,12 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
}
_pTexture->textureBytes = (_pTexture->width * _pTexture->height) << sizeShift;
// RAII holder for texture data
class TexData
{
public:
TexData(u32 bytes)
{
pData = (u32*)malloc(bytes);
assert(pData != NULL);
}
~TexData()
{
free(pData);
pData = NULL;
}
u32 * get() const
{
return pData;
}
private:
u32 *pData = NULL;
} texData(std::max((_pTexture->textureBytes + 8*sizeof(u32)), MIPMAP_TILE_WIDTH * sizeof(u32))
* (_pTexture->max_level + 1));
unsigned int totalTexSize = std::max(static_cast<u32>(_pTexture->textureBytes/sizeof(u32) + 8), MIPMAP_TILE_WIDTH)
* (_pTexture->max_level + 1);
if (m_tempTextureHolder.size() < totalTexSize) {
m_tempTextureHolder.resize(totalTexSize);
}
GetTexelFunc GetTexel;
InternalColorFormatParam glInternalFormat;
@ -1180,15 +1363,15 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
while (true)
{
const u32 tileSizePacked = texDataOffset | (tmptex.width << 16) | (tmptex.height << 24);
texData.get()[mipLevel] = tileSizePacked;
m_tempTextureHolder[mipLevel] = tileSizePacked;
getLoadParams(tmptex.format, tmptex.size);
_getTextureDestData(tmptex, texData.get() + texDataOffset, glInternalFormat, GetTexel, &line);
_getTextureDestData(tmptex, &m_tempTextureHolder[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,
txfilter_dmptx((u8*)(m_tempTextureHolder.data() + texDataOffset), tmptex.width, tmptex.height,
tmptex.width, (u16)u32(glInternalFormat),
(unsigned short)(_pTexture->format << 8 | _pTexture->size),
ricecrc);
@ -1228,7 +1411,7 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
params.internalFormat = gfxContext.convertInternalTextureFormat(u32(glInternalFormat));
params.format = colorFormat::RGBA;
params.dataType = glType;
params.data = texData.get();
params.data = m_tempTextureHolder.data();
gfxContext.init2DTexture(params);
_pTexture->mipmapAtlasWidth = params.width;
_pTexture->mipmapAtlasHeight = params.height;
@ -1236,17 +1419,17 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
else
{
getLoadParams(tmptex.format, tmptex.size);
_getTextureDestData(tmptex, texData.get(), glInternalFormat, GetTexel, &line);
_getTextureDestData(tmptex, m_tempTextureHolder.data(), glInternalFormat, GetTexel, &line);
if ((config.generalEmulation.hacks&hack_LoadDepthTextures) != 0 && gDP.colorImage.address == gDP.depthImageAddress) {
_loadDepthTexture(_pTexture, (u16*)texData.get());
_loadDepthTexture(_pTexture, (u16*)m_tempTextureHolder.data());
return;
}
if (m_toggleDumpTex &&
config.textureFilter.txHiresEnable != 0 &&
config.hotkeys.enabledKeys[Config::HotKey::hkTexDump] != 0) {
txfilter_dmptx((u8*)texData.get(), tmptex.width, tmptex.height,
txfilter_dmptx((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height,
tmptex.width, (u16)u32(glInternalFormat),
(unsigned short)(_pTexture->format << 8 | _pTexture->size),
ricecrc);
@ -1273,7 +1456,7 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
if (needEnhance) {
GHQTexInfo ghqTexInfo;
if (txfilter_filter((u8*)texData.get(), tmptex.width, tmptex.height,
if (txfilter_filter((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height,
(u16)u32(glInternalFormat), (uint64)_pTexture->crc,
&ghqTexInfo) != 0 && ghqTexInfo.data != nullptr) {
if (ghqTexInfo.width % 2 != 0 &&
@ -1313,7 +1496,7 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
params.internalFormat = gfxContext.convertInternalTextureFormat(u32(glInternalFormat));
params.format = colorFormat::RGBA;
params.dataType = glType;
params.data = texData.get();
params.data = m_tempTextureHolder.data();
gfxContext.init2DTexture(params);
}
}
@ -1565,6 +1748,14 @@ void TextureCache::update(u32 _t)
return;
}
if (_t == 1 && needReplaceTex1ByTex0()) {
current[1] = current[0];
if (current[1] != nullptr) {
activateTexture(1, current[1]);
return;
}
}
if (gSP.texture.tile == 7 &&
_t == 0 &&
gSP.textureTile[0] == gDP.loadTile &&
@ -1660,7 +1851,11 @@ void TextureCache::update(u32 _t)
pCurrent->offsetS = 0.0f;
pCurrent->offsetT = 0.0f;
_load(_t, pCurrent);
if (config.generalEmulation.enableInaccurateTextureCoordinates) {
_loadFast(_t, pCurrent);
} else {
_loadAccurate(_t, pCurrent);
}
activateTexture( _t, pCurrent );
current[_t] = pCurrent;
@ -1686,4 +1881,11 @@ void getTextureShiftScale(u32 t, const TextureCache & cache, f32 & shiftScaleS,
shiftScaleT = (f32)(1 << (16 - gSP.textureTile[t]->shiftt));
else if (gSP.textureTile[t]->shiftt > 0)
shiftScaleT /= (f32)(1 << gSP.textureTile[t]->shiftt);
}
}
bool needReplaceTex1ByTex0()
{
return config.generalEmulation.enableInaccurateTextureCoordinates &&
gSP.texture.level == 0 && gDP.otherMode.textureLOD == G_TL_LOD && gDP.otherMode.textureDetail == G_TD_CLAMP;
}

View File

@ -5,6 +5,7 @@
#include <list>
#include <map>
#include <unordered_map>
#include <vector>
#include <stddef.h> // for size_t
#include "CRC.h"
@ -84,7 +85,8 @@ private:
void _checkCacheSize();
CachedTexture * _addTexture(u64 _crc64);
void _load(u32 _tile, CachedTexture *_pTexture);
void _loadFast(u32 _tile, CachedTexture *_pTexture);
void _loadAccurate(u32 _tile, CachedTexture *_pTexture);
bool _loadHiresTexture(u32 _tile, CachedTexture *_pTexture, u64 & _ricecrc);
void _loadBackground(CachedTexture *pTexture);
bool _loadHiresBackground(CachedTexture *_pTexture, u64 & _ricecrc);
@ -104,6 +106,7 @@ private:
u32 m_hits, m_misses;
s32 m_curUnpackAlignment;
bool m_toggleDumpTex;
std::vector<u32> m_tempTextureHolder;
#ifdef VC
const size_t m_maxCacheSize = 1500;
#else
@ -113,6 +116,9 @@ private:
void getTextureShiftScale(u32 tile, const TextureCache & cache, f32 & shiftScaleS, f32 & shiftScaleT);
// Check for situation when Tex0 is used instead of Tex1
bool needReplaceTex1ByTex0();
inline TextureCache & textureCache()
{
return TextureCache::get();

View File

@ -858,7 +858,7 @@ void gDPTextureRectangle(f32 ulx, f32 uly, f32 lrx, f32 lry, s32 tile, s16 s, s1
textureTileOrg[0] = gSP.textureTile[0];
textureTileOrg[1] = gSP.textureTile[1];
gSP.textureTile[0] = &gDP.tiles[tile];
gSP.textureTile[1] = &gDP.tiles[(tile + 1) & 7];
gSP.textureTile[1] = needReplaceTex1ByTex0() ? &gDP.tiles[tile] : &gDP.tiles[(tile + 1) & 7];
// HACK ALERT!
if (s == 0x4000 && (gDP.colorImage.width + gSP.textureTile[0]->uls < 512))
@ -973,7 +973,7 @@ void LLETriangle::start(u32 _tile)
m_textureScaleOrg[1] = gSP.texture.scalet;
gSP.texture.tile = _tile;
gSP.textureTile[0] = &gDP.tiles[_tile];
gSP.textureTile[1] = &gDP.tiles[(_tile + 1) & 7];
gSP.textureTile[1] = needReplaceTex1ByTex0() ? &gDP.tiles[_tile] : &gDP.tiles[(_tile + 1) & 7];
gSP.texture.scales = 1.0f;
gSP.texture.scalet = 1.0f;
m_flushed = false;

View File

@ -163,6 +163,8 @@ bool Config_SetDefault()
assert(res == M64ERR_SUCCESS);
res = ConfigSetDefaultBool(g_configVideoGliden64, "EnableHybridFilter", config.generalEmulation.enableHybridFilter, "Enable hybrid integer scaling filter. Can be slow with low-end GPUs.");
assert(res == M64ERR_SUCCESS);
res = ConfigSetDefaultBool(g_configVideoGliden64, "EnableInaccurateTextureCoordinates", config.generalEmulation.enableInaccurateTextureCoordinates, "Use fast but less accurate shaders. Can help with low-end GPUs.");
assert(res == M64ERR_SUCCESS);
res = ConfigSetDefaultBool(g_configVideoGliden64, "EnableFragmentDepthWrite", config.generalEmulation.enableFragmentDepthWrite, "Enable writing of fragment depth. Some mobile GPUs do not support it, thus made optional. Leave enabled.");
assert(res == M64ERR_SUCCESS);
res = ConfigSetDefaultBool(g_configVideoGliden64, "EnableCustomSettings", config.generalEmulation.enableCustomSettings, "Use GLideN64 per-game settings.");
@ -508,6 +510,7 @@ void Config_LoadConfig()
config.generalEmulation.enableShadersStorage = ConfigGetParamBool(g_configVideoGliden64, "EnableShadersStorage");
config.generalEmulation.enableLegacyBlending = ConfigGetParamBool(g_configVideoGliden64, "EnableLegacyBlending");
config.generalEmulation.enableHybridFilter = ConfigGetParamBool(g_configVideoGliden64, "EnableHybridFilter");
config.generalEmulation.enableInaccurateTextureCoordinates = ConfigGetParamBool(g_configVideoGliden64, "EnableInaccurateTextureCoordinates");
config.generalEmulation.enableFragmentDepthWrite = ConfigGetParamBool(g_configVideoGliden64, "EnableFragmentDepthWrite");
config.generalEmulation.enableCustomSettings = ConfigGetParamBool(g_configVideoGliden64, "EnableCustomSettings");
#if defined(OS_ANDROID) || defined(OS_IOS)