mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Fix, Test] (GLState, ShaderTranspiler): report GL's default binding of zero for an unqualified uniform block
This commit is contained in:
@@ -627,7 +627,8 @@ namespace MobileGL::MG_State::GLState {
|
||||
.explicitFragmentOutLocations = in.explicitFragDataLocation,
|
||||
.explicitFragmentOutIndices = in.explicitFragDataIndex,
|
||||
.explicitOpaqueUniformBindings = &artifacts.explicitOpaqueUniformBindings,
|
||||
.storageBlocksWithoutBinding = &artifacts.storageBlocksWithoutBinding};
|
||||
.storageBlocksWithoutBinding = &artifacts.storageBlocksWithoutBinding,
|
||||
.uniformBlocksWithoutBinding = &artifacts.uniformBlocksWithoutBinding};
|
||||
|
||||
MGLOG_D("ProgramObject %u: Calling ShaderCompiler::LinkProgram", in.externalIndex);
|
||||
auto result = ShaderCompiler::LinkProgram(attrib);
|
||||
@@ -1573,7 +1574,25 @@ namespace MobileGL::MG_State::GLState {
|
||||
// (DirectGLES.cpp / UniformManager.cpp), all 14 elements also read the same
|
||||
// buffer. This is the rule the storage-block path in ProgramInterface.cpp
|
||||
// already applies, and whose comment there claims uniform blocks follow.
|
||||
const Int declaredBinding = ubo.getBinding();
|
||||
//
|
||||
// "Declared" cannot be read back off the reflection, though. MobileGL asks glslang
|
||||
// to auto-map bindings, so mapIO writes an invented one into every block's
|
||||
// qualifier before reflection ever runs and ubo.getBinding() is never negative;
|
||||
// worse, glslang packs uniform blocks into the SAME slot space as samplers and
|
||||
// images (setEnvClient(EShClientVulkan) leaves spvVersion.openGl at 0, so
|
||||
// TDefaultGlslIoResolver::resolveBinding keys every resource kind on set 0), so a
|
||||
// block declared after an unbound image gets 1. GL 4.6 core 7.6.2 says an
|
||||
// unqualified block reports ZERO. The set below is the shader's own answer,
|
||||
// captured during mapIO while the qualifier still meant it - the same mechanism
|
||||
// SeedDefaultStorageBlockBindings uses for storage blocks, and the aliasing at 0
|
||||
// that results is GL's, not a bug: unqualified blocks collide there until the
|
||||
// application rebinds them.
|
||||
//
|
||||
// Only this GL-visible binding POINT changes. The backends' descriptor lookups run
|
||||
// off glslang's assignment through uniformBlockIndexByBinding, which is untouched.
|
||||
const String blockTypeName = StripArrayElementSuffix(ubo.name);
|
||||
const Int declaredBinding =
|
||||
artifacts.uniformBlocksWithoutBinding.contains(blockTypeName) ? 0 : ubo.getBinding();
|
||||
artifacts.uniformBlockBinding[i] =
|
||||
declaredBinding < 0 ? declaredBinding : declaredBinding + BlockArrayElement(ubo.name);
|
||||
MGLOG_D("ProgramObject %u: Reflection - UBO[%d] name='%s' size=%u binding=%d", in.externalIndex, i,
|
||||
|
||||
@@ -369,6 +369,7 @@ namespace MobileGL::MG_State::GLState {
|
||||
// link, so a stale set would otherwise default a block the new sources do declare a
|
||||
// binding for.
|
||||
artifacts.storageBlocksWithoutBinding.clear();
|
||||
artifacts.uniformBlocksWithoutBinding.clear();
|
||||
artifacts.attribs.clear();
|
||||
artifacts.attribTypes.clear();
|
||||
artifacts.activeUniformCount = 0;
|
||||
|
||||
@@ -1024,8 +1024,10 @@ namespace MobileGL::MG_State::GLState {
|
||||
Uint32 GetBlockBindingVersion() const { return m_blockBindingVersion; }
|
||||
|
||||
// Set by glUniformBlockBinding. The vector is seeded at link with each block's DECLARED
|
||||
// binding (layout(binding=N), else -1), so an untouched program already reports what its
|
||||
// shaders asked for.
|
||||
// binding (layout(binding=N)), and with GL's default of 0 for a block that declared none
|
||||
// - which the reflection cannot tell apart on its own, so the seeder consults
|
||||
// uniformBlocksWithoutBinding. Either way an untouched program already reports what GL
|
||||
// says it should.
|
||||
void SetUniformBlockBinding(Uint index, Uint binding) {
|
||||
if (index >= Artifacts().uniformBlockBinding.size() || Artifacts().uniformBlockBinding[index] == static_cast<Int>(binding)) {
|
||||
return;
|
||||
@@ -1287,6 +1289,11 @@ namespace MobileGL::MG_State::GLState {
|
||||
// binding from an invented one - and, unlike the per-shader lexer this replaced,
|
||||
// sees the declaration with its macros expanded.
|
||||
std::set<String> storageBlocksWithoutBinding;
|
||||
// The same list for UNIFORM blocks, and it is needed for the same reason: glslang's
|
||||
// auto-mapper assigns every uniform block a binding whether or not the shader asked
|
||||
// for one, so uniformBlockBinding below cannot tell "declared 1" from "invented 1".
|
||||
// GL 4.6 core 7.6.2 requires an unqualified block to report ZERO.
|
||||
std::set<String> uniformBlocksWithoutBinding;
|
||||
|
||||
Uint activeUniformCount = 0;
|
||||
Uint maxUniformLocation = 0;
|
||||
|
||||
Reference in New Issue
Block a user