mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Fix]: fix Chocapic V6 Lite
- prune unused SPIR-V interface variables before GLES transpilation - remap shader varyings through glslang IO resolver bindings - initialize opaque uniforms from explicit sampler bindings only - avoid side effects in texture binding assertions - register Chocapic V6 Lite retrace fixture
This commit is contained in:
@@ -1589,8 +1589,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
MOBILEGL_ASSERT(mipmapTexture != nullptr, "GenerateMipmap requires mipmap texture storage.");
|
MOBILEGL_ASSERT(mipmapTexture != nullptr, "GenerateMipmap requires mipmap texture storage.");
|
||||||
Bool allocatedStorage = false;
|
Bool allocatedStorage = false;
|
||||||
for (const TextureUploadTarget uploadTarget : texture->GetUploadTargets()) {
|
for (const TextureUploadTarget uploadTarget : texture->GetUploadTargets()) {
|
||||||
MOBILEGL_ASSERT(EnsureGenerateMipmapStorageAllocated(*mipmapTexture, uploadTarget, allocatedStorage),
|
const Bool allocated = EnsureGenerateMipmapStorageAllocated(*mipmapTexture, uploadTarget, allocatedStorage);
|
||||||
"GenerateMipmap could not allocate generated mipmap storage.");
|
MOBILEGL_ASSERT(allocated, "GenerateMipmap could not allocate generated mipmap storage.");
|
||||||
}
|
}
|
||||||
return allocatedStorage;
|
return allocatedStorage;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -554,11 +554,79 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
currentTextureInfo.mipmapLevels = mipmapCount;
|
currentTextureInfo.mipmapLevels = mipmapCount;
|
||||||
|
|
||||||
Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo);
|
Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo);
|
||||||
|
const Bool canAppendMipmaps =
|
||||||
|
m_isInitialized &&
|
||||||
|
currentTextureInfo.internalFormat == m_prevTextureInfo.internalFormat &&
|
||||||
|
currentTextureInfo.width == m_prevTextureInfo.width &&
|
||||||
|
currentTextureInfo.height == m_prevTextureInfo.height &&
|
||||||
|
currentTextureInfo.depth == m_prevTextureInfo.depth &&
|
||||||
|
currentTextureInfo.bufferExternalIndex == m_prevTextureInfo.bufferExternalIndex &&
|
||||||
|
currentTextureInfo.samples == m_prevTextureInfo.samples &&
|
||||||
|
currentTextureInfo.fixedSampleLocations == m_prevTextureInfo.fixedSampleLocations &&
|
||||||
|
currentTextureInfo.mipmapLevels > m_prevTextureInfo.mipmapLevels &&
|
||||||
|
!TextureImpl::IsMultisampleTextureTarget(targetInternal);
|
||||||
|
|
||||||
MGLOG_D("%s: Got texture info: %dx%dx%d, mips %d, format %s", __func__, baseSize.x(), baseSize.y(),
|
MGLOG_D("%s: Got texture info: %dx%dx%d, mips %d, format %s", __func__, baseSize.x(), baseSize.y(),
|
||||||
baseSize.z(), mipmapCount,
|
baseSize.z(), mipmapCount,
|
||||||
MG_Util::ConvertTextureInternalFormatToString(textureMipmapObject->GetFormat()).c_str());
|
MG_Util::ConvertTextureInternalFormatToString(textureMipmapObject->GetFormat()).c_str());
|
||||||
|
|
||||||
|
if (canAppendMipmaps) {
|
||||||
|
MGLOG_D("Texture mip count increased for backend ID %u, appending levels %zu..%zu",
|
||||||
|
m_backendTextureId, m_prevTextureInfo.mipmapLevels, mipmapCount - 1);
|
||||||
|
|
||||||
|
GLenum glInternalFormat, glType, glFormat;
|
||||||
|
TextureImpl::GenerateTextureFormatInfo(textureMipmapObject->GetFormat(), &glInternalFormat,
|
||||||
|
&glFormat, &glType);
|
||||||
|
|
||||||
|
const auto& uploadTargets = textureMipmapObject->GetUploadTargets();
|
||||||
|
for (auto& uploadTarget : uploadTargets) {
|
||||||
|
for (SizeT level = m_prevTextureInfo.mipmapLevels; level < mipmapCount; ++level) {
|
||||||
|
auto levelTexelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
|
||||||
|
auto levelByteSize = textureMipmapObject->GetMipmapByteSize(uploadTarget, level);
|
||||||
|
bool levelDirty = textureMipmapObject->IsStorageDirty(uploadTarget, level);
|
||||||
|
auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget);
|
||||||
|
auto* pData = (levelDirty && levelByteSize != 0)
|
||||||
|
? textureMipmapObject->MapMipmapData(uploadTarget, level)
|
||||||
|
: nullptr;
|
||||||
|
|
||||||
|
DebugImpl::ErrorLopper::Clear();
|
||||||
|
g_GLESFuncs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
switch (stateTextureObject->GetTarget()) {
|
||||||
|
case TextureTarget::Texture2D:
|
||||||
|
case TextureTarget::TextureCubeMap:
|
||||||
|
g_GLESFuncs.glTexImage2D(
|
||||||
|
glUploadTarget, static_cast<GLint>(level), (GLint)glInternalFormat,
|
||||||
|
static_cast<GLsizei>(levelTexelSize.x()), static_cast<GLsizei>(levelTexelSize.y()),
|
||||||
|
0, glFormat, glType, pData);
|
||||||
|
break;
|
||||||
|
case TextureTarget::Texture3D:
|
||||||
|
g_GLESFuncs.glTexImage3D(
|
||||||
|
glUploadTarget, static_cast<GLint>(level), (GLint)glInternalFormat,
|
||||||
|
static_cast<GLsizei>(levelTexelSize.x()), static_cast<GLsizei>(levelTexelSize.y()),
|
||||||
|
static_cast<GLsizei>(levelTexelSize.z()), 0, glFormat, glType, pData);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MGLOG_E("Unhandled texture target %s",
|
||||||
|
MG_Util::ConvertTextureTargetToString(stateTextureObject->GetTarget()).c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__,
|
||||||
|
glUploadTarget, glInternalFormat, glFormat, glType,
|
||||||
|
pData](GLenum err) {
|
||||||
|
MGLOG_D("%s(%s:%d) ES error: %s. glTexImage*: target=%s, internalformat=%s, format=%s, "
|
||||||
|
"type=%s, pixels=%p",
|
||||||
|
func, file, line, MG_Util::ConvertGLEnumToString(err).c_str(),
|
||||||
|
MG_Util::ConvertGLEnumToString(glUploadTarget).c_str(),
|
||||||
|
MG_Util::ConvertGLEnumToString(glInternalFormat).c_str(),
|
||||||
|
MG_Util::ConvertGLEnumToString(glFormat).c_str(),
|
||||||
|
MG_Util::ConvertGLEnumToString(glType).c_str(), pData);
|
||||||
|
});
|
||||||
|
textureMipmapObject->MarkStorageDirty(uploadTarget, level, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
needsRegeneration = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (needsRegeneration) {
|
if (needsRegeneration) {
|
||||||
MGLOG_D("Texture state changed significantly or not initialized, regenerating texture with ID: %u",
|
MGLOG_D("Texture state changed significantly or not initialized, regenerating texture with ID: %u",
|
||||||
m_backendTextureId);
|
m_backendTextureId);
|
||||||
|
|||||||
@@ -4212,8 +4212,9 @@ void main() {
|
|||||||
static_cast<Int>(resource->format));
|
static_cast<Int>(resource->format));
|
||||||
}
|
}
|
||||||
|
|
||||||
MOBILEGL_ASSERT(EnsureGenerateMipmapStorageAllocated(*mipmapTexture, uploadTarget, baseMipLevel),
|
const Bool allocatedMipmapStorage =
|
||||||
"GenerateMipmap could not allocate a full mip chain for this texture.");
|
EnsureGenerateMipmapStorageAllocated(*mipmapTexture, uploadTarget, baseMipLevel);
|
||||||
|
MOBILEGL_ASSERT(allocatedMipmapStorage, "GenerateMipmap could not allocate a full mip chain for this texture.");
|
||||||
|
|
||||||
resource = m_textureManager->SyncTextureAndGetDescriptor(*texture);
|
resource = m_textureManager->SyncTextureAndGetDescriptor(*texture);
|
||||||
MOBILEGL_ASSERT(resource != nullptr && resource->image != VK_NULL_HANDLE,
|
MOBILEGL_ASSERT(resource != nullptr && resource->image != VK_NULL_HANDLE,
|
||||||
|
|||||||
@@ -2837,16 +2837,16 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
if (textureObject) {
|
if (textureObject) {
|
||||||
auto* mipmapTexture = dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
auto* mipmapTexture = dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
||||||
MOBILEGL_ASSERT(mipmapTexture != nullptr, "GenerateMipmap requires mipmap texture storage.");
|
MOBILEGL_ASSERT(mipmapTexture != nullptr, "GenerateMipmap requires mipmap texture storage.");
|
||||||
for (const TextureUploadTarget uploadTarget : textureObject->GetUploadTargets()) {
|
|
||||||
MOBILEGL_ASSERT(EnsureGeneratedMipmapStorageAllocated(*mipmapTexture, uploadTarget),
|
|
||||||
"GenerateMipmap could not allocate generated mipmap state.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
GenerateMipmap_Backend(target);
|
GenerateMipmap_Backend(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateTextureMipmap(GLuint texture) {
|
void GenerateTextureMipmap(GLuint texture) {
|
||||||
auto textureObject = GetTextureObjectByName(texture, __func__);
|
auto textureObject = GetTextureObjectByName(texture, __func__);
|
||||||
|
if (textureObject) {
|
||||||
|
auto* mipmapTexture = dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
||||||
|
MOBILEGL_ASSERT(mipmapTexture != nullptr, "GenerateTextureMipmap requires mipmap texture storage.");
|
||||||
|
}
|
||||||
WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { GenerateMipmap_Backend(target); });
|
WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { GenerateMipmap_Backend(target); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
m_uniformLocations.clear();
|
m_uniformLocations.clear();
|
||||||
m_uniformIndexInTProgram.clear();
|
m_uniformIndexInTProgram.clear();
|
||||||
m_uniformSamplerOrImageUnitIndex.clear();
|
m_uniformSamplerOrImageUnitIndex.clear();
|
||||||
|
m_explicitOpaqueUniformBindings.clear();
|
||||||
m_uniformBlockIndexByName.clear();
|
m_uniformBlockIndexByName.clear();
|
||||||
m_uniformBlockBinding.clear();
|
m_uniformBlockBinding.clear();
|
||||||
m_uniformOffsets.clear();
|
m_uniformOffsets.clear();
|
||||||
@@ -199,7 +200,9 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
|
|
||||||
MG_Util::ShaderTranspiler::ProgramAttrib attrib{.shaders = Move(shaders),
|
MG_Util::ShaderTranspiler::ProgramAttrib attrib{.shaders = Move(shaders),
|
||||||
.explicitVertexInLocations = m_explicitAttribLocations,
|
.explicitVertexInLocations = m_explicitAttribLocations,
|
||||||
.explicitFragmentOutLocations = m_explicitFragDataLocation};
|
.explicitFragmentOutLocations = m_explicitFragDataLocation,
|
||||||
|
.explicitOpaqueUniformBindings =
|
||||||
|
&m_explicitOpaqueUniformBindings};
|
||||||
|
|
||||||
MGLOG_D("ProgramObject %u: Calling ShaderCompiler::LinkProgram", m_externalIndex);
|
MGLOG_D("ProgramObject %u: Calling ShaderCompiler::LinkProgram", m_externalIndex);
|
||||||
auto result = MG_Util::ShaderTranspiler::ShaderCompiler::LinkProgram(attrib);
|
auto result = MG_Util::ShaderTranspiler::ShaderCompiler::LinkProgram(attrib);
|
||||||
@@ -306,6 +309,11 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SizeT locNeedle = 0;
|
SizeT locNeedle = 0;
|
||||||
|
std::sort(unallocatedUniformIndex.begin(), unallocatedUniformIndex.end(), [this](Int lhs, Int rhs) {
|
||||||
|
const auto& lhsUniform = m_program->getUniform(lhs);
|
||||||
|
const auto& rhsUniform = m_program->getUniform(rhs);
|
||||||
|
return lhsUniform.name < rhsUniform.name;
|
||||||
|
});
|
||||||
for (auto index : unallocatedUniformIndex) {
|
for (auto index : unallocatedUniformIndex) {
|
||||||
auto& uniform = m_program->getUniform(index);
|
auto& uniform = m_program->getUniform(index);
|
||||||
for (; locNeedle <= m_maxUniformLocation; locNeedle++) {
|
for (; locNeedle <= m_maxUniformLocation; locNeedle++) {
|
||||||
@@ -334,12 +342,12 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int binding = uniform.getBinding();
|
const auto explicitBinding = m_explicitOpaqueUniformBindings.find(uniform.name);
|
||||||
if (binding >= 0 && binding != static_cast<int>(glslang::TQualifier::layoutBindingEnd)) {
|
const int initialUnit =
|
||||||
m_uniformSamplerOrImageUnitIndex[location] = binding;
|
explicitBinding != m_explicitOpaqueUniformBindings.end() ? static_cast<int>(explicitBinding->second) : 0;
|
||||||
MGLOG_D("ProgramObject %u: Reflection - opaque uniform '%s' location=%u initialUnit=%d",
|
m_uniformSamplerOrImageUnitIndex[location] = initialUnit;
|
||||||
m_externalIndex, uniform.name.c_str(), location, binding);
|
MGLOG_D("ProgramObject %u: Reflection - opaque uniform '%s' location=%u initialUnit=%d",
|
||||||
}
|
m_externalIndex, uniform.name.c_str(), location, initialUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------ attributes (vertex in) ---------------
|
// ------------ attributes (vertex in) ---------------
|
||||||
@@ -461,7 +469,8 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
// 2. Do actual linking
|
// 2. Do actual linking
|
||||||
ProgramAttrib attrib{.shaders = Move(shaders),
|
ProgramAttrib attrib{.shaders = Move(shaders),
|
||||||
.explicitVertexInLocations = m_explicitAttribLocations,
|
.explicitVertexInLocations = m_explicitAttribLocations,
|
||||||
.explicitFragmentOutLocations = m_explicitFragDataLocation};
|
.explicitFragmentOutLocations = m_explicitFragDataLocation,
|
||||||
|
.explicitOpaqueUniformBindings = &m_explicitOpaqueUniformBindings};
|
||||||
MGLOG_D("ProgramObject %u: GenerateBinary - linking program for binary", m_externalIndex);
|
MGLOG_D("ProgramObject %u: GenerateBinary - linking program for binary", m_externalIndex);
|
||||||
auto programResult = ShaderCompiler::LinkProgram(attrib);
|
auto programResult = ShaderCompiler::LinkProgram(attrib);
|
||||||
if (!programResult) {
|
if (!programResult) {
|
||||||
@@ -495,6 +504,8 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
m_uniformSizesInBytes.clear();
|
m_uniformSizesInBytes.clear();
|
||||||
m_uniformOffsets.clear();
|
m_uniformOffsets.clear();
|
||||||
m_globalUboScratch.clear();
|
m_globalUboScratch.clear();
|
||||||
|
m_uniformOffsets.resize(m_maxUniformLocation + 1);
|
||||||
|
m_uniformSizesInBytes.resize(m_maxUniformLocation + 1);
|
||||||
for (SizeT i = 0; i < m_generatedSpirv.size(); i++) {
|
for (SizeT i = 0; i < m_generatedSpirv.size(); i++) {
|
||||||
auto& spv = m_generatedSpirv[i];
|
auto& spv = m_generatedSpirv[i];
|
||||||
|
|
||||||
@@ -520,37 +531,34 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
m_globalUboScratch.resize(size);
|
if (m_globalUboScratch.size() < size) {
|
||||||
m_uniformOffsets.resize(m_maxUniformLocation + 1);
|
m_globalUboScratch.resize(size);
|
||||||
|
}
|
||||||
for (const auto& [name, offset] : meta.plainUniformOffsetsInUBO) {
|
for (const auto& [name, offset] : meta.plainUniformOffsetsInUBO) {
|
||||||
if (m_uniformLocations.find(name) != m_uniformLocations.end()) {
|
if (m_uniformLocations.find(name) != m_uniformLocations.end()) {
|
||||||
m_uniformOffsets[m_uniformLocations[name]] = offset;
|
m_uniformOffsets[m_uniformLocations[name]] = offset;
|
||||||
MGLOG_D("ProgramObject %u: GenerateBinary - uniform '%s' offset=%u assigned to location %u",
|
MGLOG_D("ProgramObject %u: GenerateBinary - uniform '%s' offset=%u assigned to location %u",
|
||||||
m_externalIndex, name.c_str(), offset, m_uniformLocations[name]);
|
m_externalIndex, name.c_str(), offset, m_uniformLocations[name]);
|
||||||
} else {
|
} else {
|
||||||
MGLOG_D("ProgramObject %u: GenerateBinary - uniform '%s' offset=%u but not found in "
|
MGLOG_D("ProgramObject %u: GenerateBinary - uniform '%s' offset=%u but not found in "
|
||||||
"m_uniformLocations",
|
"m_uniformLocations",
|
||||||
m_externalIndex, name.c_str(), offset);
|
m_externalIndex, name.c_str(), offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_uniformSizesInBytes.resize(m_maxUniformLocation + 1);
|
|
||||||
for (const auto& [name, size] : meta.plainUniformMemberSizesInBytes) {
|
for (const auto& [name, size] : meta.plainUniformMemberSizesInBytes) {
|
||||||
if (m_uniformLocations.find(name) != m_uniformLocations.end()) {
|
if (m_uniformLocations.find(name) != m_uniformLocations.end()) {
|
||||||
m_uniformSizesInBytes[m_uniformLocations[name]] = size;
|
m_uniformSizesInBytes[m_uniformLocations[name]] = size;
|
||||||
MGLOG_D("ProgramObject %u: GenerateBinary - uniform '%s' size=%u assigned to location %u",
|
MGLOG_D("ProgramObject %u: GenerateBinary - uniform '%s' size=%u assigned to location %u",
|
||||||
m_externalIndex, name.c_str(), size, m_uniformLocations[name]);
|
m_externalIndex, name.c_str(), size, m_uniformLocations[name]);
|
||||||
} else {
|
} else {
|
||||||
MGLOG_D("ProgramObject %u: GenerateBinary - uniform '%s' size=%u but not found in "
|
MGLOG_D("ProgramObject %u: GenerateBinary - uniform '%s' size=%u but not found in "
|
||||||
"m_uniformLocations",
|
"m_uniformLocations",
|
||||||
m_externalIndex, name.c_str(), size);
|
m_externalIndex, name.c_str(), size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Only parse first module that contains uniform metadata
|
MGLOG_D("ProgramObject %u: GenerateBinary - finished parsing module %zu metadata",
|
||||||
MGLOG_D("ProgramObject %u: GenerateBinary - finished parsing module %zu; breaking after first "
|
|
||||||
"valid metadata",
|
|
||||||
m_externalIndex, i);
|
m_externalIndex, i);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -162,7 +162,12 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
Uint32 GetBackendStateVersion() const { return m_backendStateVersion; }
|
Uint32 GetBackendStateVersion() const { return m_backendStateVersion; }
|
||||||
|
|
||||||
void SetUniformSamplerOrImageUnitIndex(Uint location, Int unit) {
|
void SetUniformSamplerOrImageUnitIndex(Uint location, Int unit) {
|
||||||
|
if (location >= m_uniformSamplerOrImageUnitIndex.size() ||
|
||||||
|
m_uniformSamplerOrImageUnitIndex[location] == unit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_uniformSamplerOrImageUnitIndex[location] = unit;
|
m_uniformSamplerOrImageUnitIndex[location] = unit;
|
||||||
|
++m_backendStateVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
Int GetUniformSamplerOrImageUnitIndex(Uint location) const {
|
Int GetUniformSamplerOrImageUnitIndex(Uint location) const {
|
||||||
@@ -260,6 +265,7 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
Vector<Int> m_uniformIndexInTProgram;
|
Vector<Int> m_uniformIndexInTProgram;
|
||||||
// ditto. Will be set at glUniform1i
|
// ditto. Will be set at glUniform1i
|
||||||
Vector<Int> m_uniformSamplerOrImageUnitIndex;
|
Vector<Int> m_uniformSamplerOrImageUnitIndex;
|
||||||
|
UnorderedMap<String, Uint> m_explicitOpaqueUniformBindings;
|
||||||
|
|
||||||
// Ordered by uniform block index
|
// Ordered by uniform block index
|
||||||
// index is DIFFERENT from binding!!!
|
// index is DIFFERENT from binding!!!
|
||||||
|
|||||||
@@ -197,7 +197,8 @@ namespace MobileGL {
|
|||||||
if (program->getIntermediate((EShLanguage)stage) == nullptr) continue;
|
if (program->getIntermediate((EShLanguage)stage) == nullptr) continue;
|
||||||
resolver =
|
resolver =
|
||||||
MakeUnique<TMglGlslIoResolver>(*program, (EShLanguage)stage, attrib.explicitVertexInLocations,
|
MakeUnique<TMglGlslIoResolver>(*program, (EShLanguage)stage, attrib.explicitVertexInLocations,
|
||||||
attrib.explicitFragmentOutLocations);
|
attrib.explicitFragmentOutLocations,
|
||||||
|
attrib.explicitOpaqueUniformBindings);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto ioMapper = UniquePtr<glslang::TIoMapper>(glslang::GetGlslIoMapper());
|
auto ioMapper = UniquePtr<glslang::TIoMapper>(glslang::GetGlslIoMapper());
|
||||||
@@ -235,6 +236,8 @@ namespace MobileGL {
|
|||||||
|
|
||||||
Optimizer optimizer(SPV_ENV_VULKAN_1_1);
|
Optimizer optimizer(SPV_ENV_VULKAN_1_1);
|
||||||
|
|
||||||
|
optimizer.RegisterPass(CreateAggressiveDCEPass(false));
|
||||||
|
optimizer.RegisterPass(CreateRemoveUnusedInterfaceVariablesPass());
|
||||||
optimizer.RegisterPass(FlattenInterfaceStructPass::CreateFlattenInterfaceStructPass());
|
optimizer.RegisterPass(FlattenInterfaceStructPass::CreateFlattenInterfaceStructPass());
|
||||||
optimizer.RegisterPass(EliminateFloatEqualsZeroPass::CreateEliminateFloatEqualsZeroPass());
|
optimizer.RegisterPass(EliminateFloatEqualsZeroPass::CreateEliminateFloatEqualsZeroPass());
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ namespace MobileGL {
|
|||||||
Vector<SharedPtr<glslang::TShader>> shaders;
|
Vector<SharedPtr<glslang::TShader>> shaders;
|
||||||
UnorderedMap<String, Uint> explicitVertexInLocations;
|
UnorderedMap<String, Uint> explicitVertexInLocations;
|
||||||
UnorderedMap<String, Uint> explicitFragmentOutLocations;
|
UnorderedMap<String, Uint> explicitFragmentOutLocations;
|
||||||
|
UnorderedMap<String, Uint>* explicitOpaqueUniformBindings = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProgramBinaryAttrib {
|
struct ProgramBinaryAttrib {
|
||||||
|
|||||||
@@ -13,6 +13,53 @@
|
|||||||
#include "TMglGlslIoResolver.h"
|
#include "TMglGlslIoResolver.h"
|
||||||
|
|
||||||
namespace MobileGL {
|
namespace MobileGL {
|
||||||
|
bool TMglGlslIoResolver::ShouldAssignPlainUniformLocation(const glslang::TType& type) const {
|
||||||
|
if (!doAutoLocationMapping()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.getQualifier().hasLocation()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.isBuiltIn() || type.getBasicType() == glslang::EbtBlock || type.isAtomic() || type.isSpirvType() ||
|
||||||
|
(type.containsOpaque() && referenceIntermediate.getSpv().openGl == 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.isStruct()) {
|
||||||
|
if (type.getStruct()->size() < 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((*type.getStruct())[0].type->isBuiltIn()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TMglGlslIoResolver::EnsurePlainUniformLocationsAssigned() {
|
||||||
|
if (m_plainUniformLocationsAssigned) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_plainUniformLocationsAssigned = true;
|
||||||
|
|
||||||
|
const int resourceKey = buildStorageKey(EShLangCount, glslang::EvqUniform);
|
||||||
|
auto& slotMap = storageSlotMap[resourceKey];
|
||||||
|
for (const auto& [name, size] : m_plainUniformLocationSizeByName) {
|
||||||
|
const auto existingLocation = slotMap.find(name);
|
||||||
|
if (existingLocation != slotMap.end()) {
|
||||||
|
m_plainUniformLocationByName[name] = existingLocation->second;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int location = getFreeSlot(resourceKey, 0, size);
|
||||||
|
slotMap[name] = location;
|
||||||
|
m_plainUniformLocationByName[name] = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TMglGlslIoResolver::reserverStorageSlot(glslang::TVarEntryInfo& ent, TInfoSink& infoSink) {
|
void TMglGlslIoResolver::reserverStorageSlot(glslang::TVarEntryInfo& ent, TInfoSink& infoSink) {
|
||||||
const glslang::TType& type = ent.symbol->getType();
|
const glslang::TType& type = ent.symbol->getType();
|
||||||
const glslang::TString& name = ent.symbol->getAccessName();
|
const glslang::TString& name = ent.symbol->getAccessName();
|
||||||
@@ -30,6 +77,43 @@ namespace MobileGL {
|
|||||||
writableType.getQualifier().layoutLocation = it->second;
|
writableType.getQualifier().layoutLocation = it->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ShouldAssignPlainUniformLocation(type)) {
|
||||||
|
const int size = glslang::TIntermediate::computeTypeUniformLocationSize(type);
|
||||||
|
auto& recordedSize = m_plainUniformLocationSizeByName[name];
|
||||||
|
recordedSize = std::max(recordedSize, size);
|
||||||
|
}
|
||||||
TDefaultGlslIoResolver::reserverStorageSlot(ent, infoSink);
|
TDefaultGlslIoResolver::reserverStorageSlot(ent, infoSink);
|
||||||
}
|
}
|
||||||
} // namespace MobileGL
|
|
||||||
|
void TMglGlslIoResolver::reserverResourceSlot(glslang::TVarEntryInfo& ent, TInfoSink& infoSink) {
|
||||||
|
const glslang::TType& type = ent.symbol->getType();
|
||||||
|
if (m_explicitOpaqueUniformBindings != nullptr && type.getBasicType() == glslang::EbtSampler &&
|
||||||
|
type.getQualifier().hasBinding()) {
|
||||||
|
const glslang::TString& name = ent.symbol->getAccessName();
|
||||||
|
(*m_explicitOpaqueUniformBindings)[name.c_str()] = type.getQualifier().layoutBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
TDefaultGlslIoResolver::reserverResourceSlot(ent, infoSink);
|
||||||
|
}
|
||||||
|
|
||||||
|
int TMglGlslIoResolver::resolveUniformLocation(EShLanguage stage, glslang::TVarEntryInfo& ent) {
|
||||||
|
const glslang::TType& type = ent.symbol->getType();
|
||||||
|
if (type.getQualifier().hasLocation()) {
|
||||||
|
return TDefaultGlslIoResolver::resolveUniformLocation(stage, ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ShouldAssignPlainUniformLocation(type)) {
|
||||||
|
return TDefaultGlslIoResolver::resolveUniformLocation(stage, ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsurePlainUniformLocationsAssigned();
|
||||||
|
|
||||||
|
const glslang::TString& name = ent.symbol->getAccessName();
|
||||||
|
const auto location = m_plainUniformLocationByName.find(name);
|
||||||
|
if (location == m_plainUniformLocationByName.end()) {
|
||||||
|
return ent.newLocation = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ent.newLocation = location->second;
|
||||||
|
}
|
||||||
|
} // namespace MobileGL
|
||||||
|
|||||||
@@ -26,15 +26,26 @@ namespace MobileGL {
|
|||||||
public:
|
public:
|
||||||
using ExplicitVarSlotMap = UnorderedMap<String, Uint>;
|
using ExplicitVarSlotMap = UnorderedMap<String, Uint>;
|
||||||
TMglGlslIoResolver(const glslang::TIntermediate& intermediate, const ExplicitVarSlotMap& vertexIns,
|
TMglGlslIoResolver(const glslang::TIntermediate& intermediate, const ExplicitVarSlotMap& vertexIns,
|
||||||
const ExplicitVarSlotMap& fragOuts)
|
const ExplicitVarSlotMap& fragOuts, ExplicitVarSlotMap* opaqueUniformBindings)
|
||||||
: TDefaultGlslIoResolver(intermediate), m_explicitVertexIns(vertexIns), m_explicitFragOuts(fragOuts) {}
|
: TDefaultGlslIoResolver(intermediate), m_explicitVertexIns(vertexIns), m_explicitFragOuts(fragOuts),
|
||||||
|
m_explicitOpaqueUniformBindings(opaqueUniformBindings) {}
|
||||||
TMglGlslIoResolver(const glslang::TProgram& program, const EShLanguage stage,
|
TMglGlslIoResolver(const glslang::TProgram& program, const EShLanguage stage,
|
||||||
const ExplicitVarSlotMap& vertexIns, const ExplicitVarSlotMap& fragOuts)
|
const ExplicitVarSlotMap& vertexIns, const ExplicitVarSlotMap& fragOuts,
|
||||||
: TMglGlslIoResolver(*program.getIntermediate(stage), vertexIns, fragOuts) {}
|
ExplicitVarSlotMap* opaqueUniformBindings)
|
||||||
|
: TMglGlslIoResolver(*program.getIntermediate(stage), vertexIns, fragOuts, opaqueUniformBindings) {}
|
||||||
void reserverStorageSlot(glslang::TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
void reserverStorageSlot(glslang::TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
||||||
|
void reserverResourceSlot(glslang::TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
||||||
|
int resolveUniformLocation(EShLanguage stage, glslang::TVarEntryInfo& ent) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool ShouldAssignPlainUniformLocation(const glslang::TType& type) const;
|
||||||
|
void EnsurePlainUniformLocationsAssigned();
|
||||||
|
|
||||||
const ExplicitVarSlotMap& m_explicitVertexIns;
|
const ExplicitVarSlotMap& m_explicitVertexIns;
|
||||||
const ExplicitVarSlotMap& m_explicitFragOuts;
|
const ExplicitVarSlotMap& m_explicitFragOuts;
|
||||||
|
ExplicitVarSlotMap* m_explicitOpaqueUniformBindings = nullptr;
|
||||||
|
std::map<glslang::TString, int> m_plainUniformLocationSizeByName;
|
||||||
|
std::map<glslang::TString, int> m_plainUniformLocationByName;
|
||||||
|
bool m_plainUniformLocationsAssigned = false;
|
||||||
};
|
};
|
||||||
} // namespace MobileGL
|
} // namespace MobileGL
|
||||||
|
|||||||
@@ -445,6 +445,16 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-mellow-in-world
|
|||||||
TOLERANCE 20
|
TOLERANCE 20
|
||||||
FUZZ_PERCENT 20)
|
FUZZ_PERCENT 20)
|
||||||
|
|
||||||
|
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world
|
||||||
|
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world.tgz
|
||||||
|
TRACE_FILE trace.trace
|
||||||
|
GOLDEN ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world.0000125124.png
|
||||||
|
TARGET_CALL 125124
|
||||||
|
WIDTH 854
|
||||||
|
HEIGHT 480
|
||||||
|
TOLERANCE 700
|
||||||
|
FUZZ_PERCENT 20)
|
||||||
|
|
||||||
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-iterationt-in-world
|
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-iterationt-in-world
|
||||||
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-iterationt-in-world.tgz
|
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-iterationt-in-world.tgz
|
||||||
TRACE_FILE trace.trace
|
TRACE_FILE trace.trace
|
||||||
|
|||||||
Reference in New Issue
Block a user