QVector<ShaderUniform> QGraphicsHelperES2::programUniformsAndLocations(GLuint programId) { QVector<ShaderUniform> uniforms; GLint nbrActiveUniforms = 0; m_funcs->glGetProgramiv(programId, GL_ACTIVE_UNIFORMS, &nbrActiveUniforms); uniforms.resize(nbrActiveUniforms); for (GLint i = 0; i < nbrActiveUniforms; i++) { ShaderUniform uniform; QByteArray uniformName(256, '\0'); // Size is 1 for scalar and more for struct or arrays // Type is the GL Type m_funcs->glGetActiveUniform(programId, i, 256, NULL, &uniform.m_size, &uniform.m_type , uniformName.data()); uniform.m_location = m_funcs->glGetUniformLocation(programId, uniformName.constData()); uniform.m_name = QString::fromUtf8(uniformName); uniforms.append(uniform); } return uniforms; }
void GFXGLShader::initConstantDescs() { mConstants.clear(); GLint numUniforms; glGetProgramiv(mProgram, GL_ACTIVE_UNIFORMS, &numUniforms); GLint maxNameLength; glGetProgramiv(mProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength); FrameTemp<GLchar> uniformName(maxNameLength); for(U32 i = 0; i < numUniforms; i++) { GLint size; GLenum type; glGetActiveUniform(mProgram, i, maxNameLength, NULL, &size, &type, uniformName); GFXShaderConstDesc desc; desc.name = String((char*)uniformName); // Remove array brackets from the name desc.name = desc.name.substr(0, desc.name.find('[')); // Insert $ to match D3D behavior of having a $ prepended to parameters to main. desc.name.insert(0, '$'); desc.arraySize = size; switch(type) { case GL_FLOAT: desc.constType = GFXSCT_Float; break; case GL_FLOAT_VEC2: desc.constType = GFXSCT_Float2; break; case GL_FLOAT_VEC3: desc.constType = GFXSCT_Float3; break; case GL_FLOAT_VEC4: desc.constType = GFXSCT_Float4; break; case GL_INT: desc.constType = GFXSCT_Int; break; case GL_INT_VEC2: desc.constType = GFXSCT_Int2; break; case GL_INT_VEC3: desc.constType = GFXSCT_Int3; break; case GL_INT_VEC4: desc.constType = GFXSCT_Int4; break; case GL_FLOAT_MAT2: desc.constType = GFXSCT_Float2x2; break; case GL_FLOAT_MAT3: desc.constType = GFXSCT_Float3x3; break; case GL_FLOAT_MAT4: desc.constType = GFXSCT_Float4x4; break; case GL_SAMPLER_1D: case GL_SAMPLER_2D: case GL_SAMPLER_3D: case GL_SAMPLER_1D_SHADOW: case GL_SAMPLER_2D_SHADOW: desc.constType = GFXSCT_Sampler; break; case GL_SAMPLER_CUBE: desc.constType = GFXSCT_SamplerCube; break; default: AssertFatal(false, "GFXGLShader::initConstantDescs - unrecognized uniform type"); // If we don't recognize the constant don't add its description. continue; } mConstants.push_back(desc); } }
void TranslatorGLSL::translate(TIntermBlock *root, ShCompileOptions compileOptions) { TInfoSinkBase &sink = getInfoSink().obj; // Write GLSL version. writeVersion(root); // Write extension behaviour as needed writeExtensionBehavior(root); // Write pragmas after extensions because some drivers consider pragmas // like non-preprocessor tokens. writePragma(compileOptions); // If flattening the global invariant pragma, write invariant declarations for built-in // variables. It should be harmless to do this twice in the case that the shader also explicitly // did this. However, it's important to emit invariant qualifiers only for those built-in // variables that are actually used, to avoid affecting the behavior of the shader. if ((compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) != 0 && getPragma().stdgl.invariantAll && !sh::RemoveInvariant(getShaderType(), getShaderVersion(), getOutputType(), compileOptions)) { ASSERT(wereVariablesCollected()); switch (getShaderType()) { case GL_VERTEX_SHADER: sink << "invariant gl_Position;\n"; // gl_PointSize should be declared invariant in both ESSL 1.00 and 3.00 fragment // shaders if it's statically referenced. conditionallyOutputInvariantDeclaration("gl_PointSize"); break; case GL_FRAGMENT_SHADER: // The preprocessor will reject this pragma if it's used in ESSL 3.00 fragment // shaders, so we can use simple logic to determine whether to declare these // variables invariant. conditionallyOutputInvariantDeclaration("gl_FragCoord"); conditionallyOutputInvariantDeclaration("gl_PointCoord"); break; default: // Currently not reached, but leave this in for future expansion. ASSERT(false); break; } } if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0) { sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion()); } if ((compileOptions & SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR) != 0) { sh::RewriteUnaryMinusOperatorFloat(root); } bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; if (precisionEmulation) { EmulatePrecision emulatePrecision(getSymbolTable(), getShaderVersion()); root->traverse(&emulatePrecision); emulatePrecision.updateTree(); emulatePrecision.writeEmulationHelpers(sink, getShaderVersion(), getOutputType()); } // Write emulated built-in functions if needed. if (!getBuiltInFunctionEmulator().isOutputEmpty()) { sink << "// BEGIN: Generated code for built-in function emulation\n\n"; sink << "#define webgl_emu_precision\n\n"; getBuiltInFunctionEmulator().outputEmulatedFunctions(sink); sink << "// END: Generated code for built-in function emulation\n\n"; } // Write array bounds clamping emulation if needed. getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData // if it's core profile shaders and they are used. if (getShaderType() == GL_FRAGMENT_SHADER) { const bool mayHaveESSL1SecondaryOutputs = IsExtensionEnabled(getExtensionBehavior(), "GL_EXT_blend_func_extended") && getShaderVersion() == 100; const bool declareGLFragmentOutputs = IsGLSL130OrNewer(getOutputType()); bool hasGLFragColor = false; bool hasGLFragData = false; bool hasGLSecondaryFragColor = false; bool hasGLSecondaryFragData = false; for (const auto &outputVar : outputVariables) { if (declareGLFragmentOutputs) { if (outputVar.name == "gl_FragColor") { ASSERT(!hasGLFragColor); hasGLFragColor = true; continue; } else if (outputVar.name == "gl_FragData") { ASSERT(!hasGLFragData); hasGLFragData = true; continue; } } if (mayHaveESSL1SecondaryOutputs) { if (outputVar.name == "gl_SecondaryFragColorEXT") { ASSERT(!hasGLSecondaryFragColor); hasGLSecondaryFragColor = true; continue; } else if (outputVar.name == "gl_SecondaryFragDataEXT") { ASSERT(!hasGLSecondaryFragData); hasGLSecondaryFragData = true; continue; } } } ASSERT(!((hasGLFragColor || hasGLSecondaryFragColor) && (hasGLFragData || hasGLSecondaryFragData))); if (hasGLFragColor) { sink << "out vec4 webgl_FragColor;\n"; } if (hasGLFragData) { sink << "out vec4 webgl_FragData[gl_MaxDrawBuffers];\n"; } if (hasGLSecondaryFragColor) { sink << "out vec4 angle_SecondaryFragColor;\n"; } if (hasGLSecondaryFragData) { sink << "out vec4 angle_SecondaryFragData[" << getResources().MaxDualSourceDrawBuffers << "];\n"; } } if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared()) { const sh::WorkGroupSize &localSize = getComputeShaderLocalSize(); sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1] << ", local_size_z=" << localSize[2] << ") in;\n"; } // Write translated shader. TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable(), getShaderType(), getShaderVersion(), getOutputType(), compileOptions); if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM) { TName uniformName(TString("ViewID_OVR")); uniformName.setInternal(true); sink << "uniform int " << outputGLSL.hashName(uniformName) << ";\n"; } root->traverse(&outputGLSL); }