From bda5d81f8218136c60245ff2f40155ef7a3abd96 Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Thu, 5 Jan 2017 18:05:47 +0700 Subject: [PATCH] CombinerProgramUniformFactory --- projects/msvc12/GLideN64.vcxproj | 6 + projects/msvc12/GLideN64.vcxproj.filters | 18 + src/Graphics/CombinerProgram.h | 11 + .../GLSL/glsl_CombinerInputs.cpp | 46 + .../OpenGLContext/GLSL/glsl_CombinerInputs.h | 31 + .../GLSL/glsl_CombinerProgramBuilder.cpp | 275 +++--- .../GLSL/glsl_CombinerProgramBuilder.h | 13 +- .../GLSL/glsl_CombinerProgramImpl.cpp | 88 +- .../GLSL/glsl_CombinerProgramImpl.h | 41 +- .../glsl_CombinerProgramUniformFactory.cpp | 861 ++++++++++++++++++ .../GLSL/glsl_CombinerProgramUniformFactory.h | 22 + .../OpenGLContext/GLSL/glsl_NoiseTexture.cpp | 116 +++ .../OpenGLContext/GLSL/glsl_NoiseTexture.h | 24 + .../OpenGLContext/opengl_ContextImpl.cpp | 8 +- .../OpenGLContext/opengl_ContextImpl.h | 5 + 15 files changed, 1361 insertions(+), 204 deletions(-) create mode 100644 src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.cpp create mode 100644 src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.h create mode 100644 src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp create mode 100644 src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.h create mode 100644 src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.cpp create mode 100644 src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.h diff --git a/projects/msvc12/GLideN64.vcxproj b/projects/msvc12/GLideN64.vcxproj index 7ac3520e..68982662 100644 --- a/projects/msvc12/GLideN64.vcxproj +++ b/projects/msvc12/GLideN64.vcxproj @@ -302,8 +302,11 @@ + + + @@ -439,8 +442,11 @@ + + + diff --git a/projects/msvc12/GLideN64.vcxproj.filters b/projects/msvc12/GLideN64.vcxproj.filters index 0b885174..7f6831b6 100644 --- a/projects/msvc12/GLideN64.vcxproj.filters +++ b/projects/msvc12/GLideN64.vcxproj.filters @@ -320,6 +320,15 @@ Source Files\Graphics\OpenGL + + Source Files\Graphics\OpenGL\GLSL + + + Source Files\Graphics\OpenGL\GLSL + + + Source Files\Graphics\OpenGL\GLSL + @@ -583,5 +592,14 @@ Header Files\Graphics\OpenGL + + Header Files\Graphics\OpenGL\GLSL + + + Header Files\Graphics\OpenGL\GLSL + + + Header Files\Graphics\OpenGL\GLSL + \ No newline at end of file diff --git a/src/Graphics/CombinerProgram.h b/src/Graphics/CombinerProgram.h index 443efae1..d9d702eb 100644 --- a/src/Graphics/CombinerProgram.h +++ b/src/Graphics/CombinerProgram.h @@ -10,6 +10,17 @@ namespace graphics { virtual void activate() = 0; virtual void update(bool _force) = 0; virtual CombinerKey getKey() const = 0; + virtual bool usesTexture() const = 0; + virtual bool usesTile(u32 _t) const = 0; + virtual bool usesShade() const = 0; + virtual bool usesLOD() const = 0; + + // TODO implement + void disableBlending() {} + void updateFrameBufferInfo(bool _bForce = false) {} + + friend std::ostream & operator<< (std::ostream & _os, const CombinerProgram & _combiner); + friend std::istream & operator>> (std::istream & _os, CombinerProgram & _combiner); }; } diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.cpp new file mode 100644 index 00000000..6407513b --- /dev/null +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.cpp @@ -0,0 +1,46 @@ +#include +#include "glsl_CombinerInputs.h" + +using namespace glsl; + +bool CombinerInputs::usesTile(u32 _t) const +{ + if (_t == 0) + return (m_inputs & ((1 << TEXEL0) | (1 << TEXEL0_ALPHA))) != 0; + return (m_inputs & ((1 << TEXEL1) | (1 << TEXEL1_ALPHA))) != 0; +} + +bool CombinerInputs::usesTexture() const +{ + return (m_inputs & ((1 << TEXEL1) | (1 << TEXEL1_ALPHA) | (1 << TEXEL0) | (1 << TEXEL0_ALPHA))) != 0; +} + +bool CombinerInputs::usesLOD() const +{ + return (m_inputs & (1 << LOD_FRACTION)) != 0; +} + +bool CombinerInputs::usesNoise() const +{ + return (m_inputs & (1 << NOISE)) != 0; +} + +bool CombinerInputs::usesShade() const +{ + return (m_inputs & ((1 << SHADE) | (1 << SHADE_ALPHA))) != 0; +} + +bool CombinerInputs::usesShadeColor() const +{ + return (m_inputs & (1 << SHADE)) != 0; +} + +bool CombinerInputs::usesHwLighting() const +{ + return (m_inputs & (1 << HW_LIGHT)) != 0; +} + +void CombinerInputs::addInput(int _input) +{ + m_inputs |= 1 << _input; +} diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.h b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.h new file mode 100644 index 00000000..9850c9b3 --- /dev/null +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.h @@ -0,0 +1,31 @@ +#pragma once +#include + +namespace glsl { + + class CombinerInputs + { + public: + explicit CombinerInputs(int _inputs) : m_inputs(_inputs) {} + + bool usesTile(u32 _t) const; + + bool usesTexture() const; + + bool usesLOD() const; + + bool usesNoise() const; + + bool usesShade() const; + + bool usesShadeColor() const; + + bool usesHwLighting() const; + + void addInput(int _input); + + private: + int m_inputs; + }; + +} diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp index c2aec594..dc88bd72 100644 --- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp @@ -2,8 +2,11 @@ #include #include #include "glsl_Utils.h" +#include "glsl_NoiseTexture.h" +#include "glsl_CombinerInputs.h" #include "glsl_CombinerProgramImpl.h" #include "glsl_CombinerProgramBuilder.h" +#include "glsl_CombinerProgramUniformFactory.h" using namespace glsl; @@ -178,9 +181,9 @@ int _compileCombiner(const CombinerStage & _stage, const char** _Input, std::str class VertexShaderHeader : public ShaderPart { public: - VertexShaderHeader(const opengl::GLInfo & _version) + VertexShaderHeader(const opengl::GLInfo & _glinfo) { - if (_version.isGLES2) { + if (_glinfo.isGLES2) { m_part = "#version 100 \n"; m_part += "#if (__VERSION__ > 120) \n" @@ -192,15 +195,15 @@ public: "#endif // __VERSION \n" ; } - else if (_version.isGLESX) { + else if (_glinfo.isGLESX) { std::stringstream ss; - ss << "#version " << _version.majorVersion << _version.minorVersion << "0 es " << std::endl; + ss << "#version " << _glinfo.majorVersion << _glinfo.minorVersion << "0 es " << std::endl; ss << "# define IN in" << std::endl << "# define OUT out" << std::endl; m_part = ss.str(); } else { std::stringstream ss; - ss << "#version " << _version.majorVersion << _version.minorVersion << "0 core " << std::endl; + ss << "#version " << _glinfo.majorVersion << _glinfo.minorVersion << "0 core " << std::endl; ss << "# define IN in" << std::endl << "# define OUT out" << std::endl; m_part = ss.str(); } @@ -210,7 +213,7 @@ public: class VertexShaderTexturedTriangle : public ShaderPart { public: - VertexShaderTexturedTriangle(const opengl::GLInfo & _version) + VertexShaderTexturedTriangle(const opengl::GLInfo & _glinfo) { m_part = "IN highp vec4 aPosition; \n" @@ -276,7 +279,7 @@ public: " vShadeColor.a = clamp(fp, 0.0, 1.0); \n" " } \n" ; - if (!_version.isGLESX) { + if (!_glinfo.isGLESX) { m_part += " gl_ClipDistance[0] = gl_Position.w - gl_Position.z; \n" ; @@ -290,7 +293,7 @@ public: class VertexShaderTriangle : public ShaderPart { public: - VertexShaderTriangle(const opengl::GLInfo & _version) + VertexShaderTriangle(const opengl::GLInfo & _glinfo) { m_part = "IN highp vec4 aPosition; \n" @@ -329,7 +332,7 @@ public: " vShadeColor.a = clamp(fp, 0.0, 1.0); \n" " } \n" ; - if (!_version.isGLESX) { + if (!_glinfo.isGLESX) { m_part += " gl_ClipDistance[0] = gl_Position.w - gl_Position.z; \n" ; @@ -343,7 +346,7 @@ public: class VertexShaderTexturedRect : public ShaderPart { public: - VertexShaderTexturedRect(const opengl::GLInfo & _version) + VertexShaderTexturedRect(const opengl::GLInfo & _glinfo) { m_part = "IN highp vec4 aRectPosition; \n" @@ -361,7 +364,7 @@ public: " vTexCoord0 = aTexCoord0; \n" " vTexCoord1 = aTexCoord1; \n" ; - if (!_version.isGLESX) { + if (!_glinfo.isGLESX) { m_part += " gl_ClipDistance[0] = gl_Position.w - gl_Position.z; \n" ; @@ -375,7 +378,7 @@ public: class VertexShaderRect : public ShaderPart { public: - VertexShaderRect(const opengl::GLInfo & _version) + VertexShaderRect(const opengl::GLInfo & _glinfo) { m_part = "IN highp vec4 aRectPosition; \n" @@ -387,7 +390,7 @@ public: " gl_Position = aRectPosition; \n" " vShadeColor = aRectColor; \n" ; - if (!_version.isGLESX) { + if (!_glinfo.isGLESX) { m_part += " gl_ClipDistance[0] = gl_Position.w - gl_Position.z; \n" ; @@ -401,9 +404,9 @@ public: class FragmentShaderHeader : public ShaderPart { public: - FragmentShaderHeader(const opengl::GLInfo & _version) + FragmentShaderHeader(const opengl::GLInfo & _glinfo) { - if (_version.isGLES2) { + if (_glinfo.isGLES2) { m_part = "#version 100 \n"; m_part += "#extension GL_EXT_shader_texture_lod : enable \n"; m_part += "#extension GL_OES_standard_derivatives : enable \n"; @@ -417,14 +420,14 @@ public: "#endif // __VERSION __ \n" ; } - else if (_version.isGLESX) { + else if (_glinfo.isGLESX) { std::stringstream ss; - ss << "#version " << _version.majorVersion << _version.minorVersion << "0 es " << std::endl; + ss << "#version " << _glinfo.majorVersion << _glinfo.minorVersion << "0 es " << std::endl; ss << "# define IN in" << std::endl << "# define OUT out" << std::endl; m_part = ss.str(); } else { std::stringstream ss; - ss << "#version " << _version.majorVersion << _version.minorVersion << "0 core " << std::endl; + ss << "#version " << _glinfo.majorVersion << _glinfo.minorVersion << "0 core " << std::endl; ss << "# define IN in" << std::endl << "# define OUT out" << std::endl; m_part = ss.str(); } @@ -434,9 +437,9 @@ public: class ShaderBlender1 : public ShaderPart { public: - ShaderBlender1(const opengl::GLInfo & _version) + ShaderBlender1(const opengl::GLInfo & _glinfo) { - if (_version.isGLES2) { + if (_glinfo.isGLES2) { m_part = " if (uForceBlendCycle1 != 0) { \n" " muxPM[0] = clampedColor; \n" @@ -500,9 +503,9 @@ public: class ShaderBlender2 : public ShaderPart { public: - ShaderBlender2(const opengl::GLInfo & _version) + ShaderBlender2(const opengl::GLInfo & _glinfo) { - if (_version.isGLES2) { + if (_glinfo.isGLES2) { m_part = " if (uForceBlendCycle2 != 0) { \n" " muxPM[0] = clampedColor; \n" @@ -689,9 +692,9 @@ public: class ShaderCallDither : public ShaderPart { public: - ShaderCallDither(const opengl::GLInfo & _version) + ShaderCallDither(const opengl::GLInfo & _glinfo) { - if (!_version.isGLES2 && config.generalEmulation.enableNoise != 0) { + if (!_glinfo.isGLES2 && config.generalEmulation.enableNoise != 0) { m_part = " if (uColorDitherMode == 2) colorNoiseDither(snoise(), clampedColor.rgb); \n" " if (uAlphaDitherMode == 2) alphaNoiseDither(snoise(), clampedColor.a); \n" @@ -703,7 +706,7 @@ public: class ShaderFragmentGlobalVariablesTex : public ShaderPart { public: - ShaderFragmentGlobalVariablesTex(const opengl::GLInfo & _version) + ShaderFragmentGlobalVariablesTex(const opengl::GLInfo & _glinfo) { m_part = "uniform sampler2D uTex0; \n" @@ -738,7 +741,7 @@ public: ; } - if (!_version.isGLES2) { + if (!_glinfo.isGLES2) { m_part += "uniform sampler2D uDepthTex; \n" "uniform lowp int uAlphaDitherMode; \n" @@ -746,7 +749,7 @@ public: "uniform lowp int uRenderTarget; \n" "uniform mediump vec2 uDepthScale; \n" ; - if (_version.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) { + if (_glinfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) { m_part += "uniform lowp int uEnableDepthCompare; \n" ; @@ -759,9 +762,9 @@ public: if (config.video.multisampling > 0) { m_part += - "uniform lowp ivec2 uMSTexEnabled; \n"; - "uniform lowp sampler2DMS uMSTex0; \n"; - "uniform lowp sampler2DMS uMSTex1; \n"; + "uniform lowp ivec2 uMSTexEnabled; \n" + "uniform lowp sampler2DMS uMSTex0; \n" + "uniform lowp sampler2DMS uMSTex1; \n" ; } @@ -779,7 +782,7 @@ public: class ShaderFragmentGlobalVariablesNotex : public ShaderPart { public: - ShaderFragmentGlobalVariablesNotex(const opengl::GLInfo & _version) + ShaderFragmentGlobalVariablesNotex(const opengl::GLInfo & _glinfo) { m_part = "uniform lowp vec4 uFogColor; \n" @@ -812,7 +815,7 @@ public: ; } - if (!_version.isGLES2) { + if (!_glinfo.isGLES2) { m_part += "uniform sampler2D uDepthTex; \n" "uniform lowp int uAlphaDitherMode; \n" @@ -820,7 +823,7 @@ public: "uniform lowp int uRenderTarget; \n" "uniform mediump vec2 uDepthScale; \n" ; - if (_version.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) { + if (_glinfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) { m_part += "uniform lowp int uEnableDepthCompare; \n" ; @@ -841,7 +844,7 @@ public: class ShaderFragmentHeaderNoise : public ShaderPart { public: - ShaderFragmentHeaderNoise(const opengl::GLInfo & _version) + ShaderFragmentHeaderNoise(const opengl::GLInfo & _glinfo) { m_part = "lowp float snoise();\n"; @@ -852,9 +855,9 @@ public: class ShaderFragmentHeaderWriteDepth : public ShaderPart { public: - ShaderFragmentHeaderWriteDepth(const opengl::GLInfo & _version) + ShaderFragmentHeaderWriteDepth(const opengl::GLInfo & _glinfo) { - if (!_version.isGLES2) { + if (!_glinfo.isGLES2) { m_part = "void writeDepth();\n"; ; @@ -865,7 +868,7 @@ public: class ShaderFragmentHeaderCalcLight : public ShaderPart { public: - ShaderFragmentHeaderCalcLight(const opengl::GLInfo & _version) + ShaderFragmentHeaderCalcLight(const opengl::GLInfo & _glinfo) { m_part = "void calc_light(in lowp float fLights, in lowp vec3 input_color, out lowp vec3 output_color);\n"; @@ -876,7 +879,7 @@ public: class ShaderFragmentHeaderMipMap : public ShaderPart { public: - ShaderFragmentHeaderMipMap(const opengl::GLInfo & _version) + ShaderFragmentHeaderMipMap(const opengl::GLInfo & _glinfo) { m_part = "mediump float mipmap(out lowp vec4 readtex0, out lowp vec4 readtex1);\n"; @@ -887,9 +890,9 @@ public: class ShaderFragmentHeaderReadMSTex : public ShaderPart { public: - ShaderFragmentHeaderReadMSTex(const opengl::GLInfo & _version) + ShaderFragmentHeaderReadMSTex(const opengl::GLInfo & _glinfo) { - if (!_version.isGLES2 && config.video.multisampling > 0) { + if (!_glinfo.isGLES2 && config.video.multisampling > 0) { m_part = "lowp vec4 readTexMS(in lowp sampler2DMS mstex, in mediump vec2 texCoord, in lowp int fbMonochrome, in lowp int fbFixedAlpha);\n"; ; @@ -900,9 +903,9 @@ public: class ShaderFragmentHeaderDither : public ShaderPart { public: - ShaderFragmentHeaderDither(const opengl::GLInfo & _version) + ShaderFragmentHeaderDither(const opengl::GLInfo & _glinfo) { - if (!_version.isGLES2 && config.generalEmulation.enableNoise != 0) { + if (!_glinfo.isGLES2 && config.generalEmulation.enableNoise != 0) { m_part = "void colorNoiseDither(in lowp float _noise, inout lowp vec3 _color);\n" "void alphaNoiseDither(in lowp float _noise, inout lowp float _alpha);\n"; @@ -914,9 +917,9 @@ public: class ShaderFragmentHeaderDepthCompare : public ShaderPart { public: - ShaderFragmentHeaderDepthCompare(const opengl::GLInfo & _version) + ShaderFragmentHeaderDepthCompare(const opengl::GLInfo & _glinfo) { - if (_version.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) { + if (_glinfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) { m_part = "bool depth_compare();\n" "bool depth_render(highp float Z);\n"; @@ -928,9 +931,9 @@ public: class ShaderFragmentHeaderReadTex : public ShaderPart { public: - ShaderFragmentHeaderReadTex (const opengl::GLInfo & _version) + ShaderFragmentHeaderReadTex (const opengl::GLInfo & _glinfo) { - if (!_version.isGLES2) { + if (!_glinfo.isGLES2) { if (config.texture.bilinearMode == BILINEAR_3POINT) { m_part = "uniform lowp int uTextureFilterMode; \n" @@ -977,13 +980,13 @@ public: class ShaderFragmentMain : public ShaderPart { public: - ShaderFragmentMain(const opengl::GLInfo & _version) + ShaderFragmentMain(const opengl::GLInfo & _glinfo) { m_part = "void main() \n" "{ \n" ; - if (!_version.isGLES2) { + if (!_glinfo.isGLES2) { m_part += " writeDepth(); \n" ; @@ -999,13 +1002,13 @@ public: class ShaderFragmentMain2Cycle : public ShaderPart { public: - ShaderFragmentMain2Cycle(const opengl::GLInfo & _version) + ShaderFragmentMain2Cycle(const opengl::GLInfo & _glinfo) { m_part = "void main() \n" "{ \n" ; - if (!_version.isGLES2) { + if (!_glinfo.isGLES2) { m_part += " writeDepth(); \n" ; @@ -1021,7 +1024,7 @@ public: class ShaderFragmentBlendMux : public ShaderPart { public: - ShaderFragmentBlendMux(const opengl::GLInfo & _version) + ShaderFragmentBlendMux(const opengl::GLInfo & _glinfo) { if (config.generalEmulation.enableLegacyBlending == 0) { m_part = @@ -1036,7 +1039,7 @@ public: class ShaderFragmentReadTexMipmap : public ShaderPart { public: - ShaderFragmentReadTexMipmap(const opengl::GLInfo & _version) + ShaderFragmentReadTexMipmap(const opengl::GLInfo & _glinfo) { m_part = " lowp vec4 readtex0, readtex1; \n" @@ -1048,26 +1051,26 @@ public: class ShaderFragmentReadTex0 : public ShaderPart { public: - ShaderFragmentReadTex0(const opengl::GLInfo & _version) + ShaderFragmentReadTex0(const opengl::GLInfo & _glinfo) { - if (_version.isGLES2) { + if (_glinfo.isGLES2) { + m_part = + " nCurrentTile = 0; \n" + " lowp vec4 readtex0 = readTex(uTex0, vTexCoord0, uFbMonochrome[0], uFbFixedAlpha[0]); \n" + ; + } else { if (config.video.multisampling > 0) { m_part = " lowp vec4 readtex0; \n" " if (uMSTexEnabled[0] == 0) READ_TEX(readtex0, uTex0, vTexCoord0, uFbMonochrome[0], uFbFixedAlpha[0]) \n" " else readtex0 = readTexMS(uMSTex0, vTexCoord0, uFbMonochrome[0], uFbFixedAlpha[0]); \n" - ; + ; } else { m_part = " lowp vec4 readtex0; \n" " READ_TEX(readtex0, uTex0, vTexCoord0, uFbMonochrome[0], uFbFixedAlpha[0]); \n" - ; + ; } - } else { - m_part = - " nCurrentTile = 0; \n" - " lowp vec4 readtex0 = readTex(uTex0, vTexCoord0, uFbMonochrome[0], uFbFixedAlpha[0]); \n" - ; } } }; @@ -1075,38 +1078,36 @@ public: class ShaderFragmentReadTex1 : public ShaderPart { public: - ShaderFragmentReadTex1(const opengl::GLInfo & _version) + ShaderFragmentReadTex1(const opengl::GLInfo & _glinfo) { - if (_version.isGLES2) { + if (_glinfo.isGLES2) { + m_part = + " nCurrentTile = 1; \n" + " lowp vec4 readtex1 = readTex(uTex1, vTexCoord1, uFbMonochrome[1], uFbFixedAlpha[1]); \n" + ; + } else { if (config.video.multisampling > 0) { m_part = " lowp vec4 readtex1; \n" " if (uMSTexEnabled[1] == 0) READ_TEX(readtex1, uTex1, vTexCoord1, uFbMonochrome[1], uFbFixedAlpha[1]) \n" " else readtex1 = readTexMS(uMSTex1, vTexCoord1, uFbMonochrome[1], uFbFixedAlpha[1]); \n" - ; - } - else { + ; + } else { m_part = " lowp vec4 readtex1; \n" " READ_TEX(readtex1, uTex1, vTexCoord1, uFbMonochrome[1], uFbFixedAlpha[1]); \n" - ; + ; } } - else { - m_part = - " nCurrentTile = 1; \n" - " lowp vec4 readtex1 = readTex(uTex1, vTexCoord1, uFbMonochrome[1], uFbFixedAlpha[1]); \n" - ; - } } }; class ShaderFragmentCallN64Depth : public ShaderPart { public: - ShaderFragmentCallN64Depth(const opengl::GLInfo & _version) + ShaderFragmentCallN64Depth(const opengl::GLInfo & _glinfo) { - if (!_version.isGLES2 && _version.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) { + if (!_glinfo.isGLES2 && _glinfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) { m_part = " if (uRenderTarget != 0) { if (!depth_render(fragColor.r)) discard; } \n" " else if (!depth_compare()) discard; \n" @@ -1118,9 +1119,9 @@ public: class ShaderFragmentRenderTarget : public ShaderPart { public: - ShaderFragmentRenderTarget(const opengl::GLInfo & _version) + ShaderFragmentRenderTarget(const opengl::GLInfo & _glinfo) { - if (!_version.isGLES2 && config.generalEmulation.enableFragmentDepthWrite != 0) { + if (!_glinfo.isGLES2 && config.generalEmulation.enableFragmentDepthWrite != 0) { m_part = " if (uRenderTarget != 0) { \n" " if (uRenderTarget > 1) { \n" @@ -1137,7 +1138,7 @@ public: class ShaderNoise : public ShaderPart { public: - ShaderNoise(const opengl::GLInfo & _version) + ShaderNoise(const opengl::GLInfo & _glinfo) { if (config.generalEmulation.enableNoise == 0) { // Dummy noise @@ -1148,7 +1149,7 @@ public: "} \n" ; } else { - if (_version.isGLES2) { + if (_glinfo.isGLES2) { m_part = "uniform sampler2D uTexNoise; \n" "lowp float snoise() \n" @@ -1175,9 +1176,9 @@ public: class ShaderDither : public ShaderPart { public: - ShaderDither(const opengl::GLInfo & _version) + ShaderDither(const opengl::GLInfo & _glinfo) { - if (!_version.isGLES2 && config.generalEmulation.enableNoise != 0) { + if (!_glinfo.isGLES2 && config.generalEmulation.enableNoise != 0) { m_part = "void colorNoiseDither(in lowp float _noise, inout lowp vec3 _color) \n" "{ \n" @@ -1203,9 +1204,9 @@ public: class ShaderWriteDepth : public ShaderPart { public: - ShaderWriteDepth(const opengl::GLInfo & _version) + ShaderWriteDepth(const opengl::GLInfo & _glinfo) { - if (!_version.isGLES2) { + if (!_glinfo.isGLES2) { if (config.generalEmulation.enableFragmentDepthWrite == 0) { // Dummy write depth m_part = @@ -1228,9 +1229,9 @@ public: class ShaderMipmap : public ShaderPart { public: - ShaderMipmap(const opengl::GLInfo & _version) + ShaderMipmap(const opengl::GLInfo & _glinfo) { - if (_version.isGLES2) { + if (_glinfo.isGLES2) { if (config.generalEmulation.enableLOD == 0) { // Fake mipmap m_part = @@ -1390,7 +1391,7 @@ public: class ShaderCalcLight : public ShaderPart { public: - ShaderCalcLight(const opengl::GLInfo & _version) + ShaderCalcLight(const opengl::GLInfo & _glinfo) { m_part = "uniform mediump vec3 uLightDirection[8]; \n" @@ -1415,9 +1416,9 @@ public: class ShaderReadtex : public ShaderPart { public: - ShaderReadtex(const opengl::GLInfo & _version) + ShaderReadtex(const opengl::GLInfo & _glinfo) { - if (_version.isGLES2) { + if (_glinfo.isGLES2) { if (config.texture.bilinearMode == BILINEAR_3POINT) { m_part = "uniform mediump vec2 uTextureSize[2]; \n" @@ -1502,10 +1503,10 @@ public: class ShaderN64DepthCompare : public ShaderPart { public: - ShaderN64DepthCompare(const opengl::GLInfo & _version) + ShaderN64DepthCompare(const opengl::GLInfo & _glinfo) { - if (_version.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) { - m_part = _version.isGLESX + if (_glinfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) { + m_part = _glinfo.isGLESX ? "layout(binding = 2, rgba32f) highp uniform coherent image2D uDepthImage;\n" : "layout(binding = 2, rg32f) highp uniform coherent image2D uDepthImage;\n" ; @@ -1564,10 +1565,10 @@ public: class ShaderN64DepthRender : public ShaderPart { public: - ShaderN64DepthRender(const opengl::GLInfo & _version) + ShaderN64DepthRender(const opengl::GLInfo & _glinfo) { - if (_version.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) { - m_part = _version.isGLESX + if (_glinfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) { + m_part = _glinfo.isGLESX ? "layout(binding = 2, rgba32f) highp uniform coherent image2D uDepthImage;\n" : "layout(binding = 2, rg32f) highp uniform coherent image2D uDepthImage;\n" ; @@ -1645,7 +1646,7 @@ int CombinerProgramBuilder::compileCombiner(const CombinerKey & _key, Combiner & _correctFirstStageParams(_alpha.stage[0]); _correctFirstStageParams(_color.stage[0]); } - _strShader.append(" alpha1 = "); + ssShader << " alpha1 = "; int nInputs = _compileCombiner(_alpha.stage[0], AlphaInput, ssShader); // Simulate N64 color sign-extend. if (combinedAlphaC(combine)) @@ -1655,7 +1656,7 @@ int CombinerProgramBuilder::compileCombiner(const CombinerKey & _key, Combiner & m_alphaTest->write(ssShader); - _strShader.append(" color1 = "); + ssShader << " color1 = "; nInputs |= _compileCombiner(_color.stage[0], ColorInput, ssShader); // Simulate N64 color sign-extend. if (combinedColorC(combine)) @@ -1712,7 +1713,7 @@ int CombinerProgramBuilder::compileCombiner(const CombinerKey & _key, Combiner & m_legacyBlender->write(ssShader); } - _strShader = ssShader.str(); + _strShader = std::move(ssShader.str()); return nInputs; } @@ -1842,10 +1843,11 @@ graphics::CombinerProgram * CombinerProgramBuilder::buildCombinerProgram(Combine glLinkProgram(program); assert(Utils::checkProgramLinkStatus(program)); glDeleteShader(fragmentShader); -// _locateUniforms(); + UniformGroups uniforms; + m_uniformFactory->buildUniforms(program, combinerInputs, bIsRect, uniforms); - return nullptr; + return new CombinerProgramImpl(program, combinerInputs, std::move(uniforms)); } static @@ -1864,9 +1866,9 @@ GLuint _createVertexShader(ShaderPart * _header, ShaderPart * _body) return shader_object; } -CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _version) -: m_blender1(new ShaderBlender1(_version)) -, m_blender2(new ShaderBlender2(_version)) +CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _glinfo) +: m_blender1(new ShaderBlender1(_glinfo)) +, m_blender2(new ShaderBlender2(_glinfo)) , m_legacyBlender(new ShaderLegacyBlender) , m_clamp(new ShaderClamp) , m_signExtendColorC(new ShaderSignExtendColorC) @@ -1874,44 +1876,47 @@ CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _version) , m_signExtendColorABD(new ShaderSignExtendColorABD) , m_signExtendAlphaABD(new ShaderSignExtendAlphaABD) , m_alphaTest(new ShaderAlphaTest) -, m_callDither(new ShaderCallDither(_version)) -, m_vertexHeader(new VertexShaderHeader(_version)) -, m_vertexRect(new VertexShaderRect(_version)) -, m_vertexTexturedRect(new VertexShaderTexturedRect(_version)) -, m_vertexTriangle(new VertexShaderTriangle(_version)) -, m_vertexTexturedTriangle(new VertexShaderTexturedTriangle(_version)) -, m_fragmentHeader(new FragmentShaderHeader(_version)) -, m_fragmentGlobalVariablesTex(new ShaderFragmentGlobalVariablesTex(_version)) -, m_fragmentGlobalVariablesNotex(new ShaderFragmentGlobalVariablesNotex(_version)) -, m_fragmentHeaderNoise(new ShaderFragmentHeaderNoise(_version)) -, m_fragmentHeaderWriteDepth(new ShaderFragmentHeaderWriteDepth(_version)) -, m_fragmentHeaderCalcLight(new ShaderFragmentHeaderCalcLight(_version)) -, m_fragmentHeaderMipMap(new ShaderFragmentHeaderMipMap(_version)) -, m_fragmentHeaderReadMSTex(new ShaderFragmentHeaderReadMSTex(_version)) -, m_fragmentHeaderDither(new ShaderFragmentHeaderDither(_version)) -, m_fragmentHeaderDepthCompare(new ShaderFragmentHeaderDepthCompare(_version)) -, m_fragmentHeaderReadTex(new ShaderFragmentHeaderReadTex(_version)) -, m_fragmentMain(new ShaderFragmentMain(_version)) -, m_fragmentMain2Cycle(new ShaderFragmentMain2Cycle(_version)) -, m_fragmentBlendMux(new ShaderFragmentBlendMux(_version)) -, m_fragmentReadTex0(new ShaderFragmentReadTex0(_version)) -, m_fragmentReadTex1(new ShaderFragmentReadTex1(_version)) -, m_fragmentReadTexMipmap(new ShaderFragmentReadTexMipmap(_version)) -, m_fragmentCallN64Depth(new ShaderFragmentCallN64Depth(_version)) -, m_fragmentRenderTarget(new ShaderFragmentRenderTarget(_version)) -, m_shaderNoise(new ShaderNoise(_version)) -, m_shaderDither(new ShaderDither(_version)) -, m_shaderWriteDepth(new ShaderWriteDepth(_version)) -, m_shaderMipmap(new ShaderMipmap(_version)) -, m_shaderCalcLight(new ShaderCalcLight(_version)) -, m_shaderReadtex(new ShaderReadtex(_version)) -, m_shaderN64DepthCompare(new ShaderN64DepthCompare(_version)) -, m_shaderN64DepthRender(new ShaderN64DepthRender(_version)) +, m_callDither(new ShaderCallDither(_glinfo)) +, m_vertexHeader(new VertexShaderHeader(_glinfo)) +, m_vertexRect(new VertexShaderRect(_glinfo)) +, m_vertexTexturedRect(new VertexShaderTexturedRect(_glinfo)) +, m_vertexTriangle(new VertexShaderTriangle(_glinfo)) +, m_vertexTexturedTriangle(new VertexShaderTexturedTriangle(_glinfo)) +, m_fragmentHeader(new FragmentShaderHeader(_glinfo)) +, m_fragmentGlobalVariablesTex(new ShaderFragmentGlobalVariablesTex(_glinfo)) +, m_fragmentGlobalVariablesNotex(new ShaderFragmentGlobalVariablesNotex(_glinfo)) +, m_fragmentHeaderNoise(new ShaderFragmentHeaderNoise(_glinfo)) +, m_fragmentHeaderWriteDepth(new ShaderFragmentHeaderWriteDepth(_glinfo)) +, m_fragmentHeaderCalcLight(new ShaderFragmentHeaderCalcLight(_glinfo)) +, m_fragmentHeaderMipMap(new ShaderFragmentHeaderMipMap(_glinfo)) +, m_fragmentHeaderReadMSTex(new ShaderFragmentHeaderReadMSTex(_glinfo)) +, m_fragmentHeaderDither(new ShaderFragmentHeaderDither(_glinfo)) +, m_fragmentHeaderDepthCompare(new ShaderFragmentHeaderDepthCompare(_glinfo)) +, m_fragmentHeaderReadTex(new ShaderFragmentHeaderReadTex(_glinfo)) +, m_fragmentMain(new ShaderFragmentMain(_glinfo)) +, m_fragmentMain2Cycle(new ShaderFragmentMain2Cycle(_glinfo)) +, m_fragmentBlendMux(new ShaderFragmentBlendMux(_glinfo)) +, m_fragmentReadTex0(new ShaderFragmentReadTex0(_glinfo)) +, m_fragmentReadTex1(new ShaderFragmentReadTex1(_glinfo)) +, m_fragmentReadTexMipmap(new ShaderFragmentReadTexMipmap(_glinfo)) +, m_fragmentCallN64Depth(new ShaderFragmentCallN64Depth(_glinfo)) +, m_fragmentRenderTarget(new ShaderFragmentRenderTarget(_glinfo)) +, m_shaderNoise(new ShaderNoise(_glinfo)) +, m_shaderDither(new ShaderDither(_glinfo)) +, m_shaderWriteDepth(new ShaderWriteDepth(_glinfo)) +, m_shaderMipmap(new ShaderMipmap(_glinfo)) +, m_shaderCalcLight(new ShaderCalcLight(_glinfo)) +, m_shaderReadtex(new ShaderReadtex(_glinfo)) +, m_shaderN64DepthCompare(new ShaderN64DepthCompare(_glinfo)) +, m_shaderN64DepthRender(new ShaderN64DepthRender(_glinfo)) { m_vertexShaderRect = _createVertexShader(m_vertexHeader.get(), m_vertexRect.get()); m_vertexShaderTriangle = _createVertexShader(m_vertexHeader.get(), m_vertexTriangle.get()); m_vertexShaderTexturedRect = _createVertexShader(m_vertexHeader.get(), m_vertexTexturedRect.get()); m_vertexShaderTexturedTriangle = _createVertexShader(m_vertexHeader.get(), m_vertexTexturedTriangle.get()); + if (config.generalEmulation.enableNoise != 0) + m_noiseTexture.reset(new NoiseTexture); + m_uniformFactory.reset(new CombinerProgramUniformFactory(_glinfo, m_noiseTexture.get())); } CombinerProgramBuilder::~CombinerProgramBuilder() diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.h b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.h index 1625bc07..191f5ba4 100644 --- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.h +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.h @@ -4,10 +4,16 @@ #include #include #include -#include + +namespace graphics { + class CombinerProgram; +} namespace glsl { + class NoiseTexture; + class CombinerProgramUniformFactory; + class ShaderPart { public: @@ -23,7 +29,7 @@ namespace glsl { class CombinerProgramBuilder { public: - CombinerProgramBuilder(const opengl::GLInfo & _version); + CombinerProgramBuilder(const opengl::GLInfo & _glinfo); ~CombinerProgramBuilder(); graphics::CombinerProgram * buildCombinerProgram(Combiner & _color, Combiner & _alpha, const CombinerKey & _key); @@ -77,6 +83,9 @@ namespace glsl { ShaderPartPtr m_shaderN64DepthCompare; ShaderPartPtr m_shaderN64DepthRender; + std::unique_ptr m_noiseTexture; + std::unique_ptr m_uniformFactory; + GLuint m_vertexShaderRect; GLuint m_vertexShaderTriangle; GLuint m_vertexShaderTexturedRect; diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.cpp index 91396d8b..e6782805 100644 --- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.cpp +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.cpp @@ -3,50 +3,11 @@ using namespace glsl; -/*---------------CombinerInputs-------------*/ - -bool CombinerInputs::usesTile(u32 _t) const -{ - if (_t == 0) - return (m_inputs & ((1 << TEXEL0) | (1 << TEXEL0_ALPHA))) != 0; - return (m_inputs & ((1 << TEXEL1) | (1 << TEXEL1_ALPHA))) != 0; -} - -bool CombinerInputs::usesTexture() const -{ - return (m_inputs & ((1 << TEXEL1) | (1 << TEXEL1_ALPHA) | (1 << TEXEL0) | (1 << TEXEL0_ALPHA))) != 0; -} - -bool CombinerInputs::usesLOD() const -{ - return (m_inputs & (1 << LOD_FRACTION)) != 0; -} - -bool CombinerInputs::usesShade() const -{ - return (m_inputs & ((1 << SHADE) | (1 << SHADE_ALPHA))) != 0; -} - -bool CombinerInputs::usesShadeColor() const -{ - return (m_inputs & (1 << SHADE)) != 0; -} - -bool CombinerInputs::usesHwLighting() const -{ - return (m_inputs & (1 << HW_LIGHT)) != 0; -} - -void CombinerInputs::addInput(int _input) -{ - m_inputs |= 1 << _input; -} - - -/*---------------CombinerProgramImpl-------------*/ - - -CombinerProgramImpl::CombinerProgramImpl() +CombinerProgramImpl::CombinerProgramImpl(GLuint _program, const CombinerInputs & _inputs, UniformGroups && _uniforms) +: m_bNeedUpdate(true) +, m_program(_program) +, m_inputs(_inputs) +, m_uniforms(std::move(_uniforms)) { } @@ -57,14 +18,51 @@ CombinerProgramImpl::~CombinerProgramImpl() void CombinerProgramImpl::activate() { + glUseProgram(m_program); } void CombinerProgramImpl::update(bool _force) { - + _force |= m_bNeedUpdate; + m_bNeedUpdate = false; + glUseProgram(m_program); + for (auto it = m_uniforms.begin(); it != m_uniforms.end(); ++it) + (*it)->update(_force); } CombinerKey CombinerProgramImpl::getKey() const { return CombinerKey(); } + +bool CombinerProgramImpl::usesTexture() const +{ + return m_inputs.usesTexture(); +} + +bool CombinerProgramImpl::usesTile(u32 _t) const { + return m_inputs.usesTile(_t); +} + +bool CombinerProgramImpl::usesShade() const { + return m_inputs.usesShade(); +} + +bool CombinerProgramImpl::usesLOD() const { + return m_inputs.usesLOD(); +} + +namespace graphics { + + // TODO implement + std::ostream & operator<< (std::ostream & _os, const CombinerProgram & _combiner) + { + return _os; + } + + std::istream & operator>> (std::istream & _is, CombinerProgram & _combiner) + { + return _is; + } + +} \ No newline at end of file diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.h b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.h index 43f8be86..7cf98518 100644 --- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.h +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.h @@ -1,40 +1,39 @@ #pragma once +#include +#include #include +#include "glsl_CombinerInputs.h" namespace glsl { - class CombinerInputs - { + class UniformGroup { public: - explicit CombinerInputs(int _inputs) : m_inputs(_inputs) {} - - bool usesTile(u32 _t) const; - - bool usesTexture() const; - - bool usesLOD() const; - - bool usesShade() const; - - bool usesShadeColor() const; - - bool usesHwLighting() const; - - void addInput(int _input); - - private: - int m_inputs; + virtual ~UniformGroup() {} + virtual void update(bool _force) = 0; }; + typedef std::vector< std::unique_ptr > UniformGroups; + class CombinerProgramImpl : public graphics::CombinerProgram { public: - CombinerProgramImpl(); + CombinerProgramImpl(GLuint _program, const CombinerInputs & _inputs, UniformGroups && _uniforms); ~CombinerProgramImpl(); void activate() override; void update(bool _force) override; CombinerKey getKey() const override; + + bool usesTexture() const override; + bool usesTile(u32 _t) const override; + bool usesShade() const override; + bool usesLOD() const override; + + private: + bool m_bNeedUpdate; + GLuint m_program; + CombinerInputs m_inputs; + UniformGroups m_uniforms; }; } diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp new file mode 100644 index 00000000..276c09a5 --- /dev/null +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp @@ -0,0 +1,861 @@ +#include +#include "glsl_CombinerProgramUniformFactory.h" +#include "glsl_NoiseTexture.h" + +#include +#include +#include +#include +#include +#include +#include + +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); + } + } +}; + + +/*---------------UniformGroup-------------*/ + +#define LocateUniform(A) \ + A.loc = glGetUniformLocation(_program, #A); + +class UNoiseTex : public UniformGroup +{ +public: + UNoiseTex(GLuint _program) { + LocateUniform(uTexNoise); + } + + void update(bool _force) override + { + uTexNoise.set(g_noiseTexIndex, _force); + } + +private: + iUniform uTexNoise; +}; + +class UDepthTex : public UniformGroup +{ +public: + UDepthTex(GLuint _program) { + LocateUniform(uDepthTex); + } + + void update(bool _force) override + { + uDepthTex.set(g_depthTexIndex, _force); + } + +private: + iUniform uDepthTex; +}; + +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); + LocateUniform(uMSAAScale); + } + + void update(bool _force) override + { + uMSTex0.set(g_MSTex0Index + 0, _force); + uMSTex1.set(g_MSTex0Index + 1, _force); + uMSAASamples.set(config.video.multisampling, _force); + uMSAAScale.set(1.0f / (float)config.video.multisampling, _force); + } + +private: + iUniform uMSTex0; + iUniform uMSTex1; + iUniform uMSAASamples; + fUniform uMSAAScale; +}; + +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; + 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.bLLE) { + uFogUsage.set(0, _force); + return; + } + + int nFogUsage = ((gSP.geometryMode & G_FOG) != 0) ? 1 : 0; + if (!GBI.isTextureGen()) + // F-Zero ucode seems to always use fog mode when fog is used in blender. + nFogUsage |= (gDP.otherMode.c1_m1a == 3 || gDP.otherMode.c1_m2a == 3) ? 1 : 0; + uFogUsage.set(nFogUsage, _force); + uFogScale.set((float)gSP.fog.multiplier / 256.0f, (float)gSP.fog.offset / 256.0f, _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); + int forceBlend1 = 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 + { + int forceBlend1 = 1; + + uBlendMux1.set(gDP.otherMode.c1_m1a, + gDP.otherMode.c1_m1b, + gDP.otherMode.c1_m2a, + gDP.otherMode.c1_m2b, + _force); + + int forceBlend2 = gDP.otherMode.forceBlender; + + if (forceBlend2 != 0) { + uBlendMux2.set(gDP.otherMode.c2_m1a, + gDP.otherMode.c2_m1b, + gDP.otherMode.c2_m2a, + gDP.otherMode.c2_m2b, + _force); + } + + uForceBlendCycle1.set(forceBlend1, _force); + uForceBlendCycle2.set(forceBlend2, _force); + } + +private: + i4Uniform uBlendMux1; + i4Uniform uBlendMux2; + iUniform uForceBlendCycle1; + iUniform uForceBlendCycle2; +}; + +class UDitherMode : public UniformGroup +{ +public: + UDitherMode(GLuint _program, bool _usesNoise, NoiseTexture * _noiseTexture) + : m_usesNoise(m_usesNoise) + , m_noiseTexture(_noiseTexture) + { + LocateUniform(uAlphaCompareMode); + LocateUniform(uAlphaDitherMode); + LocateUniform(uColorDitherMode); + } + ~UDitherMode() + { + m_noiseTexture = nullptr; + } + + 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 && m_noiseTexture != nullptr) + m_noiseTexture->update(); + } + +private: + iUniform uAlphaCompareMode; + iUniform uAlphaDitherMode; + iUniform uColorDitherMode; + bool m_usesNoise; + NoiseTexture * m_noiseTexture; +}; + +class UScreenScale : public UniformGroup +{ +public: + UScreenScale(GLuint _program) { + LocateUniform(uScreenScale); + } + + void update(bool _force) override + { + if (config.frameBufferEmulation.nativeResFactor == 0) + // TODO fix me + //uScreenScale.set(video().getScaleX(), video().getScaleY(), _force); + uScreenScale.set(1.0f, 1.0f, _force); + else + uScreenScale.set(float(config.frameBufferEmulation.nativeResFactor), float(config.frameBufferEmulation.nativeResFactor), _force); + } + +private: + fv2Uniform uScreenScale; +}; + +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 UTexturePersp : public UniformGroup +{ +public: + UTexturePersp(GLuint _program) { + LocateUniform(uTexturePersp); + } + + void update(bool _force) override + { + const u32 texturePersp = (RSP.bLLE || GBI.isTexturePersp()) ? gDP.otherMode.texturePersp : 1U; + uTexturePersp.set(texturePersp, _force); + } + +private: + iUniform uTexturePersp; +}; + +class UTextureFilterMode : public UniformGroup +{ +public: + UTextureFilterMode(GLuint _program) { + LocateUniform(uTextureFilterMode); + } + + void update(bool _force) override + { + uTextureFilterMode.set(gDP.otherMode.textureFilter | (gSP.objRendermode&G_OBJRM_BILERP), _force); + } + +private: + iUniform uTextureFilterMode; +}; + +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); + } + else if (gDP.otherMode.cycleType == G_CYC_COPY) { + if (gDP.otherMode.alphaCompare & G_AC_THRESHOLD) { + uEnableAlphaTest.set(1, _force); + uAlphaCvgSel.set(0, _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); + } + + uCvgXAlpha.set(gDP.otherMode.cvgXAlpha, _force); + } + +private: + iUniform uEnableAlphaTest; + iUniform uAlphaCvgSel; + iUniform uCvgXAlpha; + fUniform uAlphaTestValue; +}; + +class UDepthScale : public UniformGroup +{ +public: + UDepthScale(GLuint _program) { + LocateUniform(uDepthScale); + } + + void update(bool _force) override + { + if (RSP.bLLE) + 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(uDeltaZ); + } + + void update(bool _force) override + { + FrameBuffer * pBuffer = frameBufferList().getCurrent(); + if (pBuffer == nullptr || pBuffer->m_pDepthBuffer == nullptr) + return; + + const int nDepthEnabled = (gSP.geometryMode & G_ZBUFFER) > 0 ? 1 : 0; + uEnableDepth.set(nDepthEnabled, _force); + if (nDepthEnabled == 0) { + uEnableDepthCompare.set(0, _force); + uEnableDepthUpdate.set(0, _force); + } + else { + uEnableDepthCompare.set(gDP.otherMode.depthCompare, _force); + uEnableDepthUpdate.set(gDP.otherMode.depthUpdate, _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); + } + +private: + iUniform uEnableDepth; + iUniform uEnableDepthCompare; + iUniform uEnableDepthUpdate; + iUniform uDepthMode; + iUniform uDepthSource; + fUniform uDeltaZ; +}; + +class URenderTarget : public UniformGroup +{ +public: + URenderTarget(GLuint _program) { + LocateUniform(uRenderTarget); + } + + void update(bool _force) override + { + int renderTarget = 0; + if (gDP.colorImage.address == gDP.depthImageAddress && + (config.generalEmulation.hacks & hack_ZeldaMM) == 0 + ) { + renderTarget = gDP.otherMode.depthCompare + 1; + } + uRenderTarget.set(renderTarget, _force); + } + +private: + iUniform uRenderTarget; +}; + +class UScreenCoordsScale : public UniformGroup +{ +public: + UScreenCoordsScale(GLuint _program) { + LocateUniform(uScreenCoordsScale); + } + + void update(bool _force) override + { + FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent(); + const float scaleX = pCurrentBuffer != nullptr ? 1.0f / pCurrentBuffer->m_width : VI.rwidth; + const float scaleY = pCurrentBuffer != nullptr ? 1.0f / pCurrentBuffer->m_height : VI.rheight; + 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(gDP.convert.k4*0.0039215689f, _force); + uK5.set(gDP.convert.k5*0.0039215689f, _force); + } + +private: + fv4Uniform uFogColor; + fv4Uniform uCenterColor; + fv4Uniform uScaleColor; + fv4Uniform uBlendColor; + fv4Uniform uEnvColor; + fv4Uniform uPrimColor; + fUniform uPrimLod; + fUniform uK4; + fUniform uK5; +}; + +class UTextureSize : public UniformGroup +{ +public: + UTextureSize(GLuint _program, bool _useT0, bool _useT1) + : m_useT0(m_useT0) + , m_useT1(m_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]->realWidth, (float)cache.current[0]->realHeight, _force); + if (m_useT1 && cache.current[1] != NULL) + uTextureSize[1].set((float)cache.current[1]->realWidth, (float)cache.current[1]->realHeight, _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(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; + + if (gSP.textureTile[t] != NULL) { + if (gSP.textureTile[t]->textureMode == TEXTUREMODE_BGIMAGE || gSP.textureTile[t]->textureMode == TEXTUREMODE_FRAMEBUFFER_BG) + uTexOffset[t].set(0.0f, 0.0f, _force); + else { + float fuls = gSP.textureTile[t]->fuls; + float fult = gSP.textureTile[t]->fult; + FrameBuffer * pBuffer = gSP.textureTile[t]->frameBuffer; + if (pBuffer != NULL) { + if (gSP.textureTile[t]->masks > 0 && gSP.textureTile[t]->clamps == 0) + fuls = float(gSP.textureTile[t]->uls % (1 << gSP.textureTile[t]->masks)); + if (gSP.textureTile[t]->maskt > 0 && gSP.textureTile[t]->clampt == 0) + fult = float(gSP.textureTile[t]->ult % (1 << gSP.textureTile[t]->maskt)); + } + uTexOffset[t].set(fuls, fult, _force); + } + } + + if (cache.current[t] != NULL) { + f32 shiftScaleS = 1.0f; + f32 shiftScaleT = 1.0f; + getTextureShiftScale(t, cache, shiftScaleS, shiftScaleT); + uCacheShiftScale[t].set(shiftScaleS, shiftScaleT, _force); + uCacheScale[t].set(cache.current[t]->scaleS, cache.current[t]->scaleT, _force); + uCacheOffset[t].set(cache.current[t]->offsetS, cache.current[t]->offsetT, _force); + nFB[t] = cache.current[t]->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 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 (s32 i = 0; i <= gSP.numLights; ++i) { + uLightDirection[i].set(&gSP.lights[i].ix, _force); + uLightColor[i].set(&gSP.lights[i].r, _force); + } + } + +private: + fv3Uniform uLightDirection[8]; + fv3Uniform uLightColor[8]; +}; + + +/*---------------CombinerProgramUniformFactory-------------*/ + +void CombinerProgramUniformFactory::buildUniforms(GLuint _program, + const CombinerInputs & _inputs, + bool _rect, + UniformGroups & _uniforms) +{ + if (config.generalEmulation.enableNoise != 0) + _uniforms.emplace_back(new UNoiseTex(_program)); + + if (!m_glInfo.isGLES2) + _uniforms.emplace_back(new UDepthTex(_program)); + + if (_inputs.usesTexture()) + _uniforms.emplace_back(new UTextures(_program)); + + if (config.video.multisampling != 0) + _uniforms.emplace_back(new UMSAATextures(_program)); + + if (_inputs.usesTexture()) + _uniforms.emplace_back(new UFrameBufferInfo(_program)); + + _uniforms.emplace_back(new UFog(_program)); + + if (config.generalEmulation.enableLegacyBlending == 0) { + switch (gDP.otherMode.cycleType) { + case G_CYC_1CYCLE: + _uniforms.emplace_back(new UBlendMode1Cycle(_program)); + break; + case G_CYC_2CYCLE: + _uniforms.emplace_back(new UBlendMode2Cycle(_program)); + break; + } + } + + _uniforms.emplace_back(new UDitherMode(_program, _inputs.usesNoise(), m_noiseTexture)); + + _uniforms.emplace_back(new UScreenScale(_program)); + + if (_inputs.usesLOD()) { + _uniforms.emplace_back(new UMipmap1(_program)); + if (config.generalEmulation.enableLOD != 0) + _uniforms.emplace_back(new UMipmap2(_program)); + } + + _uniforms.emplace_back(new UTexturePersp(_program)); + + if (config.texture.bilinearMode == BILINEAR_3POINT) + _uniforms.emplace_back(new UTextureFilterMode(_program)); + + _uniforms.emplace_back(new UAlphaTestInfo(_program)); + + if (!m_glInfo.isGLES2) + _uniforms.emplace_back(new UDepthScale(_program)); + + if (m_glInfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) + _uniforms.emplace_back(new UDepthInfo(_program)); + + if (config.generalEmulation.enableFragmentDepthWrite != 0) + _uniforms.emplace_back(new URenderTarget(_program)); + + _uniforms.emplace_back(new UScreenCoordsScale(_program)); + + _uniforms.emplace_back(new UColors(_program)); + + if (_inputs.usesTexture()) { + _uniforms.emplace_back(new UTextureSize(_program, _inputs.usesTile(0), _inputs.usesTile(1))); + if (!_rect) + _uniforms.emplace_back(new UTextureParams(_program, _inputs.usesTile(0), _inputs.usesTile(1))); + } + + if (_inputs.usesHwLighting()) + _uniforms.emplace_back(new ULights(_program)); +} + +CombinerProgramUniformFactory::CombinerProgramUniformFactory(const opengl::GLInfo & _glInfo, + NoiseTexture * _noiseTexture) +: m_glInfo(_glInfo) +, m_noiseTexture(_noiseTexture) +{ +} + +CombinerProgramUniformFactory::~CombinerProgramUniformFactory() +{ + m_noiseTexture = nullptr; +} + +} diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.h b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.h new file mode 100644 index 00000000..668e5776 --- /dev/null +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.h @@ -0,0 +1,22 @@ +#pragma once +#include +#include "glsl_CombinerProgramImpl.h" + +namespace glsl { + + class NoiseTexture; + + class CombinerProgramUniformFactory + { + public: + CombinerProgramUniformFactory(const opengl::GLInfo & _glInfo, NoiseTexture * _noiseTexture); + ~CombinerProgramUniformFactory(); + + void buildUniforms(GLuint _program, const CombinerInputs & _inputs, bool _rect, UniformGroups & _uniforms); + + private: + const opengl::GLInfo & m_glInfo; + NoiseTexture * m_noiseTexture; + }; + +} diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.cpp new file mode 100644 index 00000000..32e82da2 --- /dev/null +++ b/src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.cpp @@ -0,0 +1,116 @@ +#include "glsl_NoiseTexture.h" +#include +#include +#include +#include +#include +#include + +namespace glsl { + + struct PBOBinder { + PBOBinder(GLenum _target, GLuint _PBO) : m_target(_target) + { + glBindBuffer(m_target, _PBO); + } + ~PBOBinder() { + glBindBuffer(m_target, 0); + } + GLenum m_target; + }; + + + NoiseTexture::NoiseTexture() + : m_pTexture(nullptr) + , m_PBO(0) + , m_DList(0) + { + init(); + } + + NoiseTexture::~NoiseTexture() + { + destroy(); + } + + void NoiseTexture::init() + { + if (config.generalEmulation.enableNoise == 0) + return; + m_pTexture = textureCache().addFrameBufferTexture(false); + m_pTexture->format = G_IM_FMT_RGBA; + m_pTexture->clampS = 1; + m_pTexture->clampT = 1; + m_pTexture->frameBufferTexture = CachedTexture::fbOneSample; + m_pTexture->maskS = 0; + m_pTexture->maskT = 0; + m_pTexture->mirrorS = 0; + m_pTexture->mirrorT = 0; + m_pTexture->realWidth = 640; + m_pTexture->realHeight = 580; + m_pTexture->textureBytes = m_pTexture->realWidth * m_pTexture->realHeight; + textureCache().addFrameBufferTextureSize(m_pTexture->textureBytes); + + { + graphics::Context::InitTextureParams params; + params.handle = graphics::ObjectHandle(m_pTexture->glName); + params.width = m_pTexture->realWidth; + params.height = m_pTexture->realHeight; + params.internalFormat = graphics::internalcolor::RED; + params.format = graphics::color::RED; + params.dataType = graphics::datatype::UNSIGNED_BYTE; + gfxContext.init2DTexture(params); + } + { + graphics::Context::TexParameters params; + params.handle = graphics::ObjectHandle(m_pTexture->glName); + params.target = graphics::target::TEXTURE_2D; + params.textureUnitIndex = 0; + params.minFilter = graphics::textureParameters::FILTER_NEAREST; + params.magFilter = graphics::textureParameters::FILTER_NEAREST; + gfxContext.setTextureParameters(params); + } + + // TODO rewrite in GL independent way + // Generate Pixel Buffer Object. Initialize it with max buffer size. + glGenBuffers(1, &m_PBO); + PBOBinder binder(GL_PIXEL_UNPACK_BUFFER, m_PBO); + glBufferData(GL_PIXEL_UNPACK_BUFFER, 640 * 580, nullptr, GL_DYNAMIC_DRAW); + } + + void NoiseTexture::destroy() + { + if (m_pTexture != nullptr) { + textureCache().removeFrameBufferTexture(m_pTexture); + m_pTexture = nullptr; + } + glDeleteBuffers(1, &m_PBO); + m_PBO = 0; + } + + void NoiseTexture::update() + { + if (m_PBO == 0 || m_pTexture == nullptr) + return; + if (m_DList == video().getBuffersSwapCount() || config.generalEmulation.enableNoise == 0) + return; + const u32 dataSize = VI.width*VI.height; + if (dataSize == 0) + return; + PBOBinder binder(GL_PIXEL_UNPACK_BUFFER, m_PBO); + GLubyte* ptr = (GLubyte*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, dataSize, GL_MAP_WRITE_BIT); + if (ptr == nullptr) + return; + for (u32 y = 0; y < VI.height; ++y) { + for (u32 x = 0; x < VI.width; ++x) + ptr[x + y*VI.width] = rand() & 0xFF; + } + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); // release the mapped buffer + + glActiveTexture(GL_TEXTURE0 + g_noiseTexIndex); + glBindTexture(GL_TEXTURE_2D, m_pTexture->glName); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VI.width, VI.height, GL_RED, GL_UNSIGNED_BYTE, 0); + m_DList = video().getBuffersSwapCount(); + } + +} diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.h b/src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.h new file mode 100644 index 00000000..1df3ce0b --- /dev/null +++ b/src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include + +struct CachedTexture; + +namespace glsl { + + class NoiseTexture + { + public: + NoiseTexture(); + ~NoiseTexture(); + + void init(); + void destroy(); + void update(); + + private: + CachedTexture * m_pTexture; + GLuint m_PBO; + u32 m_DList; + }; +} diff --git a/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp b/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp index eb95b6b6..5c9140df 100644 --- a/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp +++ b/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp @@ -1,6 +1,7 @@ #include #include #include "opengl_ContextImpl.h" +#include "GLSL/glsl_CombinerProgramBuilder.h" using namespace opengl; @@ -35,6 +36,8 @@ void ContextImpl::init() m_initRenderbuffer.reset(bufferObjectFactory.getInitRenderbuffer()); m_addFramebufferRenderTarget.reset(bufferObjectFactory.getAddFramebufferRenderTarget()); } + + m_combinerProgramBuilder.reset(new glsl::CombinerProgramBuilder(m_glInfo)); } void ContextImpl::destroy() @@ -48,6 +51,9 @@ void ContextImpl::destroy() m_createRenderbuffer.reset(nullptr); m_initRenderbuffer.reset(nullptr); m_addFramebufferRenderTarget.reset(nullptr); + + + m_combinerProgramBuilder.reset(nullptr); } graphics::ObjectHandle ContextImpl::createTexture(graphics::Parameter _target) @@ -103,5 +109,5 @@ void ContextImpl::addFrameBufferRenderTarget(const graphics::Context::FrameBuffe graphics::CombinerProgram * ContextImpl::createCombinerProgram(Combiner & _color, Combiner & _alpha, const CombinerKey & _key) { - return nullptr; + return m_combinerProgramBuilder->buildCombinerProgram(_color, _alpha, _key); } diff --git a/src/Graphics/OpenGLContext/opengl_ContextImpl.h b/src/Graphics/OpenGLContext/opengl_ContextImpl.h index 48e2693e..7c7bf1c6 100644 --- a/src/Graphics/OpenGLContext/opengl_ContextImpl.h +++ b/src/Graphics/OpenGLContext/opengl_ContextImpl.h @@ -6,6 +6,10 @@ #include "opengl_GLInfo.h" #include "opengl_CachedFunctions.h" +namespace glsl { + class CombinerProgramBuilder; +} + namespace opengl { class ContextImpl : public graphics::ContextImpl @@ -49,6 +53,7 @@ namespace opengl { std::unique_ptr m_initRenderbuffer; std::unique_ptr m_addFramebufferRenderTarget; + std::unique_ptr m_combinerProgramBuilder; GLInfo m_glInfo; };