From 6392d3063410e32b4855c14c4c1c20bc86f54961 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Tue, 24 Nov 2015 21:28:55 +0100 Subject: [PATCH] Shader: Implement geometry shader support. --- src/Layers/xrRender/R_Backend.h | 8 +- src/Layers/xrRender/ResourceManager.h | 9 +- src/Layers/xrRender/SH_Atomic.cpp | 10 +- src/Layers/xrRender/SH_Atomic.h | 6 +- src/Layers/xrRender/SH_Texture.h | 2 +- src/Layers/xrRender/Shader.cpp | 2 +- src/Layers/xrRender/Shader.h | 2 +- .../glResourceManager_Resources.cpp | 279 +++++++++++------- 8 files changed, 199 insertions(+), 119 deletions(-) diff --git a/src/Layers/xrRender/R_Backend.h b/src/Layers/xrRender/R_Backend.h index b5c08999d8c..2ac61958c88 100644 --- a/src/Layers/xrRender/R_Backend.h +++ b/src/Layers/xrRender/R_Backend.h @@ -173,7 +173,7 @@ class ECORE_API CBackend CTexture* textures_ps [CTexture::mtMaxPixelShaderTextures]; // stages //CTexture* textures_vs [5 ]; // dmap + 4 vs CTexture* textures_vs [CTexture::mtMaxVertexShaderTextures]; // 4 vs -#if defined(USE_DX10) || defined(USE_DX11) +#if defined(USE_DX10) || defined(USE_DX11) || defined(USE_OGL) CTexture* textures_gs [CTexture::mtMaxGeometryShaderTextures]; // 4 vs # ifdef USE_DX11 CTexture* textures_hs [CTexture::mtMaxHullShaderTextures]; // 4 vs @@ -295,8 +295,12 @@ class ECORE_API CBackend #endif // USE_OGL ICF void set_PS (ref_ps& _ps) { set_PS(_ps->ps,_ps->cName.c_str()); } -#if defined(USE_DX10) || defined(USE_DX11) +#if defined(USE_DX10) || defined(USE_DX11) || defined(USE_OGL) +#ifdef USE_OGL + ICF void set_GS (GLuint _gs, LPCSTR _n=0); +#else ICF void set_GS (ID3DGeometryShader* _gs, LPCSTR _n=0); +#endif // USE_OGL ICF void set_GS (ref_gs& _gs) { set_GS(_gs->gs,_gs->cName.c_str()); } # ifdef USE_DX11 diff --git a/src/Layers/xrRender/ResourceManager.h b/src/Layers/xrRender/ResourceManager.h index 7aa51339d17..8f1444e0462 100644 --- a/src/Layers/xrRender/ResourceManager.h +++ b/src/Layers/xrRender/ResourceManager.h @@ -35,7 +35,7 @@ class ECORE_API CResourceManager DEFINE_MAP_PRED(const char*,CRT*, map_RT, map_RTIt, str_pred); // DX10 cut DEFINE_MAP_PRED(const char*,CRTC*, map_RTC, map_RTCIt, str_pred); DEFINE_MAP_PRED(const char*,SVS*, map_VS, map_VSIt, str_pred); -#if defined(USE_DX10) || defined(USE_DX11) +#if defined(USE_DX10) || defined(USE_DX11) || defined(USE_OGL) DEFINE_MAP_PRED(const char*,SGS*, map_GS, map_GSIt, str_pred); #endif // USE_DX10 #ifdef USE_DX11 @@ -56,7 +56,7 @@ class ECORE_API CResourceManager // DX10 cut map_RTC m_rtargets_c; map_VS m_vs; map_PS m_ps; -#if defined(USE_DX10) || defined(USE_DX11) +#if defined(USE_DX10) || defined(USE_DX11) || defined(USE_OGL) map_GS m_gs; #endif // USE_DX10 map_TD m_td; @@ -145,7 +145,7 @@ class ECORE_API CResourceManager // DX10 cut CRTC* _CreateRTC (LPCSTR Name, u32 size, D3DFORMAT f); // DX10 cut void _DeleteRTC (const CRTC* RT ); -#if defined(USE_DX10) || defined(USE_DX11) +#if defined(USE_DX10) || defined(USE_DX11) || defined(USE_OGL) SGS* _CreateGS (LPCSTR Name); void _DeleteGS (const SGS* GS ); #endif // USE_DX10 @@ -174,6 +174,9 @@ class ECORE_API CResourceManager SState* _CreateState (SimulatorStates& Code); void _DeleteState (const SState* SB); +#ifdef USE_OGL + SDeclaration* _CreateDecl (u32 FVF); +#endif // USE_OGL SDeclaration* _CreateDecl (D3DVERTEXELEMENT9* dcl); void _DeleteDecl (const SDeclaration* dcl); diff --git a/src/Layers/xrRender/SH_Atomic.cpp b/src/Layers/xrRender/SH_Atomic.cpp index 6b62607d4f0..3bdb9be5788 100644 --- a/src/Layers/xrRender/SH_Atomic.cpp +++ b/src/Layers/xrRender/SH_Atomic.cpp @@ -48,12 +48,16 @@ SPS::~SPS() RImplementation.Resources->_DeletePS(this); } -#if defined(USE_DX10) || defined(USE_DX11) +#if defined(USE_DX10) || defined(USE_DX11) || defined(USE_OGL) /////////////////////////////////////////////////////////////////////// // SGS SGS::~SGS () { - _RELEASE(gs); +#ifdef USE_OGL + CHK_GL(glDeleteProgram(gs)); +#else + _RELEASE(gs); +#endif // USE_OGL RImplementation.Resources->_DeleteGS(this); } @@ -74,7 +78,9 @@ SCS::~SCS () RImplementation.Resources->_DeleteCS(this); } # endif +#endif // USE_DX10 +#if defined(USE_DX10) || defined(USE_DX11) /////////////////////////////////////////////////////////////////////// // SInputSignature SInputSignature::SInputSignature(ID3DBlob* pBlob) { VERIFY(pBlob); signature=pBlob; signature->AddRef();}; diff --git a/src/Layers/xrRender/SH_Atomic.h b/src/Layers/xrRender/SH_Atomic.h index c67e6abd4b5..a70e310d494 100644 --- a/src/Layers/xrRender/SH_Atomic.h +++ b/src/Layers/xrRender/SH_Atomic.h @@ -54,11 +54,15 @@ struct ECORE_API SPS : public xr_resource_named }; typedef resptr_core > ref_ps; -#if defined(USE_DX10) || defined(USE_DX11) +#if defined(USE_DX10) || defined(USE_DX11) || defined(USE_OGL) ////////////////////////////////////////////////////////////////////////// struct ECORE_API SGS : public xr_resource_named { +#ifdef USE_OGL + GLuint gs; +#else ID3DGeometryShader* gs; +#endif // USE_OGL R_constant_table constants; ~SGS (); }; diff --git a/src/Layers/xrRender/SH_Texture.h b/src/Layers/xrRender/SH_Texture.h index e4b5c429e40..9737c065303 100644 --- a/src/Layers/xrRender/SH_Texture.h +++ b/src/Layers/xrRender/SH_Texture.h @@ -10,7 +10,7 @@ class CTheoraSurface; class ECORE_API CTexture : public xr_resource_named { public: -#if defined(USE_DX10) || defined(USE_DX11) +#if defined(USE_DX10) || defined(USE_DX11) || defined(USE_OGL) enum MaxTextures { // Actually these values are 128 diff --git a/src/Layers/xrRender/Shader.cpp b/src/Layers/xrRender/Shader.cpp index afefb740f3f..88a12397174 100644 --- a/src/Layers/xrRender/Shader.cpp +++ b/src/Layers/xrRender/Shader.cpp @@ -59,7 +59,7 @@ BOOL SPass::equal(const SPass& other) if (state != other.state) return FALSE; if (ps != other.ps) return FALSE; if (vs != other.vs) return FALSE; -#if defined(USE_DX10) || defined(USE_DX11) +#if defined(USE_DX10) || defined(USE_DX11) || defined(USE_OGL) if (gs != other.gs) return FALSE; # ifdef USE_DX11 if (hs != other.hs) return FALSE; diff --git a/src/Layers/xrRender/Shader.h b/src/Layers/xrRender/Shader.h index a713ee7de97..9f812b6a29c 100644 --- a/src/Layers/xrRender/Shader.h +++ b/src/Layers/xrRender/Shader.h @@ -89,7 +89,7 @@ struct ECORE_API SPass : public xr_resource_flagged { ref_state state; // Generic state, like Z-Buffering, samplers, etc ref_ps ps; // may be NULL = FFP, in that case "state" must contain TSS setup ref_vs vs; // may be NULL = FFP, in that case "state" must contain RS setup, *and* FVF-compatible declaration must be used -#if defined(USE_DX10) || defined(USE_DX11) +#if defined(USE_DX10) || defined(USE_DX11) || defined(USE_OGL) ref_gs gs; // may be NULL = don't use geometry shader at all # ifdef USE_DX11 ref_hs hs; // may be NULL = don't use hull shader at all diff --git a/src/Layers/xrRenderPC_GL/glResourceManager_Resources.cpp b/src/Layers/xrRenderPC_GL/glResourceManager_Resources.cpp index 6ccffe7b0e1..d4eb4991b11 100644 --- a/src/Layers/xrRenderPC_GL/glResourceManager_Resources.cpp +++ b/src/Layers/xrRenderPC_GL/glResourceManager_Resources.cpp @@ -68,23 +68,24 @@ void CResourceManager::_DeleteState (const SState* state) } //-------------------------------------------------------------------------------------------------------------- -SPass* CResourceManager::_CreatePass (ref_state& _state, ref_ps& _ps, ref_vs& _vs, ref_ctable& _ctable, ref_texture_list& _T, ref_matrix_list& _M, ref_constant_list& _C) +SPass* CResourceManager::_CreatePass (const SPass& proto) { for (u32 it=0; itequal(_state,_ps,_vs,_ctable,_T,_M,_C)) + if (v_passes[it]->equal(proto)) return v_passes[it]; - - SPass* P = new SPass(); - P->dwFlags |= xr_resource_flagged::RF_REGISTERED; - P->state = _state; - P->ps = _ps; - P->vs = _vs; - P->constants = _ctable; - P->T = _T; + + SPass* P = xr_new(); + P->dwFlags |= xr_resource_flagged::RF_REGISTERED; + P->state = proto.state; + P->ps = proto.ps; + P->vs = proto.vs; + P->gs = proto.gs; + P->constants = proto.constants; + P->T = proto.T; #ifdef _EDITOR - P->M = _M; + P->M = proto.M; #endif - P->C = _C; + P->C = proto.C; v_passes.push_back (P); return v_passes.back(); @@ -117,10 +118,10 @@ SDeclaration* CResourceManager::_CreateDecl (u32 FVF) } SDeclaration* D = new SDeclaration(); - glGenVertexArrays(1, &D->vao); + glGenVertexArrays(1, &D->dcl); D->FVF = FVF; - glBufferUtils::ConvertVertexDeclaration(FVF, D->vao); + glBufferUtils::ConvertVertexDeclaration(FVF, D->dcl); D->dwFlags |= xr_resource_flagged::RF_REGISTERED; v_declarations.push_back(D); @@ -137,12 +138,12 @@ SDeclaration* CResourceManager::_CreateDecl(D3DVERTEXELEMENT9* dcl) } SDeclaration* D = new SDeclaration(); - glGenVertexArrays(1, &D->vao); + glGenVertexArrays(1, &D->dcl); D->FVF = 0; u32 dcl_size = glBufferUtils::GetDeclLength(dcl) + 1; D->dcl_code.assign(dcl, dcl + dcl_size); - glBufferUtils::ConvertVertexDeclaration(dcl, D->vao); + glBufferUtils::ConvertVertexDeclaration(dcl, D->dcl); D->dwFlags |= xr_resource_flagged::RF_REGISTERED; v_declarations.push_back(D); @@ -160,63 +161,68 @@ void CResourceManager::_DeleteDecl (const SDeclaration* dcl) SVS* CResourceManager::_CreateVS (LPCSTR _name) { string_path name; - strcpy_s(name, _name); - if (0 == ::Render->m_skinning) strcat(name, "_0"); - if (1 == ::Render->m_skinning) strcat(name, "_1"); - if (2 == ::Render->m_skinning) strcat(name, "_2"); - if (3 == ::Render->m_skinning) strcat(name, "_3"); - if (4 == ::Render->m_skinning) strcat(name, "_4"); - LPSTR N = LPSTR(name); - map_VS::iterator I = m_vs.find(N); - if (I != m_vs.end()) return I->second; + xr_strcpy (name,_name); + if (0 == GlobalEnv.Render->m_skinning) xr_strcat(name,"_0"); + if (1 == GlobalEnv.Render->m_skinning) xr_strcat(name,"_1"); + if (2 == GlobalEnv.Render->m_skinning) xr_strcat(name,"_2"); + if (3 == GlobalEnv.Render->m_skinning) xr_strcat(name,"_3"); + if (4 == GlobalEnv.Render->m_skinning) xr_strcat(name,"_4"); + LPSTR N = LPSTR (name); + map_VS::iterator I = m_vs.find (N); + if (I!=m_vs.end()) return I->second; else { - SVS* _vs = new SVS(); - _vs->dwFlags |= xr_resource_flagged::RF_REGISTERED; - m_vs.insert(mk_pair(_vs->set_name(name), _vs)); + SVS* _vs = xr_new (); + _vs->dwFlags |= xr_resource_flagged::RF_REGISTERED; + m_vs.insert (mk_pair(_vs->set_name(name),_vs)); //_vs->vs = NULL; //_vs->signature = NULL; VERIFY(strcmpi(name, "null") != 0); - GLchar* pErrorBuf = NULL; + string_path shName; + { + const char* pchr = strchr(_name, '('); + ptrdiff_t size = pchr?pchr-_name:xr_strlen(_name); + strncpy(shName, _name, size); + shName[size] = 0; + } + string_path cname; - strconcat(sizeof(cname), cname, ::Render->getShaderPath(), _name, ".vs"); - FS.update_path(cname, "$game_shaders$", cname); + strconcat (sizeof(cname),cname,GlobalEnv.Render->getShaderPath(),/*_name*/shName,".vs"); + FS.update_path (cname, "$game_shaders$", cname); // LPCSTR target = NULL; - - IReader* fs = FS.r_open(cname); + + // duplicate and zero-terminate + IReader* file = FS.r_open(cname); // TODO: OGL: HACK: Implement all shaders. Remove this for PS - if (!fs) + if (!file) { string1024 tmp; - sprintf(tmp, "OGL: %s is missing. Replace with stub_default.vs", cname); - Msg(tmp); - strconcat(sizeof(cname), cname, ::Render->getShaderPath(), "stub_default", ".vs"); - FS.update_path(cname, "$game_shaders$", cname); - fs = FS.r_open(cname); + xr_sprintf (tmp, "DX10: %s is missing. Replace with stub_default.vs", cname); + Msg (tmp); + strconcat (sizeof(cname), cname,GlobalEnv.Render->getShaderPath(),"stub_default",".vs"); + FS.update_path (cname, "$game_shaders$", cname); + file = FS.r_open(cname); } - R_ASSERT3(fs, "shader file doesnt exist", cname); + u32 const size = file->length(); + char* const data = (LPSTR)_alloca(size + 1); + CopyMemory ( data, file->pointer(), size ); + data[size] = 0; + FS.r_close ( file ); - // vertex - R_ASSERT2(fs, cname); + // Select target _vs->vs = glCreateShader(GL_VERTEX_SHADER); - GLenum _result = ::Render->shader_compile(name, LPCSTR(fs->pointer()), fs->length(), NULL, NULL, NULL, NULL, 0, &_vs->vs, &pErrorBuf, NULL); - FS.r_close(fs); + void* _result = &_vs->vs; + HRESULT const _hr = GlobalEnv.Render->shader_compile(name,(DWORD const*)data,size, NULL, NULL, NULL, _result ); - if (_result == GL_TRUE) - { - // Parse constant, texture, sampler binding - _vs->constants.parse(&_vs->vs, RC_dest_vertex); - } - else - { - VERIFY(pErrorBuf); - Log("! VS: ", _name); - Log("! error: ", pErrorBuf); - } - R_ASSERT2(_result, pErrorBuf); - xr_free(pErrorBuf); - return _vs; + VERIFY(SUCCEEDED(_hr)); + + CHECK_OR_EXIT ( + !FAILED(_hr), + make_string("Your video card doesn't meet game requirements.\n\nTry to lower game settings.") + ); + + return _vs; } } @@ -237,77 +243,70 @@ SPS* CResourceManager::_CreatePS (LPCSTR _name) { string_path name; strcpy_s(name, _name); - if (0 == ::Render->m_MSAASample) strcat(name, "_0"); - if (1 == ::Render->m_MSAASample) strcat(name, "_1"); - if (2 == ::Render->m_MSAASample) strcat(name, "_2"); - if (3 == ::Render->m_MSAASample) strcat(name, "_3"); - if (4 == ::Render->m_MSAASample) strcat(name, "_4"); - if (5 == ::Render->m_MSAASample) strcat(name, "_5"); - if (6 == ::Render->m_MSAASample) strcat(name, "_6"); - if (7 == ::Render->m_MSAASample) strcat(name, "_7"); - LPSTR N = LPSTR(name); - map_PS::iterator I = m_ps.find(N); + if (0 == GlobalEnv.Render->m_MSAASample) strcat(name, "_0"); + if (1 == GlobalEnv.Render->m_MSAASample) strcat(name, "_1"); + if (2 == GlobalEnv.Render->m_MSAASample) strcat(name, "_2"); + if (3 == GlobalEnv.Render->m_MSAASample) strcat(name, "_3"); + if (4 == GlobalEnv.Render->m_MSAASample) strcat(name, "_4"); + if (5 == GlobalEnv.Render->m_MSAASample) strcat(name, "_5"); + if (6 == GlobalEnv.Render->m_MSAASample) strcat(name, "_6"); + if (7 == GlobalEnv.Render->m_MSAASample) strcat(name, "_7"); + LPSTR N = LPSTR(name); + map_PS::iterator I = m_ps.find (N); if (I != m_ps.end()) return I->second; else { - SPS* _ps = new SPS(); - _ps->dwFlags |= xr_resource_flagged::RF_REGISTERED; - m_ps.insert(mk_pair(_ps->set_name(name), _ps)); + SPS* _ps = xr_new (); + _ps->dwFlags |= xr_resource_flagged::RF_REGISTERED; + m_ps.insert (mk_pair(_ps->set_name(name),_ps)); VERIFY(strcmpi(name, "null") != 0); + string_path shName; + const char* pchr = strchr(_name, '('); + ptrdiff_t strSize = pchr?pchr-_name:xr_strlen(_name); + strncpy(shName, _name, strSize ); + shName[strSize] = 0; + // Open file string_path cname; - strconcat(sizeof(cname), cname, ::Render->getShaderPath(), _name, ".ps"); - FS.update_path(cname, "$game_shaders$", cname); + strconcat (sizeof(cname), cname,GlobalEnv.Render->getShaderPath(),/*_name*/shName,".ps"); + FS.update_path (cname, "$game_shaders$", cname); // duplicate and zero-terminate - IReader* R = FS.r_open(cname); + IReader* R = FS.r_open(cname); // TODO: DX10: HACK: Implement all shaders. Remove this for PS if (!R) { string1024 tmp; // TODO: HACK: Test failure //Memory.mem_compact(); - sprintf(tmp, "OGL: %s is missing. Replace with stub_default.ps", cname); - Msg(tmp); - strconcat(sizeof(cname), cname, ::Render->getShaderPath(), "stub_default", ".ps"); - FS.update_path(cname, "$game_shaders$", cname); - R = FS.r_open(cname); + xr_sprintf (tmp, "OGL: %s is missing. Replace with stub_default.ps", cname); + Msg (tmp); + strconcat (sizeof(cname), cname,GlobalEnv.Render->getShaderPath(),"stub_default",".ps"); + FS.update_path (cname, "$game_shaders$", cname); + R = FS.r_open(cname); } - R_ASSERT2(R, cname); - u32 size = R->length(); - char* data = xr_alloc(size + 1); - CopyMemory(data, R->pointer(), size); - data[size] = 0; - FS.r_close(R); - - // Compile - GLchar* pErrorBuf = NULL; - _ps->ps = glCreateShader(GL_FRAGMENT_SHADER); - GLenum _result = ::Render->shader_compile(name, data, size, NULL, NULL, NULL, NULL, 0, &_ps->ps, &pErrorBuf, NULL); - xr_free(data); - if (_result == GL_TRUE) - { - // Parse constant, texture, sampler binding - _ps->constants.parse(&_ps->ps, RC_dest_pixel); - } - else - { - VERIFY(pErrorBuf); - Log("! PS: ", _name); - Msg("error is %s", pErrorBuf); - } - R_ASSERT2(_result, pErrorBuf); - xr_free(pErrorBuf); + IReader* file = FS.r_open(cname); + R_ASSERT2 ( file, cname ); + u32 const size = file->length(); + char* const data = (LPSTR)_alloca(size + 1); + CopyMemory ( data, file->pointer(), size ); + data[size] = 0; + FS.r_close ( file ); - if (_result == GL_FALSE) - Msg("Can't compile shader %s", _name); + // Select target + _ps->ps = glCreateShader(GL_FRAGMENT_SHADER); + void* _result = &_ps->ps; + HRESULT const _hr = GlobalEnv.Render->shader_compile(name,(DWORD const*)data,size, NULL, NULL, NULL, _result); + + VERIFY(SUCCEEDED(_hr)); CHECK_OR_EXIT( - _result != GL_FALSE, - make_string("Your video card doesn't meet game requirements\n\nPixel Shaders v1.1 or higher required") + !FAILED(_hr), + make_string("Your video card doesn't meet game requirements.\n\nTry to lower game settings.") ); + return _ps; } } @@ -323,6 +322,70 @@ void CResourceManager::_DeletePS (const SPS* ps) Msg ("! ERROR: Failed to find compiled pixel-shader '%s'",*ps->cName); } +//-------------------------------------------------------------------------------------------------------------- +SGS* CResourceManager::_CreateGS (LPCSTR name) +{ + LPSTR N = LPSTR(name); + map_GS::iterator I = m_gs.find (N); + if (I!=m_gs.end()) return I->second; + else + { + SGS* _gs = xr_new (); + _gs->dwFlags |= xr_resource_flagged::RF_REGISTERED; + m_gs.insert (mk_pair(_gs->set_name(name),_gs)); + VERIFY(strcmpi(name, "null") != 0); + + // Open file + string_path cname; + strconcat (sizeof(cname), cname,GlobalEnv.Render->getShaderPath(),name,".gs"); + FS.update_path (cname, "$game_shaders$", cname); + + // duplicate and zero-terminate + IReader* R = FS.r_open(cname); + // TODO: DX10: HACK: Implement all shaders. Remove this for PS + if (!R) + { + string1024 tmp; + // TODO: HACK: Test failure + //Memory.mem_compact(); + xr_sprintf (tmp, "OGL: %s is missing. Replace with stub_default.gs", cname); + Msg (tmp); + strconcat (sizeof(cname), cname,GlobalEnv.Render->getShaderPath(),"stub_default",".gs"); + FS.update_path (cname, "$game_shaders$", cname); + R = FS.r_open(cname); + } + IReader* file = FS.r_open(cname); + R_ASSERT2 ( file, cname ); + + // Select target + _gs->gs = glCreateShader(GL_GEOMETRY_SHADER); + void* _result = &_gs->gs; + HRESULT const _hr = GlobalEnv.Render->shader_compile(name,(DWORD const*)file->pointer(),file->length(), NULL, NULL, NULL, _result ); + + VERIFY(SUCCEEDED(_hr)); + + FS.r_close ( file ); + + CHECK_OR_EXIT ( + !FAILED(_hr), + make_string("Your video card doesn't meet game requirements.\n\nTry to lower game settings.") + ); + + return _gs; + } +} +void CResourceManager::_DeleteGS (const SGS* gs) +{ + if (0==(gs->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + LPSTR N = LPSTR (*gs->cName); + map_GS::iterator I = m_gs.find (N); + if (I!=m_gs.end()) { + m_gs.erase(I); + return; + } + Msg ("! ERROR: Failed to find compiled geometry shader '%s'",*gs->cName); +} + R_constant_table* CResourceManager::_CreateConstantTable (R_constant_table& C) { if (C.empty()) return NULL;