From b0e4de824046f77b9de378ea5d6f3de4e53b22a4 Mon Sep 17 00:00:00 2001 From: Xottab_DUTY Date: Sat, 30 Jul 2022 22:07:39 +0500 Subject: [PATCH] OpenGL: use program pipelines or monolithic shader programs depending on GL_ARB_separate_shader_programs support. This is first step on removing dependency on this extension. Dependency on GLSL 4.10 is still there. --- res/gamedata/shaders/gl/clouds.s | 4 +- src/Layers/xrRender/Blender_Recorder.cpp | 70 ++++++------ src/Layers/xrRender/Blender_Recorder.h | 10 +- src/Layers/xrRender/Blender_Recorder_R2.cpp | 35 +++--- src/Layers/xrRender/R_Backend.h | 72 +++++++----- src/Layers/xrRender/R_Backend_Runtime.h | 19 +++- src/Layers/xrRender/ResourceManager.h | 13 +++ src/Layers/xrRender/SH_Atomic.cpp | 43 ++++++- src/Layers/xrRender/SH_Atomic.h | 15 +++ src/Layers/xrRender/Shader.cpp | 28 ++--- src/Layers/xrRender/Shader.h | 3 + src/Layers/xrRender/ShaderResourceTraits.h | 55 ++++++++- .../xrRender/blenders/BlenderDefault.cpp | 15 +-- .../blenders/Blender_Editor_Selection.cpp | 3 +- .../xrRender/blenders/Blender_Editor_Wire.cpp | 3 +- .../xrRender/blenders/Blender_Screen_SET.cpp | 12 +- .../xrRender/blenders/Blender_Vertex.cpp | 15 +-- .../xrRender/blenders/Blender_Vertex_aref.cpp | 15 +-- .../blenders/Blender_default_aref.cpp | 15 +-- src/Layers/xrRender/dxEnvironmentRender.cpp | 107 ++++++++---------- src/Layers/xrRender/dxEnvironmentRender.h | 22 ++-- src/Layers/xrRender/dxFontRender.cpp | 5 +- src/Layers/xrRender/dxUIRender.cpp | 4 +- src/Layers/xrRender/dxUISequenceVideoItem.cpp | 8 +- src/Layers/xrRender/r_constants.cpp | 15 ++- src/Layers/xrRender/r_constants.h | 29 ++++- src/Layers/xrRenderDX10/dx10r_constants.cpp | 10 +- src/Layers/xrRenderGL/Blender_Recorder_GL.cpp | 27 +++-- src/Layers/xrRenderGL/glHW.cpp | 6 +- src/Layers/xrRenderGL/glHW.h | 2 +- src/Layers/xrRenderGL/glR_Backend_Runtime.h | 30 ++++- .../glResourceManager_Resources.cpp | 85 ++++++++++++++ src/Layers/xrRenderGL/glr_constants.cpp | 17 ++- src/Layers/xrRenderGL/glr_constants_cache.h | 72 ++++++++++-- src/Layers/xrRenderPC_GL/r2_test_hw.cpp | 6 - src/Layers/xrRenderPC_GL/rgl_shaders.cpp | 18 +-- src/Layers/xrRenderPC_GL/stdafx.h | 1 - src/Layers/xrRenderPC_R1/FStaticRender.cpp | 6 + src/Layers/xrRenderPC_R1/FStaticRender.h | 8 ++ .../FStaticRender_RenderTarget.cpp | 3 +- .../xrRenderPC_R1/FStaticRender_Types.h | 4 + src/Layers/xrRenderPC_R1/LightShadows.cpp | 1 - src/Layers/xrRender_R2/r2.cpp | 4 + src/Layers/xrRender_R2/r2.h | 4 + src/xrGame/GamePersistent.cpp | 9 +- src/xrGame/GamePersistent.h | 2 - 46 files changed, 619 insertions(+), 331 deletions(-) diff --git a/res/gamedata/shaders/gl/clouds.s b/res/gamedata/shaders/gl/clouds.s index ce7acd0a063..99029e3869e 100644 --- a/res/gamedata/shaders/gl/clouds.s +++ b/res/gamedata/shaders/gl/clouds.s @@ -6,7 +6,7 @@ function normal (shader, t_base, t_second, t_detail) : zb (false,false) : sorting (3, true) : blend (true, blend.srcalpha,blend.invsrcalpha) - shader:sampler ("s_clouds0") :texture ("$user$clouds0") : wrap() : f_anisotropic() - shader:sampler ("s_clouds1") :texture ("$user$clouds1") : wrap() : f_anisotropic() + shader:sampler ("s_clouds0") :texture ("$null") : wrap() : f_anisotropic() + shader:sampler ("s_clouds1") :texture ("$null") : wrap() : f_anisotropic() shader:sampler ("s_tonemap") :texture ("$user$tonemap") end diff --git a/src/Layers/xrRender/Blender_Recorder.cpp b/src/Layers/xrRender/Blender_Recorder.cpp index f63619b778e..67ae3a5bd40 100644 --- a/src/Layers/xrRender/Blender_Recorder.cpp +++ b/src/Layers/xrRender/Blender_Recorder.cpp @@ -164,20 +164,12 @@ void CBlender_Compile::PassBegin() passMatrices.clear(); passConstants.clear(); ctable.clear(); + dwStage = 0; // Set default pipeline state PassSET_ZB(true, true); PassSET_Blend(false, D3DBLEND_ONE, D3DBLEND_ZERO, false, 0); PassSET_LightFog(false, false); - - // Set default shaders - xr_strcpy(pass_ps, "null"); - xr_strcpy(pass_vs, "null"); - xr_strcpy(pass_gs, "null"); - xr_strcpy(pass_hs, "null"); - xr_strcpy(pass_ds, "null"); - xr_strcpy(pass_cs, "null"); - dwStage = 0; } void CBlender_Compile::PassEnd() @@ -187,28 +179,16 @@ void CBlender_Compile::PassEnd() RS.SetTSS(Stage(), D3DTSS_ALPHAOP, D3DTOP_DISABLE); // Create pass - if (!dest.vs) + if (!dest.vs) // XXX: remove { dest.vs = RImplementation.Resources->_CreateVS("null"); } - if (!dest.ps) + if (!dest.ps) // XXX: remove { dest.ps = RImplementation.Resources->_CreatePS("null"); } -#if defined(USE_DX11) || defined(USE_OGL) - dest.gs = RImplementation.Resources->_CreateGS(pass_gs); - ctable.merge(&dest.gs->constants); -#ifdef USE_DX11 - dest.hs = RImplementation.Resources->_CreateHS(pass_hs); - ctable.merge(&dest.hs->constants); - dest.ds = RImplementation.Resources->_CreateDS(pass_ds); - ctable.merge(&dest.ds->constants); - dest.cs = RImplementation.Resources->_CreateCS(pass_cs); - ctable.merge(&dest.cs->constants); -#endif // USE_DX11 -#endif // !USE_DX9 SetMapping(); dest.state = RImplementation.Resources->_CreateState(RS.GetContainer()); dest.constants = RImplementation.Resources->_CreateConstantTable(ctable); @@ -222,20 +202,38 @@ void CBlender_Compile::PassEnd() SH->passes.push_back(_pass_); } -void CBlender_Compile::PassSET_PS(LPCSTR name) -{ - xr_strcpy(pass_ps, name); - xr_strlwr(pass_ps); - dest.ps = RImplementation.Resources->_CreatePS(pass_ps); - ctable.merge(&dest.ps->constants); -} - -void CBlender_Compile::PassSET_VS(LPCSTR name) +void CBlender_Compile::PassSET_Shaders(pcstr _vs, pcstr _ps, pcstr _gs /*= nullptr*/, pcstr _hs /*= nullptr*/, pcstr _ds /*= nullptr*/) { - xr_strcpy(pass_vs, name); - xr_strlwr(pass_vs); - dest.vs = RImplementation.Resources->_CreateVS(pass_vs); - ctable.merge(&dest.vs->constants); +#if defined(USE_OGL) + dest.pp = RImplementation.Resources->_CreatePP(_vs, _ps, _gs, _hs, _ds); + if (HW.SeparateShaderObjectsSupported || !dest.pp->pp) +#endif + { + dest.ps = RImplementation.Resources->_CreatePS(_ps); + ctable.merge(&dest.ps->constants); + u32 flags = 0; +#if defined(USE_DX11) + if (dest.ps->constants.dx9compatibility) + flags |= D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY; +#endif + dest.vs = RImplementation.Resources->_CreateVS(_vs, flags); + ctable.merge(&dest.vs->constants); +#if defined(USE_DX11) || defined(USE_OGL) + dest.gs = RImplementation.Resources->_CreateGS(_gs); + ctable.merge(&dest.gs->constants); +# ifdef USE_DX11 + dest.hs = RImplementation.Resources->_CreateHS(_hs); + dest.ds = RImplementation.Resources->_CreateDS(_ds); + ctable.merge(&dest.hs->constants); + ctable.merge(&dest.ds->constants); + dest.cs = RImplementation.Resources->_CreateCS("null"); +# endif +#endif // !USE_DX9 + } +#if defined(USE_OGL) + RImplementation.Resources->_LinkPP(dest); + ctable.merge(&dest.pp->constants); +#endif } void CBlender_Compile::PassSET_ZB(BOOL bZTest, BOOL bZWrite, BOOL bInvertZTest) diff --git a/src/Layers/xrRender/Blender_Recorder.h b/src/Layers/xrRender/Blender_Recorder.h index 399eb150cee..893c9bb4651 100644 --- a/src/Layers/xrRender/Blender_Recorder.h +++ b/src/Layers/xrRender/Blender_Recorder.h @@ -53,13 +53,6 @@ class CBlender_Compile SConstantList passConstants; u32 dwStage; - string128 pass_vs; - string128 pass_ps; - string128 pass_gs; - string128 pass_hs; - string128 pass_ds; - string128 pass_cs; - private: inline u32 BC(BOOL v) const { return v ? 1 : 0; } void SetupSampler(u32 stage, pcstr sampler); @@ -99,8 +92,7 @@ class CBlender_Compile PassSET_Blend(TRUE, D3DBLEND_DESTCOLOR, D3DBLEND_SRCCOLOR, bAref, ref); } void PassSET_LightFog(BOOL bLight, BOOL bFog); - void PassSET_PS(LPCSTR name); - void PassSET_VS(LPCSTR name); + void PassSET_Shaders(pcstr _vs, pcstr _ps, pcstr _gs = "null", pcstr _hs = "null", pcstr _ds = "null"); void PassEnd(); void StageBegin(); diff --git a/src/Layers/xrRender/Blender_Recorder_R2.cpp b/src/Layers/xrRender/Blender_Recorder_R2.cpp index a932e52020b..23335bf3a21 100644 --- a/src/Layers/xrRender/Blender_Recorder_R2.cpp +++ b/src/Layers/xrRender/Blender_Recorder_R2.cpp @@ -23,26 +23,33 @@ void CBlender_Compile::r_Pass(LPCSTR _vs, LPCSTR _ps, bool bFog, BOOL bZtest, BO PassSET_LightFog(FALSE, bFog); // Create shaders - SPS* ps = RImplementation.Resources->_CreatePS(_ps); - u32 flags = 0; +#if defined(USE_OGL) + dest.pp = RImplementation.Resources->_CreatePP(_vs, _ps, "null", "null", "null"); + if (HW.SeparateShaderObjectsSupported || !dest.pp->pp) +#endif + { + dest.ps = RImplementation.Resources->_CreatePS(_ps); + ctable.merge(&dest.ps->constants); + u32 flags = 0; #if defined(USE_DX11) - if (ps->constants.dx9compatibility) - flags |= D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY; + if (dest.ps->constants.dx9compatibility) + flags |= D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY; #endif - SVS* vs = RImplementation.Resources->_CreateVS(_vs, flags); - dest.ps = ps; - dest.vs = vs; + dest.vs = RImplementation.Resources->_CreateVS(_vs, flags); + ctable.merge(&dest.vs->constants); #if defined(USE_DX11) || defined(USE_OGL) - SGS* gs = RImplementation.Resources->_CreateGS("null"); - dest.gs = gs; + dest.gs = RImplementation.Resources->_CreateGS("null"); # ifdef USE_DX11 - dest.hs = RImplementation.Resources->_CreateHS("null"); - dest.ds = RImplementation.Resources->_CreateDS("null"); - dest.cs = RImplementation.Resources->_CreateCS("null"); + dest.hs = RImplementation.Resources->_CreateHS("null"); + dest.ds = RImplementation.Resources->_CreateDS("null"); + dest.cs = RImplementation.Resources->_CreateCS("null"); # endif #endif // !USE_DX9 - ctable.merge(&ps->constants); - ctable.merge(&vs->constants); + } +#if defined(USE_OGL) + RImplementation.Resources->_LinkPP(dest); + ctable.merge(&dest.pp->constants); +#endif // Last Stage - disable if (0 == xr_stricmp(_ps, "null")) diff --git a/src/Layers/xrRender/R_Backend.h b/src/Layers/xrRender/R_Backend.h index 29dd1749595..b8757cd7376 100644 --- a/src/Layers/xrRender/R_Backend.h +++ b/src/Layers/xrRender/R_Backend.h @@ -134,6 +134,7 @@ class ECORE_API CBackend GLuint ps; GLuint vs; GLuint gs; + GLuint pp; #else # error No graphics API selected or enabled! #endif @@ -149,6 +150,9 @@ class ECORE_API CBackend LPCSTR cs_name; #endif // USE_DX11 #endif // !USE_DX9 +# ifdef USE_OGL + pcstr pp_name; +# endif #endif // DEBUG u32 stencil_enable; @@ -202,6 +206,7 @@ class ECORE_API CBackend u32 calls; u32 vs; u32 ps; + u32 pp; #ifdef DEBUG u32 decl; u32 vb; @@ -344,6 +349,7 @@ class ECORE_API CBackend ICF void set_Format(SDeclaration* _decl); +private: #if defined(USE_DX9) || defined(USE_DX11) ICF void set_PS(ID3DPixelShader* _ps, LPCSTR _n = nullptr); #elif defined(USE_OGL) @@ -365,29 +371,18 @@ class ECORE_API CBackend ICF void set_DS(ID3D11DomainShader* _ds, LPCSTR _n = nullptr); ICF void set_DS(ref_ds& _ds) { set_DS(_ds->sh, _ds->cName.c_str()); } - - ICF void set_CS(ID3D11ComputeShader* _cs, LPCSTR _n = nullptr); - ICF void set_CS(ref_cs& _cs) { set_CS(_cs->sh, _cs->cName.c_str()); } # elif defined(USE_OGL) ICF void set_GS(GLuint _gs, LPCSTR _n = 0); + + ICF void set_PP(GLuint _pp, pcstr _n = nullptr); + ICF void set_PP(ref_pp& _pp) { set_PP(_pp->pp, _pp->cName.c_str()); } # endif #endif // USE_DX9 - -#if defined(USE_DX9) || defined(USE_OGL) - ICF bool is_TessEnabled() { return false; } -#elif defined(USE_DX11) - ICF bool is_TessEnabled(); -#else -# error No graphics API selected or enabled! -#endif - ICF void set_VS(ref_vs& _vs); #if defined(USE_DX11) ICF void set_VS(SVS* _vs); - -protected: // In DX11+ we need input shader signature which is stored in ref_vs #endif #if defined(USE_DX9) || defined(USE_DX11) @@ -398,8 +393,19 @@ class ECORE_API CBackend # error No graphics API selected or enabled! #endif +public: #if defined(USE_DX11) + ICF void set_CS(ID3D11ComputeShader* _cs, LPCSTR _n = nullptr); + ICF void set_CS(ref_cs& _cs) { set_CS(_cs->sh, _cs->cName.c_str()); } +#endif + public: +#if defined(USE_DX9) || defined(USE_OGL) + ICF bool is_TessEnabled() { return false; } +#elif defined(USE_DX11) + ICF bool is_TessEnabled(); +#else +# error No graphics API selected or enabled! #endif ICF void set_Vertices(VertexBufferHandle _vb, u32 _vb_stride); @@ -442,45 +448,59 @@ class ECORE_API CBackend template ICF void set_c(R_constant* C, Args&&... args) { - if (C) - constants.set(C, std::forward(args)...); + if (!C) + return; +#ifdef USE_OGL + if (!HW.SeparateShaderObjectsSupported) + VERIFY(C->pp.program == pp); +#endif + constants.set(C, std::forward(args)...); } template ICF void set_ca(R_constant* C, Args&&... args) { - if (C) - constants.seta(C, std::forward(args)...); + if (!C) + return; +#ifdef USE_OGL + if (!HW.SeparateShaderObjectsSupported) + VERIFY(C->pp.program == pp); +#endif + constants.seta(C, std::forward(args)...); } // constants - raw string (slow) template ICF void set_c(cpcstr name, Args&&... args) { - if (ctable) - set_c(&*ctable->get(name), std::forward(args)...); + if (!ctable) + return; + set_c(&*ctable->get(name), std::forward(args)...); } template ICF void set_ca(cpcstr name, Args&&... args) { - if (ctable) - set_ca(&*ctable->get(name), std::forward(args)...); + if (!ctable) + return; + set_ca(&*ctable->get(name), std::forward(args)...); } // constants - shared_str (average) template ICF void set_c(const shared_str& name, Args&& ... args) { - if (ctable) - set_c(&*ctable->get(name), std::forward(args)...); + if (!ctable) + return; + set_c(&*ctable->get(name), std::forward(args)...); } template ICF void set_ca(const shared_str& name, Args&& ... args) { - if (ctable) - set_ca(&*ctable->get(name), std::forward(args)...); + if (!ctable) + return; + set_ca(&*ctable->get(name), std::forward(args)...); } // Rendering diff --git a/src/Layers/xrRender/R_Backend_Runtime.h b/src/Layers/xrRender/R_Backend_Runtime.h index a65c47240a9..0e6438cbc96 100644 --- a/src/Layers/xrRender/R_Backend_Runtime.h +++ b/src/Layers/xrRender/R_Backend_Runtime.h @@ -125,14 +125,21 @@ IC void CBackend::set_Matrices(SMatrixList* _M) IC void CBackend::set_Pass(SPass* P) { set_States(P->state); - set_PS(P->ps); - set_VS(P->vs); +#ifdef USE_OGL + if (P->pp) + set_PP(P->pp); + else +#endif + { + set_PS(P->ps); + set_VS(P->vs); #ifdef USE_DX11 - set_GS(P->gs); - set_HS(P->hs); - set_DS(P->ds); - set_CS(P->cs); + set_GS(P->gs); + set_HS(P->hs); + set_DS(P->ds); + set_CS(P->cs); #endif + } set_Constants(P->constants); set_Textures(P->T); #ifdef _EDITOR diff --git a/src/Layers/xrRender/ResourceManager.h b/src/Layers/xrRender/ResourceManager.h index 2a7371d9038..05b01c7e2a9 100644 --- a/src/Layers/xrRender/ResourceManager.h +++ b/src/Layers/xrRender/ResourceManager.h @@ -47,6 +47,9 @@ class ECORE_API CResourceManager using map_DS = xr_map; using map_CS = xr_map; #endif +#if defined(USE_OGL) + using map_PP = xr_map; +#endif using map_PS = xr_map; using map_TD = xr_map; @@ -71,6 +74,9 @@ class ECORE_API CResourceManager map_HS m_hs; map_CS m_cs; #endif +#if defined(USE_OGL) + map_PP m_pp; +#endif map_TD m_td; @@ -158,6 +164,13 @@ class ECORE_API CResourceManager // DX10 cut CRTC* _CreateRTC (LPCSTR Name, u32 size, D3DFORMAT f); // DX10 cut void _DeleteRTC (const CRTC* RT ); + +#if defined(USE_OGL) + SPP* _CreatePP(pcstr vs, pcstr ps, pcstr gs, pcstr hs, pcstr ds); + bool _LinkPP(SPass& pass); + void _DeletePP(const SPP* p); +#endif + #if defined(USE_DX11) || defined(USE_OGL) SGS* _CreateGS(LPCSTR Name); void _DeleteGS(const SGS* GS); diff --git a/src/Layers/xrRender/SH_Atomic.cpp b/src/Layers/xrRender/SH_Atomic.cpp index 65d17ecc8de..a79e725716f 100644 --- a/src/Layers/xrRender/SH_Atomic.cpp +++ b/src/Layers/xrRender/SH_Atomic.cpp @@ -47,7 +47,10 @@ SVS::~SVS() #if defined(USE_DX9) || defined(USE_DX11) _RELEASE(sh); #elif defined(USE_OGL) - CHK_GL(glDeleteProgram(sh)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glDeleteProgram(sh)); + else + CHK_GL(glDeleteShader(sh)); #else # error No graphics API selected or enabled! #endif @@ -60,7 +63,10 @@ SPS::~SPS() #if defined(USE_DX9) || defined(USE_DX11) _RELEASE(sh); #elif defined(USE_OGL) - CHK_GL(glDeleteProgram(sh)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glDeleteProgram(sh)); + else + CHK_GL(glDeleteShader(sh)); #else # error No graphics API selected or enabled! #endif @@ -76,7 +82,10 @@ SGS::~SGS() # if defined(USE_DX11) _RELEASE(sh); # elif defined(USE_OGL) - CHK_GL(glDeleteProgram(sh)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glDeleteProgram(sh)); + else + CHK_GL(glDeleteShader(sh)); # else # error No graphics API selected or enabled! # endif @@ -89,7 +98,10 @@ SHS::~SHS() # if defined(USE_DX11) _RELEASE(sh); # elif defined(USE_OGL) - CHK_GL(glDeleteProgram(sh)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glDeleteProgram(sh)); + else + CHK_GL(glDeleteShader(sh)); # else # error No graphics API selected or enabled! # endif @@ -102,7 +114,10 @@ SDS::~SDS() # if defined(USE_DX11) _RELEASE(sh); # elif defined(USE_OGL) - CHK_GL(glDeleteProgram(sh)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glDeleteProgram(sh)); + else + CHK_GL(glDeleteShader(sh)); # endif RImplementation.Resources->_DeleteDS(this); @@ -113,7 +128,10 @@ SCS::~SCS() # if defined(USE_DX11) _RELEASE(sh); # elif defined(USE_OGL) - CHK_GL(glDeleteProgram(sh)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glDeleteProgram(sh)); + else + CHK_GL(glDeleteShader(sh)); # else # error No graphics API selected or enabled! # endif @@ -122,6 +140,19 @@ SCS::~SCS() } #endif // USE_DX11 || USE_OGL +#if defined(USE_OGL) +SPP::~SPP() +{ + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glDeleteProgramPipelines(1, &pp)); + else + CHK_GL(glDeleteProgram(pp)); + + RImplementation.Resources->_DeletePP(this); +} +#endif // USE_OGL + + #if defined(USE_DX11) /////////////////////////////////////////////////////////////////////// // SInputSignature diff --git a/src/Layers/xrRender/SH_Atomic.h b/src/Layers/xrRender/SH_Atomic.h index ded249ed162..3165751065a 100644 --- a/src/Layers/xrRender/SH_Atomic.h +++ b/src/Layers/xrRender/SH_Atomic.h @@ -119,6 +119,21 @@ typedef resptr_core> ref_cs; #endif // USE_DX11 || USE_OGL +#if defined(USE_OGL) +struct ECORE_API SPP : public xr_resource_named +{ + // Program pipeline object + // or shader program if ARB_separate_shader_objects is unavailabe + GLuint pp{}; + R_constant_table constants; + + SPP() = default; + SPP(GLuint _pp) : pp(_pp) {} + ~SPP(); +}; +typedef resptr_core> ref_pp; +#endif // USE_OGL + ////////////////////////////////////////////////////////////////////////// struct ECORE_API SState : public xr_resource_flagged { diff --git a/src/Layers/xrRender/Shader.cpp b/src/Layers/xrRender/Shader.cpp index dec298bd643..7a827cf2564 100644 --- a/src/Layers/xrRender/Shader.cpp +++ b/src/Layers/xrRender/Shader.cpp @@ -60,6 +60,10 @@ bool SPass::equal(const SPass& other) const return false; # endif #endif // USE_DX11 || USE_OGL +#ifdef USE_OGL + if (pp != other.pp) + return false; +#endif if (constants != other.constants) return false; // is this nessesary??? (ps+vs already combines) @@ -136,26 +140,16 @@ void STextureList::clear() u32 STextureList::find_texture_stage(const shared_str& TexName) const { - u32 dwTextureStage = 0; - - STextureList::const_iterator _it = this->begin(); - STextureList::const_iterator _end = this->end(); - for (; _it != _end; ++_it) + for (const auto& [stage, texture] : *this) { - const std::pair& loader = *_it; - - // Shadowmap texture always uses 0 texture unit - if (loader.second->cName == TexName) - { - // Assign correct texture - dwTextureStage = loader.first; - break; - } + if (!texture) + continue; + if (texture->cName == TexName) + return stage; } - VERIFY(_it != _end); - - return dwTextureStage; + VERIFY3(false, "Couldn't find texture stage", TexName.c_str()); + return 0; } void STextureList::create_texture(u32 stage, pcstr textureName, bool evenIfNotNull) diff --git a/src/Layers/xrRender/Shader.h b/src/Layers/xrRender/Shader.h index 99face148c8..31d50471456 100644 --- a/src/Layers/xrRender/Shader.h +++ b/src/Layers/xrRender/Shader.h @@ -98,6 +98,9 @@ struct ECORE_API SPass : public xr_resource_flagged ref_cs cs; // may be NULL = don't use compute shader at all # endif #endif // !USE_DX9 +#if defined(USE_OGL) + ref_pp pp; // may be NULL = don't use program pipeline at all +#endif ref_ctable constants; // may be NULL ref_texture_list T; diff --git a/src/Layers/xrRender/ShaderResourceTraits.h b/src/Layers/xrRender/ShaderResourceTraits.h index b0fb80a5718..c82ee616a88 100644 --- a/src/Layers/xrRender/ShaderResourceTraits.h +++ b/src/Layers/xrRender/ShaderResourceTraits.h @@ -42,7 +42,7 @@ static void show_compile_errors(cpcstr filename, GLuint program, GLuint shader) template inline std::pair GLCompileShader(pcstr* buffer, size_t size, pcstr name) { - GLuint shader = glCreateShader(type); + const GLuint shader = glCreateShader(type); R_ASSERT(shader); CHK_GL(glShaderSource(shader, size, buffer, nullptr)); CHK_GL(glCompileShader(shader)); @@ -56,7 +56,10 @@ inline std::pair GLCompileShader(pcstr* buffer, size_t size, pcstr return { 's', 0 }; // 's' means "shader", 0 means error } - GLuint program = glCreateProgram(); + if (!HW.SeparateShaderObjectsSupported) + return { 's', shader }; + + const GLuint program = glCreateProgram(); R_ASSERT(program); CHK_GL(glObjectLabel(GL_PROGRAM, program, -1, name)); CHK_GL(glProgramParameteri(program, GL_PROGRAM_SEPARABLE, (GLint)GL_TRUE)); @@ -87,7 +90,7 @@ inline std::pair GLUseBinary(pcstr* buffer, size_t size, const GLe { GLint status{}; - GLuint program = glCreateProgram(); + const GLuint program = glCreateProgram(); R_ASSERT(program); CHK_GL(glObjectLabel(GL_PROGRAM, program, -1, name)); CHK_GL(glProgramParameteri(program, GL_PROGRAM_SEPARABLE, (GLint)GL_TRUE)); @@ -108,6 +111,52 @@ inline std::pair GLUseBinary(pcstr* buffer, size_t size, const GLe return { 'p', program }; } + +static GLuint GLLinkMonolithicProgram(pcstr name, GLuint ps, GLuint vs, GLuint gs) +{ + const GLuint program = glCreateProgram(); + R_ASSERT(program); + CHK_GL(glObjectLabel(GL_PROGRAM, program, -1, name)); + // XXX: support caching for monolithic programs + //if (HW.ShaderBinarySupported) + // CHK_GL(glProgramParameteri(program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, (GLint)GL_TRUE)); + + CHK_GL(glAttachShader(program, ps)); + CHK_GL(glAttachShader(program, vs)); + if (gs) + CHK_GL(glAttachShader(program, gs)); + CHK_GL(glBindFragDataLocation(program, 0, "SV_Target")); + CHK_GL(glBindFragDataLocation(program, 0, "SV_Target0")); + CHK_GL(glBindFragDataLocation(program, 1, "SV_Target1")); + CHK_GL(glBindFragDataLocation(program, 2, "SV_Target2")); + CHK_GL(glLinkProgram(program)); + CHK_GL(glDetachShader(program, ps)); + CHK_GL(glDetachShader(program, vs)); + if (gs) + CHK_GL(glDetachShader(program, gs)); + + GLint status{}; + CHK_GL(glGetProgramiv(program, GL_LINK_STATUS, &status)); + if (GLboolean(status) == GL_FALSE) + { + show_compile_errors(name, program, 0); + CHK_GL(glDeleteProgram(program)); + return 0; // 0 means error + } + return program; +} + +static GLuint GLGeneratePipeline(pcstr name, GLuint ps, GLuint vs, GLuint gs) +{ + GLuint pp; + CHK_GL(glGenProgramPipelines(1, &pp)); + R_ASSERT(pp); + CHK_GL(glUseProgramStages(pp, GL_FRAGMENT_SHADER_BIT, ps)); + CHK_GL(glUseProgramStages(pp, GL_VERTEX_SHADER_BIT, vs)); + CHK_GL(glUseProgramStages(pp, GL_GEOMETRY_SHADER_BIT, gs)); + CHK_GL(glValidateProgramPipeline(pp)); + return pp; +} #endif template diff --git a/src/Layers/xrRender/blenders/BlenderDefault.cpp b/src/Layers/xrRender/blenders/BlenderDefault.cpp index e27b06dbbed..c9876e67e1c 100644 --- a/src/Layers/xrRender/blenders/BlenderDefault.cpp +++ b/src/Layers/xrRender/blenders/BlenderDefault.cpp @@ -99,8 +99,7 @@ void CBlender_default::Compile(CBlender_Compile& C) // Level view C.PassBegin(); { - C.PassSET_VS(tsv_hq); - C.PassSET_PS(tsp_hq); + C.PassSET_Shaders(tsv_hq, tsp_hq); C.PassSET_LightFog(false, true); @@ -119,8 +118,7 @@ void CBlender_default::Compile(CBlender_Compile& C) case SE_R1_NORMAL_LQ: C.PassBegin(); { - C.PassSET_VS("lmap"); - C.PassSET_PS("lmap"); + C.PassSET_Shaders("lmap", "lmap"); C.PassSET_LightFog(false, true); @@ -135,8 +133,7 @@ void CBlender_default::Compile(CBlender_Compile& C) { C.PassBegin(); { - C.PassSET_VS("lmap_point"); - C.PassSET_PS("add_point"); + C.PassSET_Shaders("lmap_point", "add_point"); C.PassSET_ZB(true, false); C.PassSET_ablend_mode(true, D3DBLEND_ONE, D3DBLEND_ONE); @@ -154,8 +151,7 @@ void CBlender_default::Compile(CBlender_Compile& C) { C.PassBegin(); { - C.PassSET_VS("lmap_spot"); - C.PassSET_PS("add_spot"); + C.PassSET_Shaders("lmap_spot", "add_spot"); C.PassSET_ZB(true, false); C.PassSET_ablend_mode(true, D3DBLEND_ONE, D3DBLEND_ONE); @@ -176,8 +172,7 @@ void CBlender_default::Compile(CBlender_Compile& C) // Lighting only, not use alpha-channel C.PassBegin(); { - C.PassSET_VS("lmap_l"); - C.PassSET_PS("lmap_l"); + C.PassSET_Shaders("lmap_l", "lmap_l"); C.SampledImage("s_base", "s_base", C.L_textures[0]); C.SampledImage("s_lmap", "s_lmap", C.L_textures[1]); diff --git a/src/Layers/xrRender/blenders/Blender_Editor_Selection.cpp b/src/Layers/xrRender/blenders/Blender_Editor_Selection.cpp index d5610aa01b6..ce932f90ff0 100644 --- a/src/Layers/xrRender/blenders/Blender_Editor_Selection.cpp +++ b/src/Layers/xrRender/blenders/Blender_Editor_Selection.cpp @@ -65,8 +65,7 @@ void CBlender_Editor_Selection::Compile(CBlender_Compile& C) C.PassBegin(); { - C.PassSET_VS("editor"); - C.PassSET_PS("simple_color"); + C.PassSET_Shaders("editor", "simple_color"); C.PassSET_LightFog(false, true); C.PassSET_ZB(true, false); diff --git a/src/Layers/xrRender/blenders/Blender_Editor_Wire.cpp b/src/Layers/xrRender/blenders/Blender_Editor_Wire.cpp index d5499864679..ab72adbe4e9 100644 --- a/src/Layers/xrRender/blenders/Blender_Editor_Wire.cpp +++ b/src/Layers/xrRender/blenders/Blender_Editor_Wire.cpp @@ -60,8 +60,7 @@ void CBlender_Editor_Wire::Compile(CBlender_Compile& C) C.PassBegin(); { - C.PassSET_VS("editor"); - C.PassSET_PS("simple_color"); + C.PassSET_Shaders("editor", "simple_color"); } C.PassEnd(); } diff --git a/src/Layers/xrRender/blenders/Blender_Screen_SET.cpp b/src/Layers/xrRender/blenders/Blender_Screen_SET.cpp index 7d730389dd8..f0efbbd1559 100644 --- a/src/Layers/xrRender/blenders/Blender_Screen_SET.cpp +++ b/src/Layers/xrRender/blenders/Blender_Screen_SET.cpp @@ -177,27 +177,23 @@ void CBlender_Screen_SET::CompileProgrammed(CBlender_Compile& C) { case 6: // Usually for wallmarks - C.PassSET_VS("stub_notransform_t"); - C.PassSET_PS("stub_default_ma"); + C.PassSET_Shaders("stub_notransform_t", "stub_default_ma"); break; case 9: // 4x R - C.PassSET_VS("stub_notransform_t_m4"); - C.PassSET_PS("stub_default"); + C.PassSET_Shaders("stub_notransform_t_m4", "stub_default"); break; case 7: case 8: // 2x R - C.PassSET_VS("stub_notransform_t_m2"); - C.PassSET_PS("stub_default"); + C.PassSET_Shaders("stub_notransform_t_m2", "stub_default"); break; default: // 1x R - C.PassSET_VS("stub_notransform_t"); - C.PassSET_PS("stub_default"); + C.PassSET_Shaders("stub_notransform_t", "stub_default"); break; } diff --git a/src/Layers/xrRender/blenders/Blender_Vertex.cpp b/src/Layers/xrRender/blenders/Blender_Vertex.cpp index 2cb9cc881ab..03fc432f984 100644 --- a/src/Layers/xrRender/blenders/Blender_Vertex.cpp +++ b/src/Layers/xrRender/blenders/Blender_Vertex.cpp @@ -93,8 +93,7 @@ void CBlender_Vertex::Compile(CBlender_Compile& C) cpcstr tsv_hq = C.bDetail_Diffuse ? "vert_dt" : "vert"; cpcstr tsp_hq = C.bDetail_Diffuse ? "vert_dt" : "vert"; - C.PassSET_VS(tsv_hq); - C.PassSET_PS(tsp_hq); + C.PassSET_Shaders(tsv_hq, tsp_hq); C.PassSET_LightFog(false, true); @@ -111,8 +110,7 @@ void CBlender_Vertex::Compile(CBlender_Compile& C) // Level view C.PassBegin(); { - C.PassSET_VS("vert"); - C.PassSET_PS("vert"); + C.PassSET_Shaders("vert", "vert"); C.PassSET_LightFog(false, true); @@ -124,8 +122,7 @@ void CBlender_Vertex::Compile(CBlender_Compile& C) case SE_R1_LPOINT: C.PassBegin(); { - C.PassSET_VS("vert_point"); - C.PassSET_PS("add_point"); + C.PassSET_Shaders("vert_point", "add_point"); C.PassSET_ZB(true, false); C.PassSET_Blend(true, D3DBLEND_ONE, D3DBLEND_ONE, true, 0); @@ -140,8 +137,7 @@ void CBlender_Vertex::Compile(CBlender_Compile& C) case SE_R1_LSPOT: C.PassBegin(); { - C.PassSET_VS("vert_spot"); - C.PassSET_PS("add_spot"); + C.PassSET_Shaders("vert_spot", "add_spot"); C.PassSET_ZB(true, false); C.PassSET_Blend(true, D3DBLEND_ONE, D3DBLEND_ONE, true, 0); @@ -159,8 +155,7 @@ void CBlender_Vertex::Compile(CBlender_Compile& C) case SE_R1_LMODELS: C.PassBegin(); { - C.PassSET_VS("vert_l"); - C.PassSET_PS("vert_l"); + C.PassSET_Shaders("vert_l", "vert_l"); C.SampledImage("s_base", "s_base", C.L_textures[0]); } diff --git a/src/Layers/xrRender/blenders/Blender_Vertex_aref.cpp b/src/Layers/xrRender/blenders/Blender_Vertex_aref.cpp index dc97e586ae1..a6797258771 100644 --- a/src/Layers/xrRender/blenders/Blender_Vertex_aref.cpp +++ b/src/Layers/xrRender/blenders/Blender_Vertex_aref.cpp @@ -92,8 +92,7 @@ void CBlender_Vertex_aref::Compile(CBlender_Compile& C) cpcstr tsv_hq = C.bDetail_Diffuse ? "vert_dt" : "vert"; cpcstr tsp_hq = C.bDetail_Diffuse ? "vert_dt" : "vert"; - C.PassSET_VS(tsv_hq); - C.PassSET_PS(tsp_hq); + C.PassSET_Shaders(tsv_hq, tsp_hq); C.PassSET_LightFog(false, true); C.PassSET_ablend_mode(true, blend_src, blend_dst); @@ -112,8 +111,7 @@ void CBlender_Vertex_aref::Compile(CBlender_Compile& C) // Level view C.PassBegin(); { - C.PassSET_VS("vert"); - C.PassSET_PS("vert"); + C.PassSET_Shaders("vert", "vert"); C.PassSET_LightFog(false, true); C.PassSET_ablend_mode(true, blend_src, blend_dst); @@ -127,8 +125,7 @@ void CBlender_Vertex_aref::Compile(CBlender_Compile& C) case SE_R1_LPOINT: C.PassBegin(); { - C.PassSET_VS("vert_point"); - C.PassSET_PS("add_point"); + C.PassSET_Shaders("vert_point", "add_point"); C.PassSET_ZB(true, false); C.PassSET_ablend_mode(true, D3DBLEND_ONE, D3DBLEND_ONE); @@ -148,8 +145,7 @@ void CBlender_Vertex_aref::Compile(CBlender_Compile& C) case SE_R1_LSPOT: C.PassBegin(); { - C.PassSET_VS("vert_spot"); - C.PassSET_PS("add_spot"); + C.PassSET_Shaders("vert_spot", "add_spot"); C.PassSET_ZB(true, false); C.PassSET_ablend_mode(true, D3DBLEND_ONE, D3DBLEND_ONE); @@ -172,8 +168,7 @@ void CBlender_Vertex_aref::Compile(CBlender_Compile& C) case SE_R1_LMODELS: C.PassBegin(); { - C.PassSET_VS("vert_l"); - C.PassSET_PS("vert_l"); + C.PassSET_Shaders("vert_l", "vert_l"); C.SampledImage("s_base", "s_base", C.L_textures[0]); } diff --git a/src/Layers/xrRender/blenders/Blender_default_aref.cpp b/src/Layers/xrRender/blenders/Blender_default_aref.cpp index a7647f55db4..06c914a890a 100644 --- a/src/Layers/xrRender/blenders/Blender_default_aref.cpp +++ b/src/Layers/xrRender/blenders/Blender_default_aref.cpp @@ -100,8 +100,7 @@ void CBlender_default_aref::Compile(CBlender_Compile& C) C.PassBegin(); { - C.PassSET_VS(tsv_hq); - C.PassSET_PS(tsp_hq); + C.PassSET_Shaders(tsv_hq, tsp_hq); C.PassSET_LightFog(false, true); C.PassSET_ZB(true, true); @@ -123,8 +122,7 @@ void CBlender_default_aref::Compile(CBlender_Compile& C) case SE_R1_NORMAL_LQ: C.PassBegin(); { - C.PassSET_VS("lmap"); - C.PassSET_PS("lmap"); + C.PassSET_Shaders("lmap", "lmap"); C.PassSET_LightFog(false, true); C.PassSET_ZB(true, true); @@ -146,8 +144,7 @@ void CBlender_default_aref::Compile(CBlender_Compile& C) C.PassBegin(); { - C.PassSET_VS("lmap_point"); - C.PassSET_PS("add_point"); + C.PassSET_Shaders("lmap_point", "add_point"); C.PassSET_ZB(true, false); C.PassSET_ablend_mode(true, D3DBLEND_ONE, D3DBLEND_ONE); @@ -168,8 +165,7 @@ void CBlender_default_aref::Compile(CBlender_Compile& C) C.PassBegin(); { - C.PassSET_VS("lmap_spot"); - C.PassSET_PS("add_spot"); + C.PassSET_Shaders("lmap_spot", "add_spot"); C.PassSET_ZB(true, false); C.PassSET_ablend_mode(true, D3DBLEND_ONE, D3DBLEND_ONE); @@ -189,8 +185,7 @@ void CBlender_default_aref::Compile(CBlender_Compile& C) case SE_R1_LMODELS: C.PassBegin(); { - C.PassSET_VS("lmap_l"); - C.PassSET_PS("lmap_l"); + C.PassSET_Shaders("lmap_l", "lmap_l"); C.SampledImage("s_base", "s_base", C.L_textures[0]); C.SampledImage("s_lmap", "s_lmap", C.L_textures[1]); diff --git a/src/Layers/xrRender/dxEnvironmentRender.cpp b/src/Layers/xrRender/dxEnvironmentRender.cpp index 2955a3c88ef..1cff48ffe5d 100644 --- a/src/Layers/xrRender/dxEnvironmentRender.cpp +++ b/src/Layers/xrRender/dxEnvironmentRender.cpp @@ -99,7 +99,6 @@ void dxEnvDescriptorMixerRender::lerp(IEnvDescriptorRender* inA, IEnvDescriptorR sky_r_textures.push_back(std::make_pair(1, pB->sky_texture)); sky_r_textures_env.clear(); - sky_r_textures_env.push_back(std::make_pair(0, pA->sky_texture_env)); sky_r_textures_env.push_back(std::make_pair(1, pB->sky_texture_env)); @@ -128,76 +127,35 @@ void dxEnvDescriptorRender::OnDeviceDestroy() } dxEnvironmentRender::dxEnvironmentRender() + : tonemap_tstage_2sky(u32(-1)), tonemap_tstage_clouds(u32(-1)), + tsky0_tstage(u32(-1)), tsky1_tstage(u32(-1)), + tclouds0_tstage(u32(-1)), tclouds1_tstage(u32(-1)) { - tsky0 = RImplementation.Resources->_CreateTexture("$user$sky0"); - tsky1 = RImplementation.Resources->_CreateTexture("$user$sky1"); -#ifdef USE_OGL - // These textures are specified in clouds.s - tclouds0 = RImplementation.Resources->_CreateTexture("$user$clouds0"); - tclouds1 = RImplementation.Resources->_CreateTexture("$user$clouds1"); -#endif + tsky0 = RImplementation.Resources->_CreateTexture(r2_T_sky0); + tsky1 = RImplementation.Resources->_CreateTexture(r2_T_sky1); } void dxEnvironmentRender::OnFrame(CEnvironment& env) { dxEnvDescriptorMixerRender& mixRen = *(dxEnvDescriptorMixerRender*)&*env.CurrentEnv->m_pDescriptorMixer; + mixRen.sky_r_textures[0].first = tsky0_tstage; + mixRen.sky_r_textures[1].first = tsky1_tstage; + mixRen.clouds_r_textures[0].first = tclouds0_tstage; + mixRen.clouds_r_textures[1].first = tclouds1_tstage; if (GEnv.Render->GenerationIsR2OrHigher()) { - //. very very ugly hack - if (HW.Caps.raster_major >= 3 && HW.Caps.geometry.bVTF) - { - // tonemapping in VS - /* - * This hack relies on assumption that `s_tonemap` sampler is - * only or the very first sampler in the VS. This is ok in case - * of DX, but OGL counts uniforms contiguousy disregarding their - * types. - * The w/a here is to skip VS uniforms in order to get - * correct sampler location. - */ -#if defined(USE_DX9) || defined(USE_DX11) - const u32 smp_location_sky = CTexture::rstVertex; - const u32 smp_location_clouds = CTexture::rstVertex; -#elif defined(USE_OGL) - const u32 smp_location_sky = CTexture::rstVertex + 1 /* m_WVP */; - const u32 smp_location_clouds = CTexture::rstVertex + 1 /* m_WVP */; -#else -# error No graphics API selected or enabled! -#endif - mixRen.sky_r_textures.push_back(std::make_pair(smp_location_sky, tonemap)); //. hack - mixRen.clouds_r_textures.push_back(std::make_pair(smp_location_clouds, tonemap)); //. hack - } - else - { - // tonemapping in PS - /* - * Note: `2` here is a dangerous assumption that previous samplers - * (0 and 1) are defined in the shader and there are no other uniforms - * before the `s_tonemap` in the case of OGL. - */ - mixRen.sky_r_textures.push_back(std::make_pair(2, tonemap)); //. hack - mixRen.clouds_r_textures.push_back(std::make_pair(2, tonemap)); //. hack - } + mixRen.sky_r_textures.emplace_back(tonemap_tstage_2sky, tonemap); //. hack + mixRen.clouds_r_textures.emplace_back(tonemap_tstage_clouds, tonemap); //. hack } //. Setup skybox textures, somewhat ugly + auto e0 = mixRen.sky_r_textures[0].second->surface_get(); + auto e1 = mixRen.sky_r_textures[1].second->surface_get(); #ifdef USE_OGL - GLuint e0 = mixRen.sky_r_textures[0].second->surface_get(); - GLuint e1 = mixRen.sky_r_textures[1].second->surface_get(); - tsky0->surface_set(GL_TEXTURE_CUBE_MAP, e0); tsky1->surface_set(GL_TEXTURE_CUBE_MAP, e1); - - e0 = mixRen.clouds_r_textures[0].second->surface_get(); - e1 = mixRen.clouds_r_textures[1].second->surface_get(); - - tclouds0->surface_set(GL_TEXTURE_2D, e0); - tclouds1->surface_set(GL_TEXTURE_2D, e1); #else // USE_OGL - ID3DBaseTexture* e0 = mixRen.sky_r_textures[0].second->surface_get(); - ID3DBaseTexture* e1 = mixRen.sky_r_textures[1].second->surface_get(); - tsky0->surface_set(e0); _RELEASE(e0); tsky1->surface_set(e1); @@ -222,7 +180,7 @@ void dxEnvironmentRender::OnFrame(CEnvironment& env) void dxEnvironmentRender::OnLoad() { - tonemap = RImplementation.Resources->_CreateTexture("$user$tonemap"); //. hack + tonemap = RImplementation.Resources->_CreateTexture(r2_RT_luminance_cur); //. hack } void dxEnvironmentRender::OnUnload() { tonemap = nullptr; } @@ -331,13 +289,11 @@ void dxEnvironmentRender::RenderClouds(CEnvironment& env) RCache.Vertex.Unlock(env.CloudsVerts.size(), clouds_geom.stride()); // Render + dxEnvDescriptorMixerRender& mixRen = *(dxEnvDescriptorMixerRender*)&*env.CurrentEnv->m_pDescriptorMixer; RCache.set_xform_world(mXFORM); RCache.set_Geometry(clouds_geom); RCache.set_Shader(clouds_sh); -#ifndef USE_OGL // Fix cloud lerping on OGL - dxEnvDescriptorMixerRender& mixRen = *(dxEnvDescriptorMixerRender*)&*env.CurrentEnv->m_pDescriptorMixer; RCache.set_Textures(&mixRen.clouds_r_textures); -#endif RCache.Render(D3DPT_TRIANGLELIST, v_offset, 0, env.CloudsVerts.size(), i_offset, env.CloudsIndices.size() / 3); GEnv.Render->rmNormal(); @@ -349,6 +305,30 @@ void dxEnvironmentRender::OnDeviceCreate() sh_2geom.create(v_skybox_fvf, RCache.Vertex.Buffer(), RCache.Index.Buffer()); clouds_sh.create("clouds", "null"); clouds_geom.create(v_clouds_fvf, RCache.Vertex.Buffer(), RCache.Index.Buffer()); + + if (GEnv.Render->GenerationIsR2OrHigher()) + { + tonemap_tstage_2sky = sh_2sky->E[0]->passes[0]->T->find_texture_stage(r2_RT_luminance_cur); + tonemap_tstage_clouds = clouds_sh->E[0]->passes[0]->T->find_texture_stage(r2_RT_luminance_cur); + R_ASSERT(tonemap_tstage_2sky != u32(-1)); + R_ASSERT(tonemap_tstage_clouds != u32(-1)); + } + + R_constant* C = sh_2sky->E[0]->passes[0]->constants->get(RImplementation.c_ssky0)._get(); + R_ASSERT(C); + tsky0_tstage = C->samp.index; + + C = sh_2sky->E[0]->passes[0]->constants->get(RImplementation.c_ssky1)._get(); + R_ASSERT(C); + tsky1_tstage = C->samp.index; + + C = clouds_sh->E[0]->passes[0]->constants->get(RImplementation.c_sclouds0)._get(); + R_ASSERT(C); + tclouds0_tstage = C->samp.index; + + C = clouds_sh->E[0]->passes[0]->constants->get(RImplementation.c_sclouds1)._get(); + R_ASSERT(C); + tclouds1_tstage = C->samp.index; } void dxEnvironmentRender::OnDeviceDestroy() @@ -359,8 +339,6 @@ void dxEnvironmentRender::OnDeviceDestroy() #elif defined(USE_OGL) tsky0->surface_set(GL_TEXTURE_CUBE_MAP, 0); tsky1->surface_set(GL_TEXTURE_CUBE_MAP, 0); - tclouds0->surface_set(GL_TEXTURE_2D, 0); - tclouds1->surface_set(GL_TEXTURE_2D, 0); #else # error No graphics API slected or defined! #endif @@ -369,6 +347,13 @@ void dxEnvironmentRender::OnDeviceDestroy() sh_2geom.destroy(); clouds_sh.destroy(); clouds_geom.destroy(); + + tonemap_tstage_2sky = u32(-1); + tonemap_tstage_clouds = u32(-1); + tsky0_tstage = u32(-1); + tsky1_tstage = u32(-1); + tclouds0_tstage = u32(-1); + tclouds1_tstage = u32(-1); } void dxEnvironmentRender::OnDeviceReset() diff --git a/src/Layers/xrRender/dxEnvironmentRender.h b/src/Layers/xrRender/dxEnvironmentRender.h index 3e4b41ecc38..dd4d64934c9 100644 --- a/src/Layers/xrRender/dxEnvironmentRender.h +++ b/src/Layers/xrRender/dxEnvironmentRender.h @@ -28,18 +28,9 @@ class CBlender_skybox : public IBlender C.r_dx10Texture("s_tonemap", "$user$tonemap"); //. hack C.PassSET_ZB(FALSE, FALSE); #elif defined(USE_OGL) - if (HW.Caps.geometry.bVTF) - { - C.r_Sampler_clf("s_sky0", "$null"); - C.r_Sampler_clf("s_sky1", "$null"); - C.r_Sampler_rtf("s_tonemap", "$user$tonemap"); //. hack - } - else - { - C.r_Sampler_clf("s_sky0", r2_T_sky0); - C.r_Sampler_clf("s_sky1", r2_T_sky1); - C.r_Sampler_rtf("s_tonemap", r2_RT_luminance_cur); - } + C.r_Sampler_clf("s_sky0", "$null"); + C.r_Sampler_clf("s_sky1", "$null"); + C.r_Sampler_rtf("s_tonemap", "$user$tonemap"); //. hack C.PassSET_ZB(FALSE, FALSE); #else # error No graphics API selected or enabled! @@ -100,13 +91,18 @@ class dxEnvironmentRender : public IEnvironmentRender, public CDeviceResetNotifi ref_shader sh_2sky; ref_geom sh_2geom; + u32 tonemap_tstage_2sky; ref_shader clouds_sh; ref_geom clouds_geom; + u32 tonemap_tstage_clouds; ref_texture tonemap; ref_texture tsky0, tsky1; - ref_texture tclouds0, tclouds1; + u32 tsky0_tstage; + u32 tsky1_tstage; + u32 tclouds0_tstage; + u32 tclouds1_tstage; }; #endif // EnvironmentRender_included diff --git a/src/Layers/xrRender/dxFontRender.cpp b/src/Layers/xrRender/dxFontRender.cpp index a9fc527370f..868f66d9588 100644 --- a/src/Layers/xrRender/dxFontRender.cpp +++ b/src/Layers/xrRender/dxFontRender.cpp @@ -28,7 +28,10 @@ void dxFontRender::OnRender(CGameFont& owner) if (!(owner.uFlags & CGameFont::fsValid)) { - CTexture* T = RCache.get_ActiveTexture(0); + R_ASSERT(pShader); + R_constant* C = RCache.get_c(RImplementation.c_sbase)._get(); // get sampler + CTexture* T = RCache.get_ActiveTexture(C ? C->samp.index : 0); + R_ASSERT(T); owner.vTS.set((int)T->get_Width(), (int)T->get_Height()); owner.fTCHeight = owner.fHeight / float(owner.vTS.y); owner.uFlags |= CGameFont::fsValid; diff --git a/src/Layers/xrRender/dxUIRender.cpp b/src/Layers/xrRender/dxUIRender.cpp index 26d07cc3b6d..3d8074c4222 100644 --- a/src/Layers/xrRender/dxUIRender.cpp +++ b/src/Layers/xrRender/dxUIRender.cpp @@ -149,7 +149,9 @@ void dxUIRender::SetScissor(Irect* rect) void dxUIRender::GetActiveTextureResolution(Fvector2& res) { - CTexture* T = RCache.get_ActiveTexture(0); + R_constant* C = RCache.get_c(RImplementation.c_sbase)._get(); // get sampler + CTexture* T = RCache.get_ActiveTexture(C ? C->samp.index : 0); + R_ASSERT(T); res.set(float(T->get_Width()), float(T->get_Height())); } diff --git a/src/Layers/xrRender/dxUISequenceVideoItem.cpp b/src/Layers/xrRender/dxUISequenceVideoItem.cpp index f0179f1baa1..44d25926baf 100644 --- a/src/Layers/xrRender/dxUISequenceVideoItem.cpp +++ b/src/Layers/xrRender/dxUISequenceVideoItem.cpp @@ -3,4 +3,10 @@ dxUISequenceVideoItem::dxUISequenceVideoItem() { m_texture = nullptr; } void dxUISequenceVideoItem::Copy(IUISequenceVideoItem& _in) { *this = *((dxUISequenceVideoItem*)&_in); } -void dxUISequenceVideoItem::CaptureTexture() { m_texture = RCache.get_ActiveTexture(0); } + +void dxUISequenceVideoItem::CaptureTexture() +{ + R_constant* C = RCache.get_c(RImplementation.c_sbase)._get(); // get sampler + m_texture = RCache.get_ActiveTexture(C ? C->samp.index : 0); + R_ASSERT(m_texture); +} diff --git a/src/Layers/xrRender/r_constants.cpp b/src/Layers/xrRender/r_constants.cpp index 56281927d7f..73f42bbab95 100644 --- a/src/Layers/xrRender/r_constants.cpp +++ b/src/Layers/xrRender/r_constants.cpp @@ -145,7 +145,7 @@ BOOL R_constant_table::parse(void* _desc, u32 destination) C->destination = RC_dest_sampler; C->type = RC_sampler; R_constant_load& L = C->samp; - L.index = u16(r_index + ((destination & 1) ? 0 : D3DVERTEXTEXTURESAMPLER0)); + L.index = u16(r_index + ((destination & RC_dest_pixel) ? 0 : D3DVERTEXTEXTURESAMPLER0)); L.cls = RC_sampler; } else @@ -176,7 +176,7 @@ BOOL R_constant_table::parse(void* _desc, u32 destination) C->name = name; C->destination = destination; C->type = type; - R_constant_load& L = (destination & 1) ? C->ps : C->vs; + R_constant_load& L = (destination & RC_dest_pixel) ? C->ps : C->vs; L.index = r_index; L.cls = r_type; } @@ -184,7 +184,7 @@ BOOL R_constant_table::parse(void* _desc, u32 destination) { C->destination |= destination; VERIFY(C->type == type); - R_constant_load& L = (destination & 1) ? C->ps : C->vs; + R_constant_load& L = (destination & RC_dest_pixel) ? C->ps : C->vs; L.index = r_index; L.cls = r_type; } @@ -225,6 +225,9 @@ void R_constant_table::merge(R_constant_table* T) C->ds = src->ds; C->cs = src->cs; # endif +#endif +#ifdef USE_OGL + C->pp = src->pp; #endif C->samp = src->samp; C->handler = src->handler; @@ -277,10 +280,10 @@ BOOL R_constant_table::equal(R_constant_table& C) { if (table.size() != C.table.size()) return FALSE; - u32 size = table.size(); - for (u32 it = 0; it < size; it++) + const size_t size = table.size(); + for (size_t it = 0; it < size; it++) { - if (!table[it]->equal(&*C.table[it])) + if (!table[it]->equal(*C.table[it])) return FALSE; } diff --git a/src/Layers/xrRender/r_constants.h b/src/Layers/xrRender/r_constants.h index 4377b563f6a..60eb21d40d9 100644 --- a/src/Layers/xrRender/r_constants.h +++ b/src/Layers/xrRender/r_constants.h @@ -42,6 +42,7 @@ enum RC_dest_hull = (1 << 4), // DX11 only RC_dest_domain = (1 << 5), // DX11 only RC_dest_compute = (1 << 6), // DX11 only + RC_dest_all = (1 << 7), // OpenGL only RC_dest_compute_cb_index_mask = 0xF0000000, // Buffer index == 0..14 RC_dest_compute_cb_index_shift = 28, RC_dest_domain_cb_index_mask = 0x0F000000, // Buffer index == 0..14 @@ -112,6 +113,9 @@ struct ECORE_API R_constant : public xr_resource R_constant_load ds; R_constant_load cs; # endif +#endif +#ifdef USE_OGL + R_constant_load pp; #endif R_constant_load samp; @@ -134,6 +138,9 @@ struct ECORE_API R_constant : public xr_resource case RC_dest_domain: return ds; case RC_dest_compute: return cs; # endif +#endif +#ifdef USE_OGL + case RC_dest_all: return pp; #endif default: FATAL("invalid enumeration for shader"); } @@ -142,11 +149,25 @@ struct ECORE_API R_constant : public xr_resource BOOL equal(R_constant& C) { - return (!xr_strcmp(name, C.name)) && (type == C.type) && (destination == C.destination) && ps.equal(C.ps) && - vs.equal(C.vs) && samp.equal(C.samp) && handler == C.handler; + return !xr_strcmp(name, C.name) + && type == C.type + && destination == C.destination + && ps.equal(C.ps) + && vs.equal(C.vs) +#if defined(USE_DX11) || defined(USE_OGL) + && gs.equal(C.gs) +# if defined(USE_DX11) + && hs.equal(C.hs) + && ds.equal(C.ds) + && cs.equal(C.cs) +# endif +# if defined(USE_OGL) + && pp.equal(C.pp) +# endif +#endif + && samp.equal(C.samp) + && handler == C.handler; } - - BOOL equal(R_constant* C) { return equal(*C); } }; typedef resptr_core> ref_constant; diff --git a/src/Layers/xrRenderDX10/dx10r_constants.cpp b/src/Layers/xrRenderDX10/dx10r_constants.cpp index f2b42e6f9ac..4ca6adb5c55 100644 --- a/src/Layers/xrRenderDX10/dx10r_constants.cpp +++ b/src/Layers/xrRenderDX10/dx10r_constants.cpp @@ -163,10 +163,7 @@ BOOL R_constant_table::parseConstants(ID3DShaderReflectionConstantBuffer* pTable C->name = name; C->destination = destination; C->type = type; - // R_constant_load& L = (destination&1)?C->ps:C->vs; - R_constant_load& L = C->get_load(destination); /*((destination&RC_dest_pixel) - ? C->ps : (destination&RC_dest_vertex) - ? C->vs : C->gs);*/ + R_constant_load& L = C->get_load(destination); L.index = r_index; L.cls = r_type; } @@ -174,10 +171,7 @@ BOOL R_constant_table::parseConstants(ID3DShaderReflectionConstantBuffer* pTable { C->destination |= destination; VERIFY(C->type == type); - // R_constant_load& L = (destination&1)?C->ps:C->vs; - R_constant_load& L = C->get_load(destination); /*((destination&RC_dest_pixel) - ? C->ps : (destination&RC_dest_vertex) - ? C->vs : C->gs);*/ + R_constant_load& L = C->get_load(destination); L.index = r_index; L.cls = r_type; } diff --git a/src/Layers/xrRenderGL/Blender_Recorder_GL.cpp b/src/Layers/xrRenderGL/Blender_Recorder_GL.cpp index b91f9b86f8e..d9fc7a9c07a 100644 --- a/src/Layers/xrRenderGL/Blender_Recorder_GL.cpp +++ b/src/Layers/xrRenderGL/Blender_Recorder_GL.cpp @@ -64,19 +64,22 @@ void CBlender_Compile::r_Pass(LPCSTR _vs, LPCSTR _gs, LPCSTR _ps, bool bFog, BOO PassSET_LightFog(FALSE, bFog); // Create shaders - SPS* ps = RImplementation.Resources->_CreatePS(_ps); - SVS* vs = RImplementation.Resources->_CreateVS(_vs); - SGS* gs = RImplementation.Resources->_CreateGS(_gs); - dest.ps = ps; - dest.vs = vs; - dest.gs = gs; -#ifdef USE_DX11 - dest.hs = RImplementation.Resources->_CreateHS("null"); - dest.ds = RImplementation.Resources->_CreateDS("null"); +#if defined(USE_OGL) + dest.pp = RImplementation.Resources->_CreatePP(_vs, _ps, _gs, "null", "null"); + if (HW.SeparateShaderObjectsSupported || !dest.pp->pp) +#endif + { + dest.ps = RImplementation.Resources->_CreatePS(_ps); + dest.vs = RImplementation.Resources->_CreateVS(_vs); + dest.gs = RImplementation.Resources->_CreateGS(_gs); + ctable.merge(&dest.ps->constants); + ctable.merge(&dest.vs->constants); + ctable.merge(&dest.gs->constants); + } +#if defined(USE_OGL) + RImplementation.Resources->_LinkPP(dest); + ctable.merge(&dest.pp->constants); #endif - ctable.merge(&ps->constants); - ctable.merge(&vs->constants); - ctable.merge(&gs->constants); // Last Stage - disable if (0 == xr_stricmp(_ps, "null")) diff --git a/src/Layers/xrRenderGL/glHW.cpp b/src/Layers/xrRenderGL/glHW.cpp index 1dd6b7cd1b2..ab27bfd7aaf 100644 --- a/src/Layers/xrRenderGL/glHW.cpp +++ b/src/Layers/xrRenderGL/glHW.cpp @@ -148,6 +148,7 @@ void CHW::CreateDevice(SDL_Window* hWnd) Msg("* GPU OpenGL shading language version: %s", ShadingVersion); Msg("* GPU OpenGL VTF units: [%d] CTI units: [%d]", iMaxVTFUnits, iMaxCTIUnits); + SeparateShaderObjectsSupported = GLEW_ARB_separate_shader_objects; ShaderBinarySupported = GLEW_ARB_get_program_binary; ComputeShadersSupported = false; // XXX: Implement compute shaders support @@ -174,7 +175,6 @@ void CHW::DestroyDevice() ////////////////////////////////////////////////////////////////////// void CHW::Reset() { - CHK_GL(glDeleteProgramPipelines(1, &pPP)); CHK_GL(glDeleteFramebuffers(1, &pFB)); UpdateViews(); UpdateVSync(); @@ -231,10 +231,6 @@ int CHW::MakeContextCurrent(IRender::RenderContext context) const void CHW::UpdateViews() { - // Create the program pipeline used for rendering with shaders - glGenProgramPipelines(1, &pPP); - CHK_GL(glBindProgramPipeline(pPP)); - // Create the default framebuffer glGenFramebuffers(1, &pFB); CHK_GL(glBindFramebuffer(GL_FRAMEBUFFER, pFB)); diff --git a/src/Layers/xrRenderGL/glHW.h b/src/Layers/xrRenderGL/glHW.h index 1ca85761ecf..b3cf96f1a3c 100644 --- a/src/Layers/xrRenderGL/glHW.h +++ b/src/Layers/xrRenderGL/glHW.h @@ -47,7 +47,6 @@ class CHW u32 BackBufferCount{}; u32 CurrentBackBuffer{}; - GLuint pPP{}; GLuint pFB{}; SDL_Window* m_window{}; @@ -60,6 +59,7 @@ class CHW pcstr OpenGLVersionString; pcstr ShadingVersion; std::pair OpenGLVersion; + bool SeparateShaderObjectsSupported; bool ShaderBinarySupported; bool ComputeShadersSupported; }; diff --git a/src/Layers/xrRenderGL/glR_Backend_Runtime.h b/src/Layers/xrRenderGL/glR_Backend_Runtime.h index eb3780b771d..1e456e94935 100644 --- a/src/Layers/xrRenderGL/glR_Backend_Runtime.h +++ b/src/Layers/xrRenderGL/glR_Backend_Runtime.h @@ -168,7 +168,7 @@ ICF void CBackend::set_PS(GLuint _ps, LPCSTR _n) PGO(Msg("PGO:Pshader:%d,%s", _ps, _n ? _n : name)); stat.ps++; ps = _ps; - CHK_GL(glUseProgramStages(HW.pPP, GL_FRAGMENT_SHADER_BIT, ps)); + //CHK_GL(glUseProgramStages(HW.pPP, GL_FRAGMENT_SHADER_BIT, ps)); #ifdef DEBUG ps_name = _n; #endif @@ -187,7 +187,7 @@ ICF void CBackend::set_GS(GLuint _gs, LPCSTR _n) // TODO: OGL: Get statistics for G Shader change //stat.gs ++; gs = _gs; - CHK_GL(glUseProgramStages(HW.pPP, GL_GEOMETRY_SHADER_BIT, gs)); + //CHK_GL(glUseProgramStages(HW.pPP, GL_GEOMETRY_SHADER_BIT, gs)); #ifdef DEBUG gs_name = _n; #endif @@ -205,13 +205,37 @@ ICF void CBackend::set_VS(GLuint _vs, LPCSTR _n) PGO(Msg("PGO:Vshader:%d,%s", _vs, _n ? _n : name)); stat.vs++; vs = _vs; - CHK_GL(glUseProgramStages(HW.pPP, GL_VERTEX_SHADER_BIT, vs)); + //CHK_GL(glUseProgramStages(HW.pPP, GL_VERTEX_SHADER_BIT, vs)); #ifdef DEBUG vs_name = _n; #endif } } +ICF void CBackend::set_PP(GLuint _pp, pcstr _n) +{ + if (pp != _pp) + { +#ifdef RBackend_PGO + string_path name; + if (HW.SeparateShaderObjectsSupported) + glGetObjectLabel(GL_PROGRAM_PIPELINE, _pp, sizeof(name), nullptr, name) + else + glGetObjectLabel(GL_PROGRAM, _pp, sizeof(name), nullptr, name) +#endif + PGO(Msg("PGO:PPshader:%d,%s", _pp, _n ? _n : name)); + stat.pp++; + pp = _pp; + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glBindProgramPipeline(pp)); + else + CHK_GL(glUseProgram(pp)); +#ifdef DEBUG + pp_name = _n; +#endif + } +} + ICF void CBackend::set_Vertices(GLuint _vb, u32 _vb_stride) { if (vb != _vb || vb_stride != _vb_stride) diff --git a/src/Layers/xrRenderGL/glResourceManager_Resources.cpp b/src/Layers/xrRenderGL/glResourceManager_Resources.cpp index a9d9cbc6882..281eeeb61ad 100644 --- a/src/Layers/xrRenderGL/glResourceManager_Resources.cpp +++ b/src/Layers/xrRenderGL/glResourceManager_Resources.cpp @@ -21,6 +21,7 @@ SPass* CResourceManager::_CreatePass(const SPass& proto) P->ps = proto.ps; P->vs = proto.vs; P->gs = proto.gs; + P->pp = proto.pp; P->constants = proto.constants; P->T = proto.T; #ifdef _EDITOR @@ -82,6 +83,90 @@ SDeclaration* CResourceManager::_CreateDecl(D3DVERTEXELEMENT9* dcl) } //-------------------------------------------------------------------------------------------------------------- + +SPP* CResourceManager::_CreatePP(pcstr vs, pcstr ps, pcstr gs, pcstr hs, pcstr ds) +{ + pcstr skinning{}, samples{}; + switch (RImplementation.m_skinning) + { + case -1: skinning = ""; break; + case 0: skinning = "_0"; break; + case 1: skinning = "_1"; break; + case 2: skinning = "_2"; break; + case 3: skinning = "_3"; break; + case 4: skinning = "_4"; break; + default: NODEFAULT; + } + switch (RImplementation.m_MSAASample) + { + case -1: samples = ""; break; + case 0: samples = "_0"; break; + case 1: samples = "_1"; break; + case 2: samples = "_2"; break; + case 3: samples = "_3"; break; + case 4: samples = "_4"; break; + case 5: samples = "_5"; break; + case 6: samples = "_6"; break; + case 7: samples = "_7"; break; + default: NODEFAULT; + } + + string256 name{}; + strconcat(name, vs, skinning, "|", ps, samples, "|", gs/*, "|", hs, "|", ds*/); // XXX: Tesselation + + const auto iterator = m_pp.find(name); + + if (iterator != m_pp.end()) + return iterator->second; + + SPP* pp = xr_new(); + + pp->dwFlags |= xr_resource_flagged::RF_REGISTERED; + m_pp.emplace(pp->set_name(name), pp); + + return pp; +} + +bool CResourceManager::_LinkPP(SPass& pass) +{ + auto& pp = *pass.pp; + if (pp.pp) + return true; + + if (HW.SeparateShaderObjectsSupported) + pp.pp = GLGeneratePipeline(pp.cName.c_str(), pass.ps->sh, pass.vs->sh, pass.gs->sh); + else + { + pp.pp = GLLinkMonolithicProgram(pp.cName.c_str(), pass.ps->sh, pass.vs->sh, pass.gs->sh); + pp.constants.parse(&pp.pp, RC_dest_all); + + pass.ps = nullptr; + pass.vs = nullptr; + pass.gs = nullptr; + } + + return pp.pp != 0; +} + +void CResourceManager::_DeletePP(const SPP* pp) +{ + if (0 == (pp->dwFlags & xr_resource_flagged::RF_REGISTERED)) + return; + + const pstr N = const_cast(*pp->cName); + auto iterator = m_pp.find(N); + + if (iterator != m_pp.end()) + { + m_pp.erase(iterator); + return; + } + + Msg("! ERROR: Failed to find program pipeline '%s'", pp->cName.c_str()); +} + +//-------------------------------------------------------------------------------------------------------------- + SVS* CResourceManager::_CreateVS(cpcstr shader, u32 flags /*= 0*/) { string_path name; diff --git a/src/Layers/xrRenderGL/glr_constants.cpp b/src/Layers/xrRenderGL/glr_constants.cpp index 3940f640f76..f928d1c050b 100644 --- a/src/Layers/xrRenderGL/glr_constants.cpp +++ b/src/Layers/xrRenderGL/glr_constants.cpp @@ -7,7 +7,13 @@ static class cl_sampler : public R_constant_setup { void setup(R_constant* C) override { - CHK_GL(glProgramUniform1i(C->samp.program, C->samp.location, C->samp.index)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glProgramUniform1i(C->samp.program, C->samp.location, C->samp.index)); + else + { + //VERIFY(RCache.pp == C->samp.program); + CHK_GL(glUniform1i(C->samp.location, C->samp.index)); + } } } binder_sampler; @@ -116,7 +122,10 @@ BOOL R_constant_table::parse(void* _desc, u32 destination) C->type = RC_sampler; C->handler = &binder_sampler; R_constant_load& L = C->samp; - L.index = u16(r_index + ((destination & 1) ? 0 : CTexture::rstVertex)); + if (destination & RC_dest_all) + L.index = r_index; + else + L.index = u16(r_index + ((destination & RC_dest_pixel) ? 0 : CTexture::rstVertex)); L.cls = RC_sampler; L.location = r_location; L.program = program; @@ -150,7 +159,7 @@ BOOL R_constant_table::parse(void* _desc, u32 destination) C->name = name; C->destination = destination; C->type = type; - R_constant_load& L = destination & 1 ? C->ps : C->vs; + R_constant_load& L = C->get_load(destination); L.index = r_index; L.cls = r_type; L.location = r_location; @@ -160,7 +169,7 @@ BOOL R_constant_table::parse(void* _desc, u32 destination) { C->destination |= destination; VERIFY (C->type == type); - R_constant_load& L = destination & 1 ? C->ps : C->vs; + R_constant_load& L = C->get_load(destination); L.index = r_index; L.cls = r_type; L.location = r_location; diff --git a/src/Layers/xrRenderGL/glr_constants_cache.h b/src/Layers/xrRenderGL/glr_constants_cache.h index 9ca7359c12b..80f4b078b2b 100644 --- a/src/Layers/xrRenderGL/glr_constants_cache.h +++ b/src/Layers/xrRenderGL/glr_constants_cache.h @@ -15,21 +15,33 @@ class ECORE_API R_constants case RC_2x4: it[0].set(A._11, A._21, A._31, A._41); it[1].set(A._12, A._22, A._32, A._42); - CHK_GL(glProgramUniformMatrix4x2fv(L.program, L.location, 1, GL_TRUE, (float*)&it)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glProgramUniformMatrix4x2fv(L.program, L.location, 1, GL_TRUE, (float*)&it)); + else + CHK_GL(glUniformMatrix4x2fv(L.location, 1, GL_TRUE, (float*)&it)); break; + case RC_3x4: it[0].set(A._11, A._21, A._31, A._41); it[1].set(A._12, A._22, A._32, A._42); it[2].set(A._13, A._23, A._33, A._43); - CHK_GL(glProgramUniformMatrix4x3fv(L.program, L.location, 1, GL_TRUE, (float*)&it)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glProgramUniformMatrix4x3fv(L.program, L.location, 1, GL_TRUE, (float*)&it)); + else + CHK_GL(glUniformMatrix4x3fv(L.location, 1, GL_TRUE, (float*)&it)); break; + case RC_4x4: it[0].set(A._11, A._21, A._31, A._41); it[1].set(A._12, A._22, A._32, A._42); it[2].set(A._13, A._23, A._33, A._43); it[3].set(A._14, A._24, A._34, A._44); - CHK_GL(glProgramUniformMatrix4fv(L.program, L.location, 1, GL_TRUE, (float*)&it)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glProgramUniformMatrix4fv(L.program, L.location, 1, GL_TRUE, (float*)&it)); + else + CHK_GL(glUniformMatrix4fv(L.location, 1, GL_TRUE, (float*)&it)); break; + default: #ifdef DEBUG xrDebug::Fatal(DEBUG_INFO, "Invalid constant run-time-type for '%s'", *C->name); @@ -45,14 +57,26 @@ class ECORE_API R_constants switch (L.cls) { case RC_1x2: - CHK_GL(glProgramUniform2fv(L.program, L.location, 1, (float*)&A)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glProgramUniform2fv(L.program, L.location, 1, (float*)&A)); + else + CHK_GL(glUniform2fv(L.location, 1, (float*)&A)); break; + case RC_1x3: - CHK_GL(glProgramUniform3fv(L.program, L.location, 1, (float*)&A)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glProgramUniform3fv(L.program, L.location, 1, (float*)&A)); + else + CHK_GL(glUniform3fv(L.location, 1, (float*)&A)); break; + case RC_1x4: - CHK_GL(glProgramUniform4fv(L.program, L.location, 1, (float*)&A)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glProgramUniform4fv(L.program, L.location, 1, (float*)&A)); + else + CHK_GL(glUniform4fv(L.location, 1, (float*)&A)); break; + default: #ifdef DEBUG xrDebug::Fatal(DEBUG_INFO, "Invalid constant run-time-type for '%s'", *C->name); @@ -68,14 +92,26 @@ class ECORE_API R_constants switch (L.cls) { case RC_1x2: - CHK_GL(glProgramUniform2f(L.program, L.location, x, y)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glProgramUniform2f(L.program, L.location, x, y)); + else + CHK_GL(glUniform2f(L.location, x, y)); break; + case RC_1x3: - CHK_GL(glProgramUniform3f(L.program, L.location, x, y, z)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glProgramUniform3f(L.program, L.location, x, y, z)); + else + CHK_GL(glUniform3f(L.location, x, y, z)); break; + case RC_1x4: - CHK_GL(glProgramUniform4f(L.program, L.location, x, y, z, w)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glProgramUniform4f(L.program, L.location, x, y, z, w)); + else + CHK_GL(glUniform4f(L.location, x, y, z, w)); break; + default: #ifdef DEBUG xrDebug::Fatal(DEBUG_INFO, "Invalid constant run-time-type for '%s'", *C->name); @@ -90,14 +126,20 @@ class ECORE_API R_constants { VERIFY(RC_float == C->type); VERIFY(RC_1x1 == L.cls); - CHK_GL(glProgramUniform1f(L.program, L.location, A)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glProgramUniform1f(L.program, L.location, A)); + else + CHK_GL(glUniform1f(L.location, A)); } ICF void set(R_constant* C, R_constant_load& L, int A) { VERIFY(RC_int == C->type); VERIFY(RC_1x1 == L.cls); - CHK_GL(glProgramUniform1i(L.program, L.location, A)); + if (HW.SeparateShaderObjectsSupported) + CHK_GL(glProgramUniform1i(L.program, L.location, A)); + else + CHK_GL(glUniform1i(L.location, A)); } public: @@ -107,6 +149,7 @@ class ECORE_API R_constants if (C->destination & RC_dest_pixel) { set(C, C->ps, A); } if (C->destination & RC_dest_vertex) { set(C, C->vs, A); } if (C->destination & RC_dest_geometry) { set(C, C->gs, A); } + if (C->destination & RC_dest_all) { set(C, C->pp, A); } } ICF void set(R_constant* C, const Fvector4& A) @@ -114,6 +157,7 @@ class ECORE_API R_constants if (C->destination & RC_dest_pixel) { set(C, C->ps, A); } if (C->destination & RC_dest_vertex) { set(C, C->vs, A); } if (C->destination & RC_dest_geometry) { set(C, C->gs, A); } + if (C->destination & RC_dest_all) { set(C, C->pp, A); } } ICF void set(R_constant* C, float x, float y, float z, float w) @@ -121,6 +165,7 @@ class ECORE_API R_constants if (C->destination & RC_dest_pixel) { set(C, C->ps, x, y, z, w); } if (C->destination & RC_dest_vertex) { set(C, C->vs, x, y, z, w); } if (C->destination & RC_dest_geometry) { set(C, C->gs, x, y, z, w); } + if (C->destination & RC_dest_all) { set(C, C->pp, x, y, z, w); } } // scalars, non-array versions @@ -129,6 +174,7 @@ class ECORE_API R_constants if (C->destination & RC_dest_pixel) { set(C, C->ps, A); } if (C->destination & RC_dest_vertex) { set(C, C->vs, A); } if (C->destination & RC_dest_geometry) { set(C, C->gs, A); } + if (C->destination & RC_dest_all) { set(C, C->pp, A); } } ICF void set(R_constant* C, int A) @@ -136,6 +182,7 @@ class ECORE_API R_constants if (C->destination & RC_dest_pixel) { set(C, C->ps, A); } if (C->destination & RC_dest_vertex) { set(C, C->vs, A); } if (C->destination & RC_dest_geometry) { set(C, C->gs, A); } + if (C->destination & RC_dest_all) { set(C, C->pp, A); } } // fp, array versions @@ -145,6 +192,7 @@ class ECORE_API R_constants if (C->destination & RC_dest_pixel) { L = C->ps; } if (C->destination & RC_dest_vertex) { L = C->vs; } if (C->destination & RC_dest_geometry) { L = C->gs; } + if (C->destination & RC_dest_all) { L = C->pp; } L.location += e; set(C, L, A); } @@ -155,6 +203,7 @@ class ECORE_API R_constants if (C->destination & RC_dest_pixel) { L = C->ps; } if (C->destination & RC_dest_vertex) { L = C->vs; } if (C->destination & RC_dest_geometry) { L = C->gs; } + if (C->destination & RC_dest_all) { L = C->pp; } L.location += e; set(C, L, A); } @@ -165,6 +214,7 @@ class ECORE_API R_constants if (C->destination & RC_dest_pixel) { L = C->ps; } if (C->destination & RC_dest_vertex) { L = C->vs; } if (C->destination & RC_dest_geometry) { L = C->gs; } + if (C->destination & RC_dest_all) { L = C->pp; } L.location += e; set(C, L, x, y, z, w); } diff --git a/src/Layers/xrRenderPC_GL/r2_test_hw.cpp b/src/Layers/xrRenderPC_GL/r2_test_hw.cpp index 523c72b0a4e..4f10385df18 100644 --- a/src/Layers/xrRenderPC_GL/r2_test_hw.cpp +++ b/src/Layers/xrRenderPC_GL/r2_test_hw.cpp @@ -48,12 +48,6 @@ bool TestOpenGLSupport() Log("~ Could not initialize glew."); return false; } - - if (!glewIsSupported("GL_ARB_separate_shader_objects")) - { - Log("~ GL_ARB_separate_shader_objects not supported"); - return false; - } return true; } diff --git a/src/Layers/xrRenderPC_GL/rgl_shaders.cpp b/src/Layers/xrRenderPC_GL/rgl_shaders.cpp index b1b6d10e9d8..5fadaec5717 100644 --- a/src/Layers/xrRenderPC_GL/rgl_shaders.cpp +++ b/src/Layers/xrRenderPC_GL/rgl_shaders.cpp @@ -23,8 +23,8 @@ static GLuint create_shader(pcstr* buffer, size_t const buffer_size, cpcstr file if (output != 0) { result->sh = output; - VERIFY(type == 'p'); - result->constants.parse(&output, ShaderTypeTraits::GetShaderDest()); + if (type == 'p') + result->constants.parse(&output, ShaderTypeTraits::GetShaderDest()); } return output; } @@ -496,9 +496,9 @@ HRESULT CRender::shader_compile(pcstr name, IReader* fs, pcstr pFunctionName, strncpy_s(extension, pTarget, 2); u32 fileCrc = 0; - string_path filename, full_path; + string_path filename, full_path{}; strconcat(sizeof(filename), filename, "gl" DELIMITER, name, ".", extension, DELIMITER, sh_name.c_str()); - if (HW.ShaderBinarySupported) + if (HW.ShaderBinarySupported && HW.SeparateShaderObjectsSupported) { string_path file; strconcat(sizeof(file), file, "shaders_cache_oxr" DELIMITER, filename); @@ -512,7 +512,7 @@ HRESULT CRender::shader_compile(pcstr name, IReader* fs, pcstr pFunctionName, } GLuint program = 0; - if (HW.ShaderBinarySupported && FS.exist(full_path)) + if (HW.ShaderBinarySupported && HW.SeparateShaderObjectsSupported && FS.exist(full_path)) { IReader* file = FS.r_open(full_path); if (file->length() > 8) @@ -550,7 +550,7 @@ HRESULT CRender::shader_compile(pcstr name, IReader* fs, pcstr pFunctionName, if (!program) { #ifdef DEBUG - Log("- Compile shader:", full_path); + Log("- Compile shader:", filename); #endif // Compile sources list shader_sources_manager sources(name); @@ -559,16 +559,16 @@ HRESULT CRender::shader_compile(pcstr name, IReader* fs, pcstr pFunctionName, // Compile the shader from sources program = create_shader(pTarget, sources.get(), sources.length(), filename, result, nullptr); - if (HW.ShaderBinarySupported && program) + if (HW.ShaderBinarySupported && HW.SeparateShaderObjectsSupported && program) { GLint binaryLength{}; GLenum binaryFormat{}; - glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binaryLength); + CHK_GL(glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binaryLength)); GLvoid* binary = binaryLength ? xr_malloc(binaryLength) : nullptr; if (binary) { - glGetProgramBinary(program, binaryLength, nullptr, &binaryFormat, binary); + CHK_GL(glGetProgramBinary(program, binaryLength, nullptr, &binaryFormat, binary)); IWriter* file = FS.w_open(full_path); file->w_string(HW.AdapterName); diff --git a/src/Layers/xrRenderPC_GL/stdafx.h b/src/Layers/xrRenderPC_GL/stdafx.h index 95696b94de1..95a9be4eb0d 100644 --- a/src/Layers/xrRenderPC_GL/stdafx.h +++ b/src/Layers/xrRenderPC_GL/stdafx.h @@ -17,7 +17,6 @@ #define GLEW_STATIC #include #include "SDL_opengl.h" -#include #include "SDL_opengl_glext.h" #include "Layers/xrRenderGL/CommonTypes.h" diff --git a/src/Layers/xrRenderPC_R1/FStaticRender.cpp b/src/Layers/xrRenderPC_R1/FStaticRender.cpp index dcf6bf73927..6be861f4fd8 100644 --- a/src/Layers/xrRenderPC_R1/FStaticRender.cpp +++ b/src/Layers/xrRenderPC_R1/FStaticRender.cpp @@ -93,7 +93,13 @@ void CRender::create() o.disasm = (strstr(Core.Params, "-disasm")) ? TRUE : FALSE; o.forceskinw = (strstr(Core.Params, "-skinw")) ? TRUE : FALSE; o.no_detail_textures = !ps_r2_ls_flags.test(R1FLAG_DETAIL_TEXTURES); + c_ldynamic_props = "L_dynamic_props"; + c_sbase = "s_base"; + c_ssky0 = "s_sky0"; + c_ssky1 = "s_sky1"; + c_sclouds0 = "s_clouds0"; + c_sclouds1 = "s_clouds1"; o.no_ram_textures = (strstr(Core.Params, "-noramtex")) ? TRUE : ps_r__common_flags.test(RFLAG_NO_RAM_TEXTURES); if (o.no_ram_textures) diff --git a/src/Layers/xrRenderPC_R1/FStaticRender.h b/src/Layers/xrRenderPC_R1/FStaticRender.h index 147706e4b4b..693e0712fda 100644 --- a/src/Layers/xrRenderPC_R1/FStaticRender.h +++ b/src/Layers/xrRenderPC_R1/FStaticRender.h @@ -5,6 +5,7 @@ #include "Layers/xrRender/DetailManager.h" #include "GlowManager.h" #include "Layers/xrRender/WallmarksEngine.h" +#include "FStaticRender_Types.h" #include "FStaticRender_RenderTarget.h" #include "Layers/xrRender/ModelPool.h" #include "LightShadows.h" @@ -74,7 +75,14 @@ class CRender : public D3DXRenderBase cl_light_PR r1_dlight_binder_PR; cl_light_C r1_dlight_binder_color; cl_light_XFORM r1_dlight_binder_xform; + shared_str c_ldynamic_props; + shared_str c_sbase; + shared_str c_ssky0; + shared_str c_ssky1; + shared_str c_sclouds0; + shared_str c_sclouds1; + bool m_bMakeAsyncSS; bool m_bFirstFrameAfterReset; // Determines weather the frame is the first after resetting device. diff --git a/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.cpp b/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.cpp index 2a0caad52ec..af31cabe2c0 100644 --- a/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.cpp +++ b/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.cpp @@ -1,6 +1,5 @@ #include "stdafx.h" -#include "fstaticrender_rendertarget.h" -#include "FStaticRender_Types.h" +#include "FStaticRender_RenderTarget.h" #include "xrEngine/IGame_Persistent.h" CRenderTarget::CRenderTarget() diff --git a/src/Layers/xrRenderPC_R1/FStaticRender_Types.h b/src/Layers/xrRenderPC_R1/FStaticRender_Types.h index d8f442f49f0..f02ce353430 100644 --- a/src/Layers/xrRenderPC_R1/FStaticRender_Types.h +++ b/src/Layers/xrRenderPC_R1/FStaticRender_Types.h @@ -18,3 +18,7 @@ #define r1_RT_async_ss "$user$async_ss" // surface +#define r2_T_sky0 "$user$sky0" +#define r2_T_sky1 "$user$sky1" + +#define r2_RT_luminance_cur "$user$tonemap" // --- result diff --git a/src/Layers/xrRenderPC_R1/LightShadows.cpp b/src/Layers/xrRenderPC_R1/LightShadows.cpp index 3e1806f5f6b..2f240f234b9 100644 --- a/src/Layers/xrRenderPC_R1/LightShadows.cpp +++ b/src/Layers/xrRenderPC_R1/LightShadows.cpp @@ -1,6 +1,5 @@ #include "stdafx.h" #include "LightShadows.h" -#include "FStaticRender_Types.h" #include "Layers/xrRender/LightTrack.h" #include "xrEngine/xr_object.h" #include "Layers/xrRender/FBasicVisual.h" diff --git a/src/Layers/xrRender_R2/r2.cpp b/src/Layers/xrRender_R2/r2.cpp index 066f335623b..cbe7a53335e 100644 --- a/src/Layers/xrRender_R2/r2.cpp +++ b/src/Layers/xrRender_R2/r2.cpp @@ -601,6 +601,10 @@ void CRender::create() c_lmaterial = "L_material"; c_sbase = "s_base"; c_snoise = "s_noise"; + c_ssky0 = "s_sky0"; + c_ssky1 = "s_sky1"; + c_sclouds0 = "s_clouds0"; + c_sclouds1 = "s_clouds1"; m_bMakeAsyncSS = false; diff --git a/src/Layers/xrRender_R2/r2.h b/src/Layers/xrRender_R2/r2.h index 0a36465e8a4..a65e047caec 100644 --- a/src/Layers/xrRender_R2/r2.h +++ b/src/Layers/xrRender_R2/r2.h @@ -186,6 +186,10 @@ class CRender final : public D3DXRenderBase shared_str c_sbase; shared_str c_snoise; shared_str c_lmaterial; + shared_str c_ssky0; + shared_str c_ssky1; + shared_str c_sclouds0; + shared_str c_sclouds1; float o_hemi; float o_hemi_cube[CROS_impl::NUM_FACES]; float o_sun; diff --git a/src/xrGame/GamePersistent.cpp b/src/xrGame/GamePersistent.cpp index 80bef3441e7..64258f35455 100644 --- a/src/xrGame/GamePersistent.cpp +++ b/src/xrGame/GamePersistent.cpp @@ -217,11 +217,6 @@ void CGamePersistent::RegisterModel(IRenderVisual* V) extern void clean_game_globals(); extern void init_game_globals(); -void CGamePersistent::create_main_menu(Task&, void*) -{ - m_pMainMenu = xr_new(); -} - void CGamePersistent::OnAppStart() { // load game materials @@ -239,8 +234,7 @@ void CGamePersistent::OnAppStart() SetupUIStyle(); GEnv.UI = xr_new(); - - const auto& menuCreated = TaskScheduler->AddTask("CMainMenu::CMainMenu()", { this, &CGamePersistent::create_main_menu }); + m_pMainMenu = xr_new(); inherited::OnAppStart(); @@ -256,7 +250,6 @@ void CGamePersistent::OnAppStart() #ifdef XR_PLATFORM_WINDOWS TaskScheduler->Wait(initializeGlobals); #endif - TaskScheduler->Wait(menuCreated); } void CGamePersistent::OnAppEnd() diff --git a/src/xrGame/GamePersistent.h b/src/xrGame/GamePersistent.h index 788c3befa28..cdf14488c4b 100644 --- a/src/xrGame/GamePersistent.h +++ b/src/xrGame/GamePersistent.h @@ -49,8 +49,6 @@ class CGamePersistent : public IGame_Persistent, public IEventReceiver void start_game_intro(); void update_game_intro(); - void create_main_menu(Task& task, void* data); - #ifdef DEBUG u32 m_frame_counter; u32 m_last_stats_frame;