GrGLSLUniformHandler::UniformHandle GrVkUniformHandler::internalAddUniformArray( uint32_t visibility, GrSLType type, GrSLPrecision precision, const char* name, bool mangleName, int arrayCount, const char** outName) { SkASSERT(name && strlen(name)); // For now asserting the the visibility is either geometry types (vertex, tesselation, geometry, // etc.) or only fragment. SkASSERT(kVertex_GrShaderFlag == visibility || kGeometry_GrShaderFlag == visibility || (kVertex_GrShaderFlag | kGeometry_GrShaderFlag) == visibility || kFragment_GrShaderFlag == visibility); SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type)); GrSLTypeIsFloatType(type); UniformInfo& uni = fUniforms.push_back(); uni.fVariable.setType(type); // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then // the names will mismatch. I think the correct solution is to have all GPs which need the // uniform view matrix, they should upload the view matrix in their setData along with regular // uniforms. char prefix = 'u'; if ('u' == name[0] || !strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX))) { prefix = '\0'; } fProgramBuilder->nameVariable(uni.fVariable.accessName(), prefix, name, mangleName); uni.fVariable.setArrayCount(arrayCount); uni.fVisibility = visibility; uni.fVariable.setPrecision(precision); // When outputing the GLSL, only the outer uniform block will get the Uniform modifier. Thus // we set the modifier to none for all uniforms declared inside the block. uni.fVariable.setTypeModifier(GrShaderVar::kNone_TypeModifier); uint32_t* currentOffset; uint32_t geomStages = kVertex_GrShaderFlag | kGeometry_GrShaderFlag; if (geomStages & visibility) { currentOffset = &fCurrentGeometryUBOOffset; } else { SkASSERT(kFragment_GrShaderFlag == visibility); currentOffset = &fCurrentFragmentUBOOffset; } get_ubo_aligned_offset(&uni.fUBOffset, currentOffset, type, arrayCount); SkString layoutQualifier; layoutQualifier.appendf("offset=%d", uni.fUBOffset); uni.fVariable.addLayoutQualifier(layoutQualifier.c_str()); if (outName) { *outName = uni.fVariable.c_str(); } return GrGLSLUniformHandler::UniformHandle(fUniforms.count() - 1); }
void GrGLSLVaryingHandler::addVarying(const char* name, GrGLSLVarying* varying, Interpolation interpolation) { SkASSERT(GrSLTypeIsFloatType(varying->type()) || Interpolation::kMustBeFlat == interpolation); bool willUseGeoShader = fProgramBuilder->primitiveProcessor().willUseGeoShader(); VaryingInfo& v = fVaryings.push_back(); SkASSERT(varying); SkASSERT(kVoid_GrSLType != varying->fType); v.fType = varying->fType; v.fIsFlat = use_flat_interpolation(interpolation, *fProgramBuilder->shaderCaps()); fProgramBuilder->nameVariable(&v.fVsOut, 'v', name); v.fVisibility = kNone_GrShaderFlags; if (varying->isInVertexShader()) { varying->fVsOut = v.fVsOut.c_str(); v.fVisibility |= kVertex_GrShaderFlag; } if (willUseGeoShader) { fProgramBuilder->nameVariable(&v.fGsOut, 'g', name); varying->fGsIn = v.fVsOut.c_str(); varying->fGsOut = v.fGsOut.c_str(); v.fVisibility |= kGeometry_GrShaderFlag; } if (varying->isInFragmentShader()) { varying->fFsIn = (willUseGeoShader ? v.fGsOut : v.fVsOut).c_str(); v.fVisibility |= kFragment_GrShaderFlag; } }
GrGLSLProgramDataManager::UniformHandle GrGLProgramBuilder::internalAddUniformArray( uint32_t visibility, GrSLType type, GrSLPrecision precision, const char* name, bool mangleName, int count, const char** outName) { SkASSERT(name && strlen(name)); SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility); SkASSERT(0 == (~kVisibilityMask & visibility)); SkASSERT(0 != visibility); SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type)); UniformInfo& uni = fUniforms.push_back(); uni.fVariable.setType(type); uni.fVariable.setTypeModifier(GrGLSLShaderVar::kUniform_TypeModifier); // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then // the names will mismatch. I think the correct solution is to have all GPs which need the // uniform view matrix, they should upload the view matrix in their setData along with regular // uniforms. char prefix = 'u'; if ('u' == name[0]) { prefix = '\0'; } this->nameVariable(uni.fVariable.accessName(), prefix, name, mangleName); uni.fVariable.setArrayCount(count); uni.fVisibility = visibility; uni.fVariable.setPrecision(precision); if (outName) { *outName = uni.fVariable.c_str(); } return GrGLSLProgramDataManager::UniformHandle(fUniforms.count() - 1); }
void GrVkUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const { SkASSERT(kVertex_GrShaderFlag == visibility || kGeometry_GrShaderFlag == visibility || kFragment_GrShaderFlag == visibility); for (int i = 0; i < fSamplers.count(); ++i) { const UniformInfo& sampler = fSamplers[i]; SkASSERT(sampler.fVariable.getType() == kTexture2DSampler_GrSLType); if (visibility == sampler.fVisibility) { sampler.fVariable.appendDecl(fProgramBuilder->shaderCaps(), out); out->append(";\n"); } } for (int i = 0; i < fTexelBuffers.count(); ++i) { const UniformInfo& texelBuffer = fTexelBuffers[i]; if (visibility == texelBuffer.fVisibility) { texelBuffer.fVariable.appendDecl(fProgramBuilder->shaderCaps(), out); out->append(";\n"); } } #ifdef SK_DEBUG bool firstGeomOffsetCheck = false; bool firstFragOffsetCheck = false; for (int i = 0; i < fUniforms.count(); ++i) { const UniformInfo& localUniform = fUniforms[i]; if (kVertex_GrShaderFlag == localUniform.fVisibility || kGeometry_GrShaderFlag == localUniform.fVisibility || (kVertex_GrShaderFlag | kGeometry_GrShaderFlag) == localUniform.fVisibility) { if (!firstGeomOffsetCheck) { // Check to make sure we are starting our offset at 0 so the offset qualifier we // set on each variable in the uniform block is valid. SkASSERT(0 == localUniform.fUBOffset); firstGeomOffsetCheck = true; } } else { SkASSERT(kFragment_GrShaderFlag == localUniform.fVisibility); if (!firstFragOffsetCheck) { // Check to make sure we are starting our offset at 0 so the offset qualifier we // set on each variable in the uniform block is valid. SkASSERT(0 == localUniform.fUBOffset); firstFragOffsetCheck = true; } } } #endif SkString uniformsString; for (int i = 0; i < fUniforms.count(); ++i) { const UniformInfo& localUniform = fUniforms[i]; if (visibility & localUniform.fVisibility) { if (GrSLTypeIsFloatType(localUniform.fVariable.getType())) { localUniform.fVariable.appendDecl(fProgramBuilder->shaderCaps(), &uniformsString); uniformsString.append(";\n"); } } } if (!uniformsString.isEmpty()) { uint32_t uniformBinding; const char* stage; if (kVertex_GrShaderFlag == visibility) { uniformBinding = kGeometryBinding; stage = "vertex"; } else if (kGeometry_GrShaderFlag == visibility) { uniformBinding = kGeometryBinding; stage = "geometry"; } else { SkASSERT(kFragment_GrShaderFlag == visibility); uniformBinding = kFragBinding; stage = "fragment"; } out->appendf("layout (set=%d, binding=%d) uniform %sUniformBuffer\n{\n", kUniformBufferDescSet, uniformBinding, stage); out->appendf("%s\n};\n", uniformsString.c_str()); } }