GlslShaderJob implements ShaderJob { @Override public void makeUniformBindings(Optional<String> pushConstant) { for (String uniformName : getPipelineInfo().getUniformNames()) { assert !getPipelineInfo().hasBindingOrIsPushConstant(uniformName); } final Set<Integer> usedBindings = findUsedBindings(); int nextBinding = 0; while (usedBindings.contains(nextBinding)) { nextBinding++; } for (TranslationUnit tu : shaders) { final List<Declaration> newTopLevelDeclarations = new ArrayList<>(); for (Declaration decl : tu.getTopLevelDeclarations()) { if (decl instanceof VariablesDeclaration && ((VariablesDeclaration) decl).getBaseType().hasQualifier(TypeQualifier.UNIFORM)) { final VariablesDeclaration variablesDeclaration = (VariablesDeclaration) decl; assert !(variablesDeclaration.getBaseType().getWithoutQualifiers() instanceof ArrayType) : "We cannot yet deal with uniforms with array base types, such as " + "'uniform float[5] A;'."; for (VariableDeclInfo declInfo : variablesDeclaration.getDeclInfos()) { final String uniformName = declInfo.getName(); assert pipelineInfo.hasUniform(uniformName); if (pushConstant.isPresent() && pushConstant.get().equals(uniformName)) { pipelineInfo.addUniformBinding(uniformName, true, 0); } else if (!pipelineInfo.hasBinding(uniformName)) { pipelineInfo.addUniformBinding(uniformName, false, nextBinding); do { nextBinding++; } while (usedBindings.contains(nextBinding)); } final Type baseType = variablesDeclaration.getBaseType(); final Type targetType = baseType.getWithoutQualifiers(); if (targetType instanceof SamplerType) { assert !declInfo.hasArrayInfo() : "We cannot yet deal with arrays of samplers."; assert !pipelineInfo.isPushConstant(uniformName) : "A sampler cannot be a push " + "constant"; final int binding = pipelineInfo.getBinding(uniformName); newTopLevelDeclarations.add( new VariablesDeclaration( new QualifiedType(targetType, Arrays.asList( new LayoutQualifierSequence( new SetLayoutQualifier(0), new BindingLayoutQualifier(binding)), TypeQualifier.UNIFORM )), declInfo)); } else { final Type memberType = Typer.combineBaseTypeAndArrayInfo(baseType, declInfo.getArrayInfo()).clone(); ((QualifiedType) memberType).removeQualifier(TypeQualifier.UNIFORM); if (pipelineInfo.isPushConstant(uniformName)) { newTopLevelDeclarations.add( new InterfaceBlock( of(new LayoutQualifierSequence(new PushConstantLayoutQualifier())), TypeQualifier.UNIFORM, "buf_push", Collections.singletonList(uniformName), Collections.singletonList(memberType), Optional.empty()) ); } else { final int binding = pipelineInfo.getBinding(uniformName); newTopLevelDeclarations.add( new InterfaceBlock( of(new LayoutQualifierSequence(new SetLayoutQualifier(0), new BindingLayoutQualifier(binding))), TypeQualifier.UNIFORM, "buf" + binding, Collections.singletonList(uniformName), Collections.singletonList(memberType), Optional.empty()) ); } } } } else { newTopLevelDeclarations.add(decl); } } tu.setTopLevelDeclarations(newTopLevelDeclarations); } for (String uniformName : getPipelineInfo().getUniformNames()) { if (!getPipelineInfo().hasBindingOrIsPushConstant(uniformName)) { if (pushConstant.isPresent() && pushConstant.get().equals(uniformName)) { getPipelineInfo().addUniformBinding(uniformName, true, 0); } else { getPipelineInfo().addUniformBinding(uniformName, false, nextBinding++); } } } } GlslShaderJob(Optional<String> license,
                       PipelineInfo pipelineInfo,
                       List<TranslationUnit> shaders);  GlslShaderJob(Optional<String> license,
                       PipelineInfo pipelineInfo,
                       TranslationUnit... shaders); @Override PipelineInfo getPipelineInfo(); @Override Optional<String> getLicense(); @Override void makeUniformBindings(Optional<String> pushConstant); @Override void removeUniformBindings(); @Override boolean hasUniformBindings(); @Override Optional<String> getPushConstant(); @Override List<TranslationUnit> getShaders(); @Override Optional<TranslationUnit> getVertexShader(); @Override Optional<TranslationUnit> getFragmentShader(); @Override Optional<TranslationUnit> getComputeShader(); @Override GlslShaderJob clone();  }
@Test public void testMakeUniformBindings() throws Exception { final GlslShaderJob job = new GlslShaderJob( Optional.empty(), new PipelineInfo(JSON_NO_BINDINGS), ParseHelper.parse(getShaderFile("vert", VERT_SHADER_NO_BINDINGS)), ParseHelper.parse(getShaderFile("frag", FRAG_SHADER_NO_BINDINGS))); job.makeUniformBindings(Optional.empty()); CompareAsts.assertEqualAsts(VERT_SHADER_WITH_BINDINGS, job.getVertexShader().get()); CompareAsts.assertEqualAsts(FRAG_SHADER_WITH_BINDINGS, job.getFragmentShader().get()); assertEquals(new PipelineInfo(JSON_WITH_BINDINGS).toString(), job.getPipelineInfo().toString()); }