mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 13:18:31 +09:00
[Feat] (MobileGL): full dual-source blending across state, transpiler, and both backends
Wire GL_SRC1_* dual-source blend factors (glBlendFunc) end to end with the
glBindFragDataLocationIndexed color index, so a fragment shader can drive both
dual-source blend inputs.
State + converters:
- RenderState BlendFactor gains Src1Color/OneMinusSrc1Color/Src1Alpha/
OneMinusSrc1Alpha; GLToMG/MGToGL/MGToVk/MGToStr converters map them to
GL_SRC1_*, VK_BLEND_FACTOR_SRC1_*, and readable names.
Transpiler layout(index = N):
- ProgramAttrib carries explicitFragmentOutIndices; ProgramObject threads
m_explicitFragDataIndex into it at both link sites.
- TMglGlslIoResolver applies the color index as TQualifier.layoutIndex on the
fragment output, emitting layout(index = 1) via the glslang Index decoration
-> SPIRV-Cross path. Only the non-zero (dual-source) index is emitted: index 0
is the GL default and an explicit "index = 0" would demand
GL_EXT_blend_func_extended on GLES for ordinary single-source outputs.
Feature detection, POST, and hard-fail at use time (no silent fallback):
- Vulkan: dualSrcBlend is detected at device creation and cached; a draw whose
enabled blend state uses a SRC1 factor without the feature throws at pipeline
build with the reason and a pointer to the POST row.
- GLES: GL_EXT_blend_func_extended detected at load into
GLESCapabilities.SupportsDualSourceBlend; a draw enabling blend with a SRC1
factor without it throws in the blend-state sync with the same guidance.
- DriverPost adds a dual-source-blend row for both backends (Pass/Warn).
Tests:
- ProgramTest.CompileAndLinkWithExplicitFragmentOut now asserts the transpiled
fragment shader carries layout(location = 0, index = 1) after a re-link with
glBindFragDataLocationIndexed(index 1), and still omits any index qualifier
for the plain index-0 output.
This commit is contained in:
@@ -49,6 +49,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
static SharedPtr<MG_State::GLState::SamplerObject> g_rawDepthFetchSamplerState;
|
||||
static SharedPtr<SamplerImpl::BackendSamplerObject> g_rawDepthFetchSamplerBackend;
|
||||
|
||||
static Bool IsDualSourceBlendFactor(BlendFactor v) {
|
||||
switch (v) {
|
||||
case BlendFactor::Src1Color:
|
||||
case BlendFactor::OneMinusSrc1Color:
|
||||
case BlendFactor::Src1Alpha:
|
||||
case BlendFactor::OneMinusSrc1Alpha:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
enum class DrawSyncBit : Uint32 {
|
||||
None = 0,
|
||||
IndexBuffer = 1 << 0,
|
||||
@@ -583,6 +595,27 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
const auto& targetStates = parameters.BlendStates;
|
||||
auto& syncedStates = g_syncedRenderStateParameters.BlendStates;
|
||||
|
||||
// Dual-source blending (GL_SRC1_* factors from glBlendFunc paired with
|
||||
// glBindFragDataLocationIndexed) needs GL_EXT_blend_func_extended; GLES core has none.
|
||||
// Detected at load and surfaced in the POST. There is no fallback, so if a draw actually
|
||||
// enables blending with a SRC1 factor on a driver that lacks it, hard-fail here at use
|
||||
// time rather than let the driver reject glBlendFuncSeparate and silently mis-blend.
|
||||
if (!g_GLESCapabilities.SupportsDualSourceBlend) {
|
||||
for (Uint i = 0; i < FBO::MAX_DRAW_BUFFERS; ++i) {
|
||||
const auto& s = targetStates[i];
|
||||
if (s.Enabled &&
|
||||
(IsDualSourceBlendFactor(s.SrcFactorRGB) || IsDualSourceBlendFactor(s.DstFactorRGB) ||
|
||||
IsDualSourceBlendFactor(s.SrcFactorAlpha) || IsDualSourceBlendFactor(s.DstFactorAlpha))) {
|
||||
THROW_EXCEPTION(
|
||||
"Dual-source blending (GL_SRC1_* blend factor) was used on draw buffer " +
|
||||
std::to_string(i) +
|
||||
", but the GLES driver does not expose GL_EXT_blend_func_extended (see the "
|
||||
"dual-source blend row in the driver POST). No fallback exists; the draw "
|
||||
"cannot proceed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Bool allEnabled = true;
|
||||
Bool allDisabled = true;
|
||||
Bool anyCapDirty = false;
|
||||
|
||||
Reference in New Issue
Block a user