From 5a33efb14eebb67a39c6671ee2b2cbe28315a9da Mon Sep 17 00:00:00 2001 From: Spoike Date: Wed, 5 Nov 2014 05:39:24 +0000 Subject: [PATCH] support for gl4 tesselation shaders. glsl code is available separately. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4786 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/m_options.c | 2 +- engine/client/renderer.c | 4 +- engine/client/snd_dma.c | 8 ++ engine/gl/gl_alias.c | 4 +- engine/gl/gl_backend.c | 104 +++++++++++++--------- engine/gl/gl_rsurf.c | 28 +++--- engine/gl/gl_shader.c | 6 +- engine/gl/gl_vidcommon.c | 176 ++++++++++++++++++++++++++------------ engine/gl/glquake.h | 3 +- engine/gl/glsupp.h | 5 ++ engine/gl/shader.h | 6 +- 11 files changed, 226 insertions(+), 120 deletions(-) diff --git a/engine/client/m_options.c b/engine/client/m_options.c index a244cacbc..90b26c93c 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -499,7 +499,7 @@ void M_Menu_Audio_f (void) MB_SLIDER("Ambient Volume", ambient_level, 0, 1, 0.1, NULL), MB_SLIDER("Ambient Fade", ambient_fade, 0, 1000, 1, NULL), MB_CHECKBOXCVAR("Static Sounds", cl_staticsounds, 0), - MB_SLIDER("CD Music Volume", bgmvolume, 0, 1, 0.1, NULL), + MB_SLIDER("Music Volume", bgmvolume, 0, 1, 0.1, NULL), // removed music buffer // removed precache // removed eax2 diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 2a862c468..d0ed6c6d3 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -215,8 +215,8 @@ cvar_t vid_multisample = CVARF ("vid_multisample", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); cvar_t vid_refreshrate = CVARF ("vid_displayfrequency", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); -cvar_t vid_srgb = CVARF ("vid_srgb", "0", - CVAR_ARCHIVE); +cvar_t vid_srgb = CVARFD ("vid_srgb", "0", + CVAR_ARCHIVE, "The framebuffer should use sRGB colourspace. This has the effect of brightening the screen"); cvar_t vid_wndalpha = CVAR ("vid_wndalpha", "1"); //more readable defaults to match conwidth/conheight. cvar_t vid_width = CVARFD ("vid_width", "0", diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index 3617b9c33..fa8717b7b 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -895,11 +895,19 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf) /*if you're sending sound, you should be prepared to accept others yelling at you to shut up*/ if (snd_voip_play.value <= 0) voipsendenable = false; + /*don't send sound if its not supported. that'll break stuff*/ if (!(cls.fteprotocolextensions2 & PEXT2_VOICECHAT)) voipsendenable = false; } else + { + /*we're not sending it to a server. the above considerations don't matter*/ voipsendenable = snd_voip_test.ival; + } + /*don't send sound if mic volume won't send anything anyway*/ + if (micamp <= 0) + voipsendenable = false; + if (rtpstream) { voipsendenable = true; diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 231af832b..dce10476f 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -684,7 +684,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e (shader->defaulttextures.upperoverlay && (shader->defaulttextures.upperoverlay->status == TEX_LOADING || shader->defaulttextures.upperoverlay->status == TEX_LOADED))) return shader; } - if (shader->prog && shader->prog->permu[PERMUTATION_UPPERLOWER].handle.glsl && !h2playertranslations) + if (shader->prog && shader->prog->permu[PERMUTATION_UPPERLOWER].handle.glsl.handle && !h2playertranslations) { //this shader can do permutations. this means we can generate only a black image, with separate top+bottom textures. tc = 0xfe000000; bc = 0xfe000000; @@ -1402,7 +1402,7 @@ void R_GAlias_DrawBatch(batch_t *batch) { if (batch->surf_first == surfnum) { - /*needrecolour =*/ Alias_GAliasBuildMesh(&mesh, &batch->vbo, inf, surfnum, e, batch->shader->prog && batch->shader->prog->permu[PERMUTATION_SKELETAL].handle.glsl); + /*needrecolour =*/ Alias_GAliasBuildMesh(&mesh, &batch->vbo, inf, surfnum, e, batch->shader->prog && batch->shader->prog->permu[PERMUTATION_SKELETAL].handle.glsl.handle); batch->mesh = &meshl; return; } diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index f1a540707..c7b6d2ffe 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -81,7 +81,7 @@ struct { const shader_t *crepopaqueshader; const shader_t *depthonlyshader; - GLhandleARB allblackshader; + union programhandle_u allblackshader; int allblack_mvp; qboolean initeddepthnorm; @@ -99,6 +99,7 @@ struct { texid_t tex_refractiondepth; /*the (culled) underwater view*/ texid_t tex_ripplemap; /*temp image for waves and things.*/ + int curpatchverts; qboolean force2d; int currenttmu; int blendmode[SHADER_TMU_MAX]; @@ -209,6 +210,12 @@ static void BE_PolyOffset(qboolean pushdepth) po.factor += r_polygonoffset_submodel_factor.value; po.unit += r_polygonoffset_submodel_offset.value; } + if (shaderstate.mode == BEM_DEPTHONLY) + { + extern cvar_t r_polygonoffset_shadowmap_offset, r_polygonoffset_shadowmap_factor; + po.factor += r_polygonoffset_shadowmap_factor.value; + po.unit += r_polygonoffset_shadowmap_offset.value; + } #ifndef FORCESTATE if (shaderstate.curpolyoffset.factor != po.factor || shaderstate.curpolyoffset.unit != po.unit) @@ -861,19 +868,19 @@ void GLBE_RenderShadowBuffer(unsigned int numverts, int vbo, vecV_t *verts, unsi GLBE_PolyOffsetShadowMap(false); - if (shaderstate.allblackshader) + if (shaderstate.allblackshader.glsl.handle) { - GL_SelectProgram(shaderstate.allblackshader); + GL_SelectProgram(shaderstate.allblackshader.glsl.handle); BE_EnableShaderAttributes(gl_config_nofixedfunc?(1u<numbones) { - if (p->permu[perm|PERMUTATION_SKELETAL].handle.glsl) + if (p->permu[perm|PERMUTATION_SKELETAL].handle.glsl.handle) perm |= PERMUTATION_SKELETAL; else return; } - if (p->permu[perm|PERMUTATION_FRAMEBLEND].handle.glsl && shaderstate.sourcevbo->coord2.gl.addr) + if (p->permu[perm|PERMUTATION_FRAMEBLEND].handle.glsl.handle && shaderstate.sourcevbo->coord2.gl.addr) perm |= PERMUTATION_FRAMEBLEND; - if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].handle.glsl) + if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].handle.glsl.handle) perm |= PERMUTATION_BUMPMAP; - if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].handle.glsl) + if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].handle.glsl.handle) perm |= PERMUTATION_FULLBRIGHT; - if ((TEXLOADED(shaderstate.curtexnums->loweroverlay) || TEXLOADED(shaderstate.curtexnums->upperoverlay)) && p->permu[perm|PERMUTATION_UPPERLOWER].handle.glsl) + if ((TEXLOADED(shaderstate.curtexnums->loweroverlay) || TEXLOADED(shaderstate.curtexnums->upperoverlay)) && p->permu[perm|PERMUTATION_UPPERLOWER].handle.glsl.handle) perm |= PERMUTATION_UPPERLOWER; - if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].handle.glsl) + if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].handle.glsl.handle) perm |= PERMUTATION_FOG; - if (p->permu[perm|PERMUTATION_DELUXE].handle.glsl && TEXLOADED(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe) + if (p->permu[perm|PERMUTATION_DELUXE].handle.glsl.handle && TEXLOADED(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe) perm |= PERMUTATION_DELUXE; #if MAXRLIGHTMAPS > 1 - if (shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].handle.glsl) + if (shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].handle.glsl.handle) perm |= PERMUTATION_LIGHTSTYLES; #endif - GL_SelectProgram(p->permu[perm].handle.glsl); + GL_SelectProgram(p->permu[perm].handle.glsl.handle); #ifndef FORCESTATE - if (shaderstate.lastuniform == p->permu[perm].handle.glsl) + if (shaderstate.lastuniform == p->permu[perm].handle.glsl.handle) i = true; else #endif { i = false; - shaderstate.lastuniform = p->permu[perm].handle.glsl; + shaderstate.lastuniform = p->permu[perm].handle.glsl.handle; } BE_Program_Set_Attributes(p, perm, i); @@ -3347,7 +3369,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas shaderstate.lastpasstmus = pass->numMergedPasses; } } - BE_SubmitMeshChain(); + BE_SubmitMeshChain(p->permu[perm].handle.glsl.usetesselation); } qboolean GLBE_LightCullModel(vec3_t org, model_t *model) @@ -3408,11 +3430,11 @@ void GLBE_SelectMode(backendmode_t mode) } else #endif - if (!shaderstate.allblackshader) + if (!shaderstate.allblackshader.glsl.handle) { const char *defs[] = {NULL}; - shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL); - shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader, "m_modelviewprojection"); + shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", NULL, NULL, "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL); + shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader.glsl.handle, "m_modelviewprojection"); } /*BEM_DEPTHONLY does support mesh writing, but its not the only way its used... FIXME!*/ while(shaderstate.lastpasstmus>0) @@ -3433,11 +3455,11 @@ void GLBE_SelectMode(backendmode_t mode) /*BEM_STENCIL doesn't support mesh writing*/ GLBE_PolyOffsetStencilShadow(false); - if (gl_config_nofixedfunc && !shaderstate.allblackshader) + if (gl_config_nofixedfunc && !shaderstate.allblackshader.glsl.handle) { const char *defs[] = {NULL}; - shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL); - shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader, "m_modelviewprojection"); + shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", NULL, NULL, "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL); + shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader.glsl.handle, "m_modelviewprojection"); } //disable all tmus @@ -3784,7 +3806,7 @@ static void BE_LegacyLighting(void) GL_DeSelectProgram(); BE_EnableShaderAttributes(attr, 0); - BE_SubmitMeshChain(); + BE_SubmitMeshChain(false); GL_LazyBind(1, 0, r_nulltex); GL_LazyBind(2, 0, r_nulltex); @@ -3904,7 +3926,7 @@ static void DrawMeshes(void) #pragma warningmsg("fixme: support alpha test") #endif BE_EnableShaderAttributes((1u<passes[0].shaderbits & ~SBITS_BLEND_BITS) | SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | SBITS_MISC_NODEPTHTEST); BE_EnableShaderAttributes((1u<flags & SHADER_HASLIGHTMAP) && !TEXVALID(shaderstate.curtexnums->fullbright)) { if (gl_config.arb_shader_objects) { - if (!shaderstate.allblackshader) + if (!shaderstate.allblackshader.glsl.handle) { const char *defs[] = {NULL}; - shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL); - shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader, "m_modelviewprojection"); + shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", NULL, NULL, "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL); + shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader.glsl.handle, "m_modelviewprojection"); } - GL_SelectProgram(shaderstate.allblackshader); + GL_SelectProgram(shaderstate.allblackshader.glsl.handle); BE_SendPassBlendDepthMask(shaderstate.curshader->passes[0].shaderbits); BE_EnableShaderAttributes(gl_config_nofixedfunc?(1u<passes[0].shaderbits); BE_EnableShaderAttributes((1u<fog); BE_EnableShaderAttributes((1u<indicies.gl.vbo = vbos[1]; vbo->indicies.gl.addr = (index_t*)((char*)vbo->indicies.gl.addr - (char*)edata); - vaostatic |= VATTR_LEG_ELEMENTS; + vaostatic |= 1u<coord.gl.addr) { vbo->coord.gl.vbo = vbos[0]; vbo->coord.gl.addr = (vecV_t*)((char*)vbo->coord.gl.addr - (char*)vdata); - vaostatic |= VATTR_VERTEX1; + vaostatic |= 1u<texcoord.gl.addr) { vbo->texcoord.gl.vbo = vbos[0]; vbo->texcoord.gl.addr = (vec2_t*)((char*)vbo->texcoord.gl.addr - (char*)vdata); - vaostatic |= VATTR_TEXCOORD; + vaostatic |= 1u<colours[s].gl.addr = (vec4_t*)((char*)vbo->colours[s].gl.addr - (char*)vdata); switch(s) { - default: vaostatic |= VATTR_COLOUR; break; + default: vaostatic |= 1u< 1 - case 1: vaostatic |= VATTR_COLOUR2; break; - case 2: vaostatic |= VATTR_COLOUR3; break; - case 3: vaostatic |= VATTR_COLOUR4; break; + case 1: vaostatic |= 1u<lmcoord[s].gl.addr = (vec2_t*)((char*)vbo->lmcoord[s].gl.addr - (char*)vdata); switch(s) { - default: vaostatic |= VATTR_LMCOORD; break; + default: vaostatic |= 1u< 1 - case 1: vaostatic |= VATTR_LMCOORD2; break; - case 2: vaostatic |= VATTR_LMCOORD3; break; - case 3: vaostatic |= VATTR_LMCOORD4; break; + case 1: vaostatic |= 1u<normals.gl.vbo = vbos[0]; vbo->normals.gl.addr = (vec3_t*)((char*)vbo->normals.gl.addr - (char*)vdata); - vaostatic |= VATTR_NORMALS; + vaostatic |= 1u<svector.gl.addr) { vbo->svector.gl.vbo = vbos[0]; vbo->svector.gl.addr = (vec3_t*)((char*)vbo->svector.gl.addr - (char*)vdata); - vaostatic |= VATTR_SNORMALS; + vaostatic |= 1u<tvector.gl.addr) { vbo->tvector.gl.vbo = vbos[0]; vbo->tvector.gl.addr = (vec3_t*)((char*)vbo->tvector.gl.addr - (char*)vdata); - vaostatic |= VATTR_TNORMALS; + vaostatic |= 1u<parm[prog->numparams].type = parmtype; for (p = 0; p < PERMUTATIONS; p++) { - if (!prog->permu[p].handle.glsl) + if (!prog->permu[p].handle.glsl.handle) continue; - GLSlang_UseProgram(prog->permu[p].handle.glsl); + GLSlang_UseProgram(prog->permu[p].handle.glsl.handle); - uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl, token); + uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl.handle, token); prog->permu[p].parm[prog->numparams] = uniformloc; if (uniformloc != -1) diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index c57efa6f2..8b368d091 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -220,6 +220,8 @@ int mtexid0; FTEPFNGLPNTRIANGLESIATIPROC qglPNTrianglesiATI; FTEPFNGLPNTRIANGLESFATIPROC qglPNTrianglesfATI; +void (APIENTRY *qglPatchParameteriARB)(GLenum pname, GLint value); //core in gl4 + //stencil shadowing FTEPFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT; @@ -742,6 +744,13 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) qglPNTrianglesfATI = (void *)getglext("glPNTrianglesfATI"); qglPNTrianglesiATI = (void *)getglext("glPNTrianglesiATI"); } + if (!gl_config.gles && gl_config.glversion >= 4.0) + qglPatchParameteriARB = getglext("glPatchParameteri"); + else if (GL_CheckExtension("GL_ARB_tessellation_shader")) + qglPatchParameteriARB = getglext("glPatchParameteriARB"); + else + qglPatchParameteriARB = NULL; + #ifndef GL_STATIC if (GL_CheckExtension("GL_EXT_texture_object")) @@ -1207,9 +1216,12 @@ static const char *glsl_hdrs[] = "uniform float cvar_r_glsl_offsetmapping_scale;\n" "vec2 offsetmap(sampler2D normtex, vec2 base, vec3 eyevector)\n" "{\n" + "#if !defined(OFFSETMAPPING_SCALE)\n" + "#define OFFSETMAPPING_SCALE 1.0\n" + "#endif\n" "#if defined(RELIEFMAPPING) && !defined(GL_ES)\n" "float i, f;\n" - "vec3 OffsetVector = vec3(normalize(eyevector.xyz).xy * cvar_r_glsl_offsetmapping_scale * vec2(-1.0, 1.0), -1.0);\n" + "vec3 OffsetVector = vec3(normalize(eyevector.xyz).xy * cvar_r_glsl_offsetmapping_scale * OFFSETMAPPING_SCALE * vec2(-1.0, 1.0), -1.0);\n" "vec3 RT = vec3(vec2(base.xy"/* - OffsetVector.xy*OffsetMapping_Bias*/"), 1.0);\n" "OffsetVector /= 10.0;\n" "for(i = 1.0; i < 10.0; ++i)\n" @@ -1218,7 +1230,7 @@ static const char *glsl_hdrs[] = "RT += OffsetVector * (step(texture2D(normtex, RT.xy).a, RT.z) * f - 0.5 * f);\n" "return RT.xy;\n" "#elif defined(OFFSETMAPPING)\n" - "vec2 OffsetVector = normalize(eyevector).xy * cvar_r_glsl_offsetmapping_scale * vec2(-1.0, 1.0);\n" + "vec2 OffsetVector = normalize(eyevector).xy * cvar_r_glsl_offsetmapping_scale * OFFSETMAPPING_SCALE * vec2(-1.0, 1.0);\n" "vec2 tc = base;\n" "tc += OffsetVector;\n" "OffsetVector *= 0.333;\n" @@ -1426,6 +1438,9 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char * int strings = 0; char verline[64]; + if (!shadersource) + return 0; + if (ver) { /*required version not supported, don't even try*/ @@ -1471,6 +1486,16 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char * strings++; } break; + case GL_TESS_CONTROL_SHADER_ARB: + prstrings[strings] = "#define TESS_CONTROL_SHADER\n"; + length[strings] = strlen(prstrings[strings]); + strings++; + break; + case GL_TESS_EVALUATION_SHADER_ARB: + prstrings[strings] = "#define TESS_EVALUATION_SHADER\n"; + length[strings] = strlen(prstrings[strings]); + strings++; + break; case GL_VERTEX_SHADER_ARB: prstrings[strings] = "#define VERTEX_SHADER\n"; length[strings] = strlen(prstrings[strings]); @@ -1487,12 +1512,28 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char * length[strings] = strlen(prstrings[strings]); strings++; } - if (gl_config.nofixedfunc) + if (ver < 140) { prstrings[strings] = - "attribute vec3 v_position1;\n" + "#define in attribute\n" + "#define out varying\n" + ; + } + else + { + prstrings[strings] = + "#define attribute in\n" + "#define varying out\n" + ; + length[strings] = strlen(prstrings[strings]); + strings++; + } + if (gl_config.nofixedfunc || ver >= 140) + { + prstrings[strings] = + "in vec3 v_position1;\n" "#ifdef FRAMEBLEND\n" - "attribute vec3 v_position2;\n" + "in vec3 v_position2;\n" "uniform vec2 e_vblend;\n" "#define v_position ((v_position1*e_vblend.x)+(v_position2*e_vblend.y))\n" "#else\n" @@ -1509,7 +1550,7 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char * { prstrings[strings] = "#ifdef FRAMEBLEND\n" - "attribute vec3 v_position2;\n" + "in vec3 v_position2;\n" "uniform vec2 e_vblend;\n" "#define v_position (gl_Vertex.xyz*e_vblend.x+v_position2*e_vblend.y)\n" "uniform mat4 m_modelviewprojection;\n" @@ -1593,6 +1634,12 @@ static GLhandleARB GLSlang_FinishShader(GLhandleARB shader, const char *name, GL case GL_VERTEX_SHADER_ARB: typedesc = "Vertex"; break; + case GL_TESS_CONTROL_SHADER_ARB: + typedesc = "Tesselation Control"; + break; + case GL_TESS_EVALUATION_SHADER_ARB: + typedesc = "Tesselation Evaluation"; + break; default: typedesc = "???"; break; @@ -1633,13 +1680,15 @@ static GLhandleARB GLSlang_FinishShader(GLhandleARB shader, const char *name, GL return shader; } -GLhandleARB GLSlang_CreateProgramObject (const char *name, GLhandleARB vert, GLhandleARB frag, qboolean silent) +GLhandleARB GLSlang_CreateProgramObject (const char *name, GLhandleARB vert, GLhandleARB cont, GLhandleARB eval, GLhandleARB frag, qboolean silent) { GLhandleARB program; program = qglCreateProgramObjectARB(); - qglAttachObjectARB(program, vert); - qglAttachObjectARB(program, frag); + if (vert) qglAttachObjectARB(program, vert); + if (cont) qglAttachObjectARB(program, cont); + if (eval) qglAttachObjectARB(program, eval); + if (frag) qglAttachObjectARB(program, frag); qglBindAttribLocationARB(program, VATTR_VERTEX1, "v_position1"); qglBindAttribLocationARB(program, VATTR_COLOUR, "v_colour"); @@ -1666,108 +1715,124 @@ GLhandleARB GLSlang_CreateProgramObject (const char *name, GLhandleARB vert, GLh return program; } -GLhandleARB GLSlang_ValidateProgram(GLhandleARB program, const char *name, qboolean silent, vfsfile_t *blobfile) +qboolean GLSlang_ValidateProgram(union programhandle_u *h, const char *name, qboolean silent, vfsfile_t *blobfile) { char str[2048]; char *nullconstants = NULL; GLint linked; - if (!program) - return (GLhandleARB)0; - qglGetProgramParameteriv_(program, GL_OBJECT_LINK_STATUS_ARB, &linked); + if (!h->glsl.handle) + return false; + qglGetProgramParameteriv_(h->glsl.handle, GL_OBJECT_LINK_STATUS_ARB, &linked); if(!linked) { if (!silent) { - qglGetProgramInfoLog_(program, sizeof(str), NULL, str); + qglGetProgramInfoLog_(h->glsl.handle, sizeof(str), NULL, str); Con_Printf("Program link error on glsl program %s:\n%s\n", name, str); } - qglDeleteProgramObject_(program); + qglDeleteProgramObject_(h->glsl.handle); + h->glsl.handle = 0; return (GLhandleARB)0; } - if (program && blobfile && qglGetProgramBinary) + if (h->glsl.handle && blobfile && qglGetProgramBinary) { GLuint ui; GLenum e; unsigned int len, fmt; void *blobdata; - qglGetProgramParameteriv_(program, GL_PROGRAM_BINARY_LENGTH, &ui); + qglGetProgramParameteriv_(h->glsl.handle, GL_PROGRAM_BINARY_LENGTH, &ui); len = ui; blobdata = BZ_Malloc(len); - qglGetProgramBinary(program, len, NULL, &e, blobdata); + qglGetProgramBinary(h->glsl.handle, len, NULL, &e, blobdata); fmt = e; VFS_WRITE(blobfile, &fmt, sizeof(fmt)); VFS_WRITE(blobfile, &len, sizeof(len)); VFS_WRITE(blobfile, blobdata, len); + VFS_WRITE(blobfile, &h->glsl.usetesselation, sizeof(h->glsl.usetesselation)); BZ_Free(blobdata); } - return program; + return true; } -GLhandleARB GLSlang_CreateProgram(const char *name, int ver, const char **precompilerconstants, const char *vert, const char *frag, qboolean silent, vfsfile_t *blobfile) +union programhandle_u GLSlang_CreateProgram(const char *name, int ver, const char **precompilerconstants, const char *vert, const char *cont, const char *eval, const char *frag, qboolean silent, vfsfile_t *blobfile) { - GLhandleARB handle; + union programhandle_u ret; GLhandleARB vs; GLhandleARB fs; + GLhandleARB cs; + GLhandleARB es; const char *nullconstants = NULL; + memset(&ret, 0, sizeof(ret)); + if (!gl_config.arb_shader_objects) - return 0; + return ret; + if ((cont || frag) && !qglPatchParameteriARB) + return ret; if (!precompilerconstants) precompilerconstants = &nullconstants; fs = GLSlang_CreateShader(name, ver, precompilerconstants, frag, GL_FRAGMENT_SHADER_ARB, silent); vs = GLSlang_CreateShader(name, ver, precompilerconstants, vert, GL_VERTEX_SHADER_ARB, silent); + cs = GLSlang_CreateShader(name, ver, precompilerconstants, cont, GL_TESS_CONTROL_SHADER_ARB, silent); + es = GLSlang_CreateShader(name, ver, precompilerconstants, eval, GL_TESS_EVALUATION_SHADER_ARB, silent); fs = GLSlang_FinishShader(fs, name, GL_FRAGMENT_SHADER_ARB, silent); vs = GLSlang_FinishShader(vs, name, GL_VERTEX_SHADER_ARB, silent); + cs = GLSlang_FinishShader(cs, name, GL_TESS_CONTROL_SHADER_ARB, silent); + es = GLSlang_FinishShader(es, name, GL_TESS_EVALUATION_SHADER_ARB, silent); if (!vs || !fs) - handle = 0; + ret.glsl.handle = 0; else - handle = GLSlang_CreateProgramObject(name, vs, fs, silent); + ret.glsl.handle = GLSlang_CreateProgramObject(name, vs, cs, es, fs, silent); //delete ignores 0s. - qglDeleteShaderObject_(vs); - qglDeleteShaderObject_(fs); + if (vs) qglDeleteShaderObject_(vs); + if (fs) qglDeleteShaderObject_(fs); + if (cs) qglDeleteShaderObject_(cs); + if (es) qglDeleteShaderObject_(es); checkglerror(); - if (handle && blobfile && qglGetProgramBinary) + if (ret.glsl.handle && blobfile && qglGetProgramBinary) { GLuint ui; GLenum e; unsigned int len, fmt; void *blobdata; - qglGetProgramParameteriv_(handle, GL_PROGRAM_BINARY_LENGTH, &ui); + qglGetProgramParameteriv_(ret.glsl.handle, GL_PROGRAM_BINARY_LENGTH, &ui); len = ui; blobdata = BZ_Malloc(len); - qglGetProgramBinary(handle, len, NULL, &e, blobdata); + qglGetProgramBinary(ret.glsl.handle, len, NULL, &e, blobdata); fmt = e; VFS_WRITE(blobfile, &fmt, sizeof(fmt)); VFS_WRITE(blobfile, &len, sizeof(len)); VFS_WRITE(blobfile, blobdata, len); + VFS_WRITE(blobfile, &ret.glsl.usetesselation, sizeof(ret.glsl.usetesselation)); BZ_Free(blobdata); } - return handle; + ret.glsl.usetesselation = (cont || eval); + + return ret; } qboolean GLSlang_ValidateProgramPermu(program_t *prog, const char *name, unsigned int permu, qboolean noerrors, vfsfile_t *blobfile) { - prog->permu[permu].handle.glsl = GLSlang_ValidateProgram(prog->permu[permu].handle.glsl, name, noerrors, blobfile); - return !!prog->permu[permu].handle.glsl; + return GLSlang_ValidateProgram(&prog->permu[permu].handle, name, noerrors, blobfile); } qboolean GLSlang_CreateProgramPermu(program_t *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *frag, qboolean noerrors, vfsfile_t *blobfile) { @@ -1777,8 +1842,8 @@ qboolean GLSlang_CreateProgramPermu(program_t *prog, const char *name, unsigned if (permu & PERMUTATION_SKELETAL) ver = 120; } - prog->permu[permu].handle.glsl = GLSlang_CreateProgram(name, ver, precompilerconstants, vert, frag, noerrors, blobfile); - if (prog->permu[permu].handle.glsl) + prog->permu[permu].handle = GLSlang_CreateProgram(name, ver, precompilerconstants, vert, tcs, tes, frag, noerrors, blobfile); + if (prog->permu[permu].handle.glsl.handle) return true; return false; } @@ -1805,26 +1870,27 @@ static qboolean GLSlang_LoadBlob(program_t *prog, const char *name, unsigned int VFS_READ(blobfile, &length, sizeof(length)); binary = BZ_Malloc(length); VFS_READ(blobfile, binary, length); + VFS_READ(blobfile, &prog->permu[permu].handle.glsl.usetesselation, sizeof(prog->permu[permu].handle.glsl.usetesselation)); - prog->permu[permu].handle.glsl = qglCreateProgramObjectARB(); - qglProgramBinary(prog->permu[permu].handle.glsl, fmt, binary, length); + prog->permu[permu].handle.glsl.handle = qglCreateProgramObjectARB(); + qglProgramBinary(prog->permu[permu].handle.glsl.handle, fmt, binary, length); BZ_Free(binary); - qglGetProgramParameteriv_(prog->permu[permu].handle.glsl, GL_OBJECT_LINK_STATUS_ARB, &success); + qglGetProgramParameteriv_(prog->permu[permu].handle.glsl.handle, GL_OBJECT_LINK_STATUS_ARB, &success); if (!success) { - qglDeleteProgramObject_(prog->permu[permu].handle.glsl); - prog->permu[permu].handle.glsl = 0; + qglDeleteProgramObject_(prog->permu[permu].handle.glsl.handle); + memset(&prog->permu[permu].handle, 0, sizeof(prog->permu[permu].handle)); } return !!success; } static void GLSlang_DeleteProg(program_t *prog, unsigned int permu) { - if (prog->permu[permu].handle.glsl) + if (prog->permu[permu].handle.glsl.handle) { - qglDeleteProgramObject_(prog->permu[permu].handle.glsl); - prog->permu[permu].handle.glsl = 0; + qglDeleteProgramObject_(prog->permu[permu].handle.glsl.handle); + prog->permu[permu].handle.glsl.handle = 0; } } @@ -1841,12 +1907,12 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart //figure out visible attributes for (p = 0; p < PERMUTATIONS; p++) { - if (!prog->permu[p].handle.glsl) + if (!prog->permu[p].handle.glsl.handle) continue; - GLSlang_UseProgram(prog->permu[p].handle.glsl); + GLSlang_UseProgram(prog->permu[p].handle.glsl.handle); for (i = 0; shader_attr_names[i].name; i++) { - uniformloc = qglGetAttribLocationARB(prog->permu[p].handle.glsl, shader_attr_names[i].name); + uniformloc = qglGetAttribLocationARB(prog->permu[p].handle.glsl.handle, shader_attr_names[i].name); if (uniformloc != -1) { if (shader_attr_names[i].ptype != uniformloc) @@ -1863,11 +1929,11 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart found = false; for (p = 0; p < PERMUTATIONS; p++) { - if (!prog->permu[p].handle.glsl) + if (!prog->permu[p].handle.glsl.handle) continue; - GLSlang_UseProgram(prog->permu[p].handle.glsl); + GLSlang_UseProgram(prog->permu[p].handle.glsl.handle); - uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl, shader_unif_names[i].name); + uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl.handle, shader_unif_names[i].name); if (uniformloc != -1) found = true; @@ -1911,11 +1977,11 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart for (p = 0; p < PERMUTATIONS; p++) { char uniformname[64]; - if (!prog->permu[p].handle.glsl) + if (!prog->permu[p].handle.glsl.handle) continue; - GL_SelectProgram(prog->permu[p].handle.glsl); + GL_SelectProgram(prog->permu[p].handle.glsl.handle); Q_snprintfz(uniformname, sizeof(uniformname), "cvar_%s", tmpname); - uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl, uniformname); + uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl.handle, uniformname); if (uniformloc != -1) { //qglUniform1fARB(uniformloc, cvar->value); @@ -1929,15 +1995,15 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart /*set texture uniforms*/ for (p = 0; p < PERMUTATIONS; p++) { - if (!prog->permu[p].handle.glsl) + if (!prog->permu[p].handle.glsl.handle) continue; if (!(prog->permu[p].attrmask & (1u<permu[p].attrmask |= (1u<permu[p].handle.glsl); + GLSlang_UseProgram(prog->permu[p].handle.glsl.handle); for (i = 0; i < 8; i++) { Q_snprintfz(tmpname, sizeof(tmpname), "s_t%i", i); - uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl, tmpname); + uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl.handle, tmpname); if (uniformloc != -1) qglUniform1iARB(uniformloc, i); } @@ -1948,7 +2014,7 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart void GL_Init(void *(*getglfunction) (char *name)) { #ifndef GL_STATIC - qglBindTexture = (void *)getglcore("glBindTexture"); //for compleateness + qglBindTexture = (void *)getglcore("glBindTexture"); //for compleateness. core in 1.1. needed by fte. qglBlendFunc = (void *)getglcore("glBlendFunc"); qglClear = (void *)getglcore("glClear"); qglClearColor = (void *)getglcore("glClearColor"); diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index cc2c0d4d4..6f2986c28 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -198,6 +198,7 @@ extern FTEPFNGLCOMPRESSEDTEXIMAGE2DARBPROC qglCompressedTexImage2DARB; extern FTEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC qglGetCompressedTexImageARB; extern FTEPFNGLPNTRIANGLESIATIPROC qglPNTrianglesiATI; extern FTEPFNGLPNTRIANGLESFATIPROC qglPNTrianglesfATI; +extern void (APIENTRY *qglPatchParameteriARB)(GLenum pname, GLint value); //core in gl4 qboolean GL_CheckExtension(char *extname); @@ -1061,7 +1062,7 @@ extern void (APIENTRY *qglBindVertexArray)(GLuint vaoarray); //glslang helper api -GLhandleARB GLSlang_CreateProgram(const char *name, int ver, const char **precompilerconstants, const char *vert, const char *frag, qboolean silent, vfsfile_t *blobfile); +union programhandle_u GLSlang_CreateProgram(const char *name, int ver, const char **precompilerconstants, const char *vert, const char *cont, const char *eval, const char *frag, qboolean silent, vfsfile_t *blobfile); GLint GLSlang_GetUniformLocation (int prog, char *name); void GL_SelectProgram(int program); #define GLSlang_UseProgram(prog) GL_SelectProgram(prog) diff --git a/engine/gl/glsupp.h b/engine/gl/glsupp.h index 7de92b4bd..b0f648897 100644 --- a/engine/gl/glsupp.h +++ b/engine/gl/glsupp.h @@ -579,6 +579,11 @@ typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei #define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A #endif +#ifndef GL_ARB_vertex_shader +#define GL_TESS_EVALUATION_SHADER_ARB 0x8E87 +#define GL_TESS_CONTROL_SHADER_ARB 0x8E88 +#endif + #ifndef GL_ARB_fragment_shader #define GL_FRAGMENT_SHADER_ARB 0x8B30 #define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 9f77a2b6e..dcccfdeb4 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -422,7 +422,11 @@ typedef struct { union programhandle_u { - int glsl; + struct + { + int handle; + qboolean usetesselation; + } glsl; #ifdef D3DQUAKE struct {