Files
MobileGL/MobileGL/MG_Util/Converters/MGToVk/RenderStateEnumConverter.cpp
T
swung0x48 aa5c33a42d [Feat] (MG_Backend/DirectVulkan): wire glPolygonMode and glColorMaski into pipeline creation
Consume the polygon mode and per-draw-buffer color write masks that the
frontend already tracks, with runtime fallback for the device features
they require.

glPolygonMode:
- Add ConvertPolygonModeToVkEnum (GL_FILL/LINE/POINT -> VkPolygonMode).
- Thread a polygonMode field through PipelineCreatePayload, fold it into
  the pipeline cache hash (distinct modes need distinct pipelines), and
  apply it in PipelineFactory instead of the hardcoded VK_POLYGON_MODE_FILL.
- LINE/POINT require the fillModeNonSolid device feature: detect and
  enable it at device creation, cache m_fillModeNonSolidFeatureEnabled,
  and fall back to FILL at pipeline-build time when it is absent.

glColorMaski:
- The per-attachment color-blend loop now reads GetColorMaskIndexed(i)
  instead of the broadcast GetColorMask(), so each draw buffer gets its
  own write mask (already covered by the pipeline hash).
- Divergent per-attachment masks require independentBlend: cache
  m_independentBlendFeatureEnabled (was enabled but never recorded) and
  fall back to draw buffer 0's mask for every attachment when it is absent.

The internal depth-mipmap utility pipeline keeps VK_POLYGON_MODE_FILL (not
GL-driven). Library builds clean; full SanityTest sweep green (30/30).
2026-07-10 22:16:47 -04:00

201 lines
7.8 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;
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