mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
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.
209 lines
8.2 KiB
C++
209 lines
8.2 KiB
C++
// MobileGL - MobileGL/MG_Util/Converters/MGToVk/RenderStateEnumConverter.cpp
|
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
|
// Licensed under the GNU Lesser General Public License v3.0:
|
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
|
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
// End of Source File Header
|
|
|
|
#include "RenderStateEnumConverter.h"
|
|
|
|
namespace MobileGL {
|
|
namespace MG_Util {
|
|
VkPrimitiveTopology ConvertPrimitiveModeToVkEnum(GLenum mode) {
|
|
switch (mode) {
|
|
case GL_POINTS:
|
|
return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
|
|
case GL_LINES:
|
|
return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
|
|
case GL_LINE_STRIP:
|
|
return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
|
|
case GL_TRIANGLES:
|
|
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
|
case GL_TRIANGLE_STRIP:
|
|
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
|
case GL_TRIANGLE_FAN:
|
|
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
|
|
case GL_LINE_LOOP:
|
|
default:
|
|
MGLOG_W("Unrecognized primitive topology");
|
|
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
|
}
|
|
}
|
|
|
|
VkPolygonMode ConvertPolygonModeToVkEnum(GLenum mode) {
|
|
switch (mode) {
|
|
case GL_FILL:
|
|
return VK_POLYGON_MODE_FILL;
|
|
case GL_LINE:
|
|
return VK_POLYGON_MODE_LINE;
|
|
case GL_POINT:
|
|
return VK_POLYGON_MODE_POINT;
|
|
default:
|
|
MGLOG_W("Unrecognized polygon mode");
|
|
return VK_POLYGON_MODE_FILL;
|
|
}
|
|
}
|
|
|
|
VkCullModeFlags ConvertCullFaceModeToVkEnum(CullFaceMode v, Bool invertClockwise) {
|
|
switch (v) {
|
|
case CullFaceMode::Front:
|
|
return invertClockwise ? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_FRONT_BIT;
|
|
case CullFaceMode::Back:
|
|
return invertClockwise ? VK_CULL_MODE_FRONT_BIT : VK_CULL_MODE_BACK_BIT;
|
|
case CullFaceMode::FrontAndBack:
|
|
return VK_CULL_MODE_FRONT_AND_BACK;
|
|
case CullFaceMode::Unknown:
|
|
case CullFaceMode::CullFaceModeCount:
|
|
default:
|
|
MGLOG_W("Unrecognized cull face mode");
|
|
return VK_CULL_MODE_BACK_BIT;
|
|
}
|
|
}
|
|
|
|
VkLogicOp ConvertLogicOperationToVkEnum(LogicOperation v) {
|
|
switch (v) {
|
|
case LogicOperation::Clear:
|
|
return VK_LOGIC_OP_CLEAR;
|
|
case LogicOperation::And:
|
|
return VK_LOGIC_OP_AND;
|
|
case LogicOperation::AndReverse:
|
|
return VK_LOGIC_OP_AND_REVERSE;
|
|
case LogicOperation::Copy:
|
|
return VK_LOGIC_OP_COPY;
|
|
case LogicOperation::AndInverted:
|
|
return VK_LOGIC_OP_AND_INVERTED;
|
|
case LogicOperation::Noop:
|
|
return VK_LOGIC_OP_NO_OP;
|
|
case LogicOperation::Xor:
|
|
return VK_LOGIC_OP_XOR;
|
|
case LogicOperation::Or:
|
|
return VK_LOGIC_OP_OR;
|
|
case LogicOperation::Nor:
|
|
return VK_LOGIC_OP_NOR;
|
|
case LogicOperation::Equiv:
|
|
return VK_LOGIC_OP_EQUIVALENT;
|
|
case LogicOperation::Invert:
|
|
return VK_LOGIC_OP_INVERT;
|
|
case LogicOperation::OrReverse:
|
|
return VK_LOGIC_OP_OR_REVERSE;
|
|
case LogicOperation::CopyInverted:
|
|
return VK_LOGIC_OP_COPY_INVERTED;
|
|
case LogicOperation::OrInverted:
|
|
return VK_LOGIC_OP_OR_INVERTED;
|
|
case LogicOperation::Nand:
|
|
return VK_LOGIC_OP_NAND;
|
|
case LogicOperation::Set:
|
|
return VK_LOGIC_OP_SET;
|
|
default:
|
|
return VK_LOGIC_OP_COPY;
|
|
}
|
|
}
|
|
|
|
VkCompareOp ConvertDepthTestFuncToVkEnum(DepthTestFunc v) {
|
|
switch (v) {
|
|
case DepthTestFunc::Never:
|
|
return VK_COMPARE_OP_NEVER;
|
|
case DepthTestFunc::Less:
|
|
return VK_COMPARE_OP_LESS;
|
|
case DepthTestFunc::Equal:
|
|
return VK_COMPARE_OP_EQUAL;
|
|
case DepthTestFunc::LessEqual:
|
|
return VK_COMPARE_OP_LESS_OR_EQUAL;
|
|
case DepthTestFunc::Greater:
|
|
return VK_COMPARE_OP_GREATER;
|
|
case DepthTestFunc::NotEqual:
|
|
return VK_COMPARE_OP_NOT_EQUAL;
|
|
case DepthTestFunc::GreaterEqual:
|
|
return VK_COMPARE_OP_GREATER_OR_EQUAL;
|
|
case DepthTestFunc::Always:
|
|
default:
|
|
return VK_COMPARE_OP_ALWAYS;
|
|
}
|
|
}
|
|
|
|
VkStencilOp ConvertStencilOperationToVkEnum(StencilOperation v) {
|
|
switch (v) {
|
|
case StencilOperation::Keep:
|
|
return VK_STENCIL_OP_KEEP;
|
|
case StencilOperation::Zero:
|
|
return VK_STENCIL_OP_ZERO;
|
|
case StencilOperation::Replace:
|
|
return VK_STENCIL_OP_REPLACE;
|
|
case StencilOperation::IncrementClamp:
|
|
return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
|
|
case StencilOperation::DecrementClamp:
|
|
return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
|
|
case StencilOperation::Invert:
|
|
return VK_STENCIL_OP_INVERT;
|
|
case StencilOperation::IncrementWrap:
|
|
return VK_STENCIL_OP_INCREMENT_AND_WRAP;
|
|
case StencilOperation::DecrementWrap:
|
|
return VK_STENCIL_OP_DECREMENT_AND_WRAP;
|
|
default:
|
|
return VK_STENCIL_OP_KEEP;
|
|
}
|
|
}
|
|
|
|
VkBlendFactor ConvertBlendFactorToVkEnum(BlendFactor v) {
|
|
switch (v) {
|
|
case BlendFactor::Zero:
|
|
return VK_BLEND_FACTOR_ZERO;
|
|
case BlendFactor::One:
|
|
return VK_BLEND_FACTOR_ONE;
|
|
case BlendFactor::SrcColor:
|
|
return VK_BLEND_FACTOR_SRC_COLOR;
|
|
case BlendFactor::OneMinusSrcColor:
|
|
return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
|
|
case BlendFactor::DstColor:
|
|
return VK_BLEND_FACTOR_DST_COLOR;
|
|
case BlendFactor::OneMinusDstColor:
|
|
return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
|
|
case BlendFactor::SrcAlpha:
|
|
return VK_BLEND_FACTOR_SRC_ALPHA;
|
|
case BlendFactor::OneMinusSrcAlpha:
|
|
return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
|
case BlendFactor::DstAlpha:
|
|
return VK_BLEND_FACTOR_DST_ALPHA;
|
|
case BlendFactor::OneMinusDstAlpha:
|
|
return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
|
|
case BlendFactor::ConstantColor:
|
|
return VK_BLEND_FACTOR_CONSTANT_COLOR;
|
|
case BlendFactor::OneMinusConstantColor:
|
|
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
|
|
case BlendFactor::ConstantAlpha:
|
|
return VK_BLEND_FACTOR_CONSTANT_ALPHA;
|
|
case BlendFactor::OneMinusConstantAlpha:
|
|
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
|
|
case BlendFactor::Src1Color:
|
|
return VK_BLEND_FACTOR_SRC1_COLOR;
|
|
case BlendFactor::OneMinusSrc1Color:
|
|
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
|
|
case BlendFactor::Src1Alpha:
|
|
return VK_BLEND_FACTOR_SRC1_ALPHA;
|
|
case BlendFactor::OneMinusSrc1Alpha:
|
|
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
|
|
default:
|
|
return VK_BLEND_FACTOR_ONE;
|
|
}
|
|
}
|
|
|
|
VkBlendOp ConvertBlendEquationToVkEnum(BlendEquation v) {
|
|
switch (v) {
|
|
case BlendEquation::Add:
|
|
return VK_BLEND_OP_ADD;
|
|
case BlendEquation::Subtract:
|
|
return VK_BLEND_OP_SUBTRACT;
|
|
case BlendEquation::ReverseSubtract:
|
|
return VK_BLEND_OP_REVERSE_SUBTRACT;
|
|
case BlendEquation::Min:
|
|
return VK_BLEND_OP_MIN;
|
|
case BlendEquation::Max:
|
|
return VK_BLEND_OP_MAX;
|
|
default:
|
|
return VK_BLEND_OP_ADD;
|
|
}
|
|
}
|
|
} // namespace MG_Util
|
|
} // namespace MobileGL
|