mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 14:18:31 +09:00
[Feat] (MG_State/RenderState, MG_Backend/DirectVulkan): make Distant
Horizon work - Implement BlendEquation/CullFaceMode/PointSize/PolygonMode - Implement GetFramebufferAttachmentParameter* - Downgrade some color attachment resolve failure - Downgrade some overly-strict shader stage linkage check (don't check on unused input var)
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <spirv-tools/libspirv.h>
|
#include <spirv-tools/libspirv.h>
|
||||||
#include <spirv-tools/optimizer.hpp>
|
#include <spirv-tools/optimizer.hpp>
|
||||||
|
#include <source/opt/build_module.h>
|
||||||
#include <source/opt/constants.h>
|
#include <source/opt/constants.h>
|
||||||
#include <source/opt/instruction.h>
|
#include <source/opt/instruction.h>
|
||||||
#include <source/opt/ir_builder.h>
|
#include <source/opt/ir_builder.h>
|
||||||
@@ -290,12 +291,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return occupiedSlotCount;
|
return occupiedSlotCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValidateTransformedSpirv(const Vector<Uint>& spirv, ShaderStage shaderStage, Uint programExternalIndex) {
|
spv_target_env GetSpirvTargetEnv(const Vector<Uint>& spirv) {
|
||||||
if (spirv.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
spv_const_binary_t binary = {spirv.data(), spirv.size()};
|
|
||||||
spv_target_env targetEnv = SPV_ENV_VULKAN_1_0;
|
spv_target_env targetEnv = SPV_ENV_VULKAN_1_0;
|
||||||
if (spirv.size() > 1) {
|
if (spirv.size() > 1) {
|
||||||
const Uint32 versionWord = spirv[1];
|
const Uint32 versionWord = spirv[1];
|
||||||
@@ -311,6 +307,53 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
targetEnv = SPV_ENV_VULKAN_1_1;
|
targetEnv = SPV_ENV_VULKAN_1_1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return targetEnv;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool IsInterfaceVariableStaticallyUsed(const Vector<Uint>& spirv, Uint32 spirvId) {
|
||||||
|
if (spirv.empty() || spirvId == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto context = spvtools::BuildModule(
|
||||||
|
GetSpirvTargetEnv(spirv),
|
||||||
|
[](spv_message_level_t, const char*, const spv_position_t&, const char*) {},
|
||||||
|
spirv.data(),
|
||||||
|
spirv.size());
|
||||||
|
if (!context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* variable = context->get_def_use_mgr()->GetDef(spirvId);
|
||||||
|
if (variable == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool used = false;
|
||||||
|
context->get_def_use_mgr()->ForEachUser(variable, [&used](spvtools::opt::Instruction* user) {
|
||||||
|
switch (user->opcode()) {
|
||||||
|
case spv::Op::OpName:
|
||||||
|
case spv::Op::OpMemberName:
|
||||||
|
case spv::Op::OpDecorate:
|
||||||
|
case spv::Op::OpMemberDecorate:
|
||||||
|
case spv::Op::OpDecorateId:
|
||||||
|
case spv::Op::OpEntryPoint:
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
used = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidateTransformedSpirv(const Vector<Uint>& spirv, ShaderStage shaderStage, Uint programExternalIndex) {
|
||||||
|
if (spirv.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spv_const_binary_t binary = {spirv.data(), spirv.size()};
|
||||||
|
const spv_target_env targetEnv = GetSpirvTargetEnv(spirv);
|
||||||
|
|
||||||
spv_context context = spvContextCreate(targetEnv);
|
spv_context context = spvContextCreate(targetEnv);
|
||||||
MOBILEGL_ASSERT(context != nullptr,
|
MOBILEGL_ASSERT(context != nullptr,
|
||||||
@@ -589,6 +632,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
if (variable == nullptr) {
|
if (variable == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (reflectInputs && !IsInterfaceVariableStaticallyUsed(module, variable->spirv_id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
ReflectStageInterfaceVariable(*variable, reflectInputs, outSummary, programExternalIndex,
|
ReflectStageInterfaceVariable(*variable, reflectInputs, outSummary, programExternalIndex,
|
||||||
stageLabel, stageCursor);
|
stageLabel, stageCursor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,49 @@
|
|||||||
|
|
||||||
#include "MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h"
|
#include "MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h"
|
||||||
#include "MG_State/GLState/TextureState/TextureObject2D.h"
|
#include "MG_State/GLState/TextureState/TextureObject2D.h"
|
||||||
|
#include "MG_Util/Converters/MGToStr/FramebufferEnumConverter.h"
|
||||||
#include "MG_Util/Converters/MGToVk/TextureEnumConverter.h"
|
#include "MG_Util/Converters/MGToVk/TextureEnumConverter.h"
|
||||||
|
|
||||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||||
|
static MG_State::GLState::ITextureObject* ResolveCompleteColorAttachmentTexture(
|
||||||
|
const MG_State::GLState::FramebufferObject& fbo,
|
||||||
|
FramebufferAttachmentType attachmentType,
|
||||||
|
Uint32 drawBufferIndex) {
|
||||||
|
if (attachmentType == FramebufferAttachmentType::None) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& attachment = fbo.GetAttachment(attachmentType);
|
||||||
|
if (!attachment.IsTexture()) {
|
||||||
|
if (attachment.IsEmpty()) {
|
||||||
|
MGLOG_D("GetOrCreateRenderPass: draw buffer slot %u (%s) on FBO %u has no bound color attachment; using VK_ATTACHMENT_UNUSED",
|
||||||
|
drawBufferIndex,
|
||||||
|
MG_Util::ConvertFramebufferAttachmentTypeToString(attachmentType).c_str(),
|
||||||
|
fbo.GetExternalIndex());
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!attachment.IsComplete()) {
|
||||||
|
MGLOG_W("GetOrCreateRenderPass: draw buffer slot %u (%s) on FBO %u has an incomplete texture attachment; using VK_ATTACHMENT_UNUSED",
|
||||||
|
drawBufferIndex,
|
||||||
|
MG_Util::ConvertFramebufferAttachmentTypeToString(attachmentType).c_str(),
|
||||||
|
fbo.GetExternalIndex());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* texture = attachment.GetTexture().get();
|
||||||
|
if (texture == nullptr) {
|
||||||
|
MGLOG_W("GetOrCreateRenderPass: draw buffer slot %u (%s) on FBO %u resolved to a null texture; using VK_ATTACHMENT_UNUSED",
|
||||||
|
drawBufferIndex,
|
||||||
|
MG_Util::ConvertFramebufferAttachmentTypeToString(attachmentType).c_str(),
|
||||||
|
fbo.GetExternalIndex());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
VkRenderPassManager::VkRenderPassManager(VkDevice device,
|
VkRenderPassManager::VkRenderPassManager(VkDevice device,
|
||||||
const VulkanRendererConfig& config, VkClearManager& clearManager, VkTextureManager& textureManager,
|
const VulkanRendererConfig& config, VkClearManager& clearManager, VkTextureManager& textureManager,
|
||||||
SwapchainObject& swapchainObject):
|
SwapchainObject& swapchainObject):
|
||||||
@@ -195,12 +235,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
// assuming default FBO has the right param
|
// assuming default FBO has the right param
|
||||||
for (Uint32 i = 0; i < colorAttachmentSlotCount; ++i) {
|
for (Uint32 i = 0; i < colorAttachmentSlotCount; ++i) {
|
||||||
auto drawbuf = drawbufs[i];
|
auto drawbuf = drawbufs[i];
|
||||||
if (drawbuf == FramebufferAttachmentType::None ||
|
auto* texture = ResolveCompleteColorAttachmentTexture(fbo, drawbuf, i);
|
||||||
fbo.GetAttachment(drawbuf).IsRenderbuffer())
|
if (texture == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto& att = fbo.GetAttachment(drawbuf);
|
auto& att = fbo.GetAttachment(drawbuf);
|
||||||
auto* texture = att.GetTexture().get();
|
|
||||||
const Uint32 attachmentMipLevel = static_cast<Uint32>(std::max(att.GetTextureLevel(), 0));
|
const Uint32 attachmentMipLevel = static_cast<Uint32>(std::max(att.GetTextureLevel(), 0));
|
||||||
const auto textureTarget = texture->GetTarget();
|
const auto textureTarget = texture->GetTarget();
|
||||||
const Uint32 attachmentIndex = static_cast<Uint32>(attachmentDescriptions.size());
|
const Uint32 attachmentIndex = static_cast<Uint32>(attachmentDescriptions.size());
|
||||||
|
|||||||
@@ -27,17 +27,19 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Bool blendEnable,
|
Bool blendEnable,
|
||||||
VkBlendFactor srcColorBlendFactor,
|
VkBlendFactor srcColorBlendFactor,
|
||||||
VkBlendFactor dstColorBlendFactor,
|
VkBlendFactor dstColorBlendFactor,
|
||||||
|
VkBlendOp colorBlendOp,
|
||||||
VkBlendFactor srcAlphaBlendFactor,
|
VkBlendFactor srcAlphaBlendFactor,
|
||||||
VkBlendFactor dstAlphaBlendFactor,
|
VkBlendFactor dstAlphaBlendFactor,
|
||||||
|
VkBlendOp alphaBlendOp,
|
||||||
VkColorComponentFlags colorWriteMask) {
|
VkColorComponentFlags colorWriteMask) {
|
||||||
VkPipelineColorBlendAttachmentState attachment{};
|
VkPipelineColorBlendAttachmentState attachment{};
|
||||||
attachment.blendEnable = blendEnable ? VK_TRUE : VK_FALSE;
|
attachment.blendEnable = blendEnable ? VK_TRUE : VK_FALSE;
|
||||||
attachment.srcColorBlendFactor = srcColorBlendFactor;
|
attachment.srcColorBlendFactor = srcColorBlendFactor;
|
||||||
attachment.dstColorBlendFactor = dstColorBlendFactor;
|
attachment.dstColorBlendFactor = dstColorBlendFactor;
|
||||||
attachment.colorBlendOp = VK_BLEND_OP_ADD;
|
attachment.colorBlendOp = colorBlendOp;
|
||||||
attachment.srcAlphaBlendFactor = srcAlphaBlendFactor;
|
attachment.srcAlphaBlendFactor = srcAlphaBlendFactor;
|
||||||
attachment.dstAlphaBlendFactor = dstAlphaBlendFactor;
|
attachment.dstAlphaBlendFactor = dstAlphaBlendFactor;
|
||||||
attachment.alphaBlendOp = VK_BLEND_OP_ADD;
|
attachment.alphaBlendOp = alphaBlendOp;
|
||||||
attachment.colorWriteMask = colorWriteMask;
|
attachment.colorWriteMask = colorWriteMask;
|
||||||
return attachment;
|
return attachment;
|
||||||
}
|
}
|
||||||
@@ -1720,8 +1722,10 @@ void main() {
|
|||||||
false,
|
false,
|
||||||
VK_BLEND_FACTOR_ONE,
|
VK_BLEND_FACTOR_ONE,
|
||||||
VK_BLEND_FACTOR_ZERO,
|
VK_BLEND_FACTOR_ZERO,
|
||||||
|
VK_BLEND_OP_ADD,
|
||||||
VK_BLEND_FACTOR_ONE,
|
VK_BLEND_FACTOR_ONE,
|
||||||
VK_BLEND_FACTOR_ZERO,
|
VK_BLEND_FACTOR_ZERO,
|
||||||
|
VK_BLEND_OP_ADD,
|
||||||
kColorWriteMask);
|
kColorWriteMask);
|
||||||
}
|
}
|
||||||
return m_pipelineFactory->GetOrCreatePipeline(payload);
|
return m_pipelineFactory->GetOrCreatePipeline(payload);
|
||||||
@@ -2173,14 +2177,15 @@ void main() {
|
|||||||
.vertexInputState = pipelineVertexInputState
|
.vertexInputState = pipelineVertexInputState
|
||||||
};
|
};
|
||||||
const Bool hasDepthStencilAttachment = renderPassEntry.hasDepthStencilAttachment;
|
const Bool hasDepthStencilAttachment = renderPassEntry.hasDepthStencilAttachment;
|
||||||
MOBILEGL_ASSERT(
|
if (!hasDepthStencilAttachment && (payload.depthTestEnable || payload.depthWriteEnable)) {
|
||||||
hasDepthStencilAttachment || (!payload.depthTestEnable && !payload.depthWriteEnable),
|
MGLOG_D("GetOrCreatePipeline: disabling depth test/write for program=%u because render pass has no depth attachment (attachmentCount=%u colorAttachmentCount=%u)",
|
||||||
"GetOrCreatePipeline: render pass has no depth attachment but depthTestEnable=%d depthWriteEnable=%d program=%u attachmentCount=%u colorAttachmentCount=%u",
|
|
||||||
payload.depthTestEnable ? 1 : 0,
|
|
||||||
payload.depthWriteEnable ? 1 : 0,
|
|
||||||
program.GetExternalIndex(),
|
program.GetExternalIndex(),
|
||||||
renderPassEntry.attachmentCount,
|
renderPassEntry.attachmentCount,
|
||||||
renderPassEntry.colorAttachmentCount);
|
renderPassEntry.colorAttachmentCount);
|
||||||
|
payload.depthTestEnable = false;
|
||||||
|
payload.depthWriteEnable = false;
|
||||||
|
payload.depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||||
|
}
|
||||||
const Uint32 fragmentOutputMask = programObj.activeFragmentOutputLocationMask;
|
const Uint32 fragmentOutputMask = programObj.activeFragmentOutputLocationMask;
|
||||||
MOBILEGL_ASSERT(
|
MOBILEGL_ASSERT(
|
||||||
(fragmentOutputMask >> payload.colorAttachmentCount) == 0,
|
(fragmentOutputMask >> payload.colorAttachmentCount) == 0,
|
||||||
@@ -2197,29 +2202,47 @@ void main() {
|
|||||||
const Bool isDefaultDrawFbo =
|
const Bool isDefaultDrawFbo =
|
||||||
drawFboBinding.get() == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO.get();
|
drawFboBinding.get() == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO.get();
|
||||||
const auto& drawBuffers = drawFboBinding->GetDrawBuffers();
|
const auto& drawBuffers = drawFboBinding->GetDrawBuffers();
|
||||||
|
auto resolveCompleteColorAttachmentTexture = [&](Uint32 drawBufferIndex) -> MG_State::GLState::ITextureObject* {
|
||||||
|
if (isDefaultDrawFbo || drawBufferIndex >= drawBuffers.size()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto drawBuffer = drawBuffers[drawBufferIndex];
|
||||||
|
if (drawBuffer == FramebufferAttachmentType::None) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& attachment = drawFboBinding->GetAttachment(drawBuffer);
|
||||||
|
if (!attachment.IsTexture() || !attachment.IsComplete()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return attachment.GetTexture().get();
|
||||||
|
};
|
||||||
for (Uint32 i = 0; i < payload.colorAttachmentCount; ++i) {
|
for (Uint32 i = 0; i < payload.colorAttachmentCount; ++i) {
|
||||||
BlendFactor srcRGB = BlendFactor::One;
|
BlendFactor srcRGB = BlendFactor::One;
|
||||||
BlendFactor dstRGB = BlendFactor::Zero;
|
BlendFactor dstRGB = BlendFactor::Zero;
|
||||||
BlendFactor srcAlpha = BlendFactor::One;
|
BlendFactor srcAlpha = BlendFactor::One;
|
||||||
BlendFactor dstAlpha = BlendFactor::Zero;
|
BlendFactor dstAlpha = BlendFactor::Zero;
|
||||||
|
BlendEquation colorEquation = BlendEquation::Add;
|
||||||
|
BlendEquation alphaEquation = BlendEquation::Add;
|
||||||
MG_State::pGLContext->GetBlendFuncIndexed(i, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
MG_State::pGLContext->GetBlendFuncIndexed(i, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||||
|
MG_State::pGLContext->GetBlendEquationIndexed(i, colorEquation, alphaEquation);
|
||||||
const Bool blendEnabled = MG_State::pGLContext->IsCapabilityEnabledIndexed(CapabilityInput::Blend, i);
|
const Bool blendEnabled = MG_State::pGLContext->IsCapabilityEnabledIndexed(CapabilityInput::Blend, i);
|
||||||
VkColorComponentFlags attachmentColorWriteMask = colorWriteMask;
|
VkColorComponentFlags attachmentColorWriteMask = colorWriteMask;
|
||||||
Bool effectiveBlendEnabled = blendEnabled;
|
Bool effectiveBlendEnabled = blendEnabled;
|
||||||
|
MG_State::GLState::ITextureObject* colorAttachmentTexture = nullptr;
|
||||||
if (!isDefaultDrawFbo && i < drawBuffers.size()) {
|
if (!isDefaultDrawFbo && i < drawBuffers.size()) {
|
||||||
const auto drawBuffer = drawBuffers[i];
|
const auto drawBuffer = drawBuffers[i];
|
||||||
if (drawBuffer == FramebufferAttachmentType::None) {
|
colorAttachmentTexture = resolveCompleteColorAttachmentTexture(i);
|
||||||
|
if (drawBuffer == FramebufferAttachmentType::None || colorAttachmentTexture == nullptr) {
|
||||||
// GL ignores writes and per-target blend state for GL_NONE draw buffer slots.
|
// GL ignores writes and per-target blend state for GL_NONE draw buffer slots.
|
||||||
|
// Depth-only or otherwise unattached draw buffers should also discard color writes.
|
||||||
attachmentColorWriteMask = 0;
|
attachmentColorWriteMask = 0;
|
||||||
effectiveBlendEnabled = false;
|
effectiveBlendEnabled = false;
|
||||||
}
|
}
|
||||||
if (drawBuffer != FramebufferAttachmentType::None) {
|
if (colorAttachmentTexture != nullptr) {
|
||||||
const auto& attachment = drawFboBinding->GetAttachment(drawBuffer);
|
auto* texture = colorAttachmentTexture;
|
||||||
if (attachment.IsTexture()) {
|
|
||||||
auto* texture = attachment.GetTexture().get();
|
|
||||||
MOBILEGL_ASSERT(texture != nullptr,
|
|
||||||
"GetOrCreatePipeline: color attachment %u texture is null",
|
|
||||||
i);
|
|
||||||
#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG
|
#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG
|
||||||
const auto* textureResource = m_textureManager->SyncTextureAndGetDescriptor(*texture);
|
const auto* textureResource = m_textureManager->SyncTextureAndGetDescriptor(*texture);
|
||||||
MOBILEGL_ASSERT(textureResource != nullptr,
|
MOBILEGL_ASSERT(textureResource != nullptr,
|
||||||
@@ -2285,7 +2308,6 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (effectiveBlendEnabled) {
|
if (effectiveBlendEnabled) {
|
||||||
MOBILEGL_ASSERT(i < drawBuffers.size(),
|
MOBILEGL_ASSERT(i < drawBuffers.size(),
|
||||||
"GetOrCreatePipeline: color attachment %u is out of draw buffer range %zu",
|
"GetOrCreatePipeline: color attachment %u is out of draw buffer range %zu",
|
||||||
@@ -2296,16 +2318,9 @@ void main() {
|
|||||||
if (isDefaultDrawFbo) {
|
if (isDefaultDrawFbo) {
|
||||||
colorAttachmentFormat = m_swapchainObject.GetSurfaceFormat().format;
|
colorAttachmentFormat = m_swapchainObject.GetSurfaceFormat().format;
|
||||||
} else {
|
} else {
|
||||||
const auto drawBuffer = drawBuffers[i];
|
auto* texture = colorAttachmentTexture;
|
||||||
MOBILEGL_ASSERT(drawBuffer != FramebufferAttachmentType::None,
|
|
||||||
"GetOrCreatePipeline: blend is enabled on draw buffer %u but the attachment is None",
|
|
||||||
i);
|
|
||||||
const auto& attachment = drawFboBinding->GetAttachment(drawBuffer);
|
|
||||||
MOBILEGL_ASSERT(attachment.IsTexture(),
|
|
||||||
"GetOrCreatePipeline: blend validation currently expects texture color attachments only");
|
|
||||||
auto* texture = attachment.GetTexture().get();
|
|
||||||
MOBILEGL_ASSERT(texture != nullptr,
|
MOBILEGL_ASSERT(texture != nullptr,
|
||||||
"GetOrCreatePipeline: color attachment %u texture is null",
|
"GetOrCreatePipeline: blend is enabled on draw buffer %u but no complete texture attachment is bound",
|
||||||
i);
|
i);
|
||||||
textureExternalIndex = texture->GetExternalIndex();
|
textureExternalIndex = texture->GetExternalIndex();
|
||||||
colorAttachmentFormat = MG_Util::ConvertTextureInternalFormatToVkEnum(texture->GetFormat());
|
colorAttachmentFormat = MG_Util::ConvertTextureInternalFormatToVkEnum(texture->GetFormat());
|
||||||
@@ -2327,8 +2342,10 @@ void main() {
|
|||||||
effectiveBlendEnabled,
|
effectiveBlendEnabled,
|
||||||
MG_Util::ConvertBlendFactorToVkEnum(srcRGB),
|
MG_Util::ConvertBlendFactorToVkEnum(srcRGB),
|
||||||
MG_Util::ConvertBlendFactorToVkEnum(dstRGB),
|
MG_Util::ConvertBlendFactorToVkEnum(dstRGB),
|
||||||
|
MG_Util::ConvertBlendEquationToVkEnum(colorEquation),
|
||||||
MG_Util::ConvertBlendFactorToVkEnum(srcAlpha),
|
MG_Util::ConvertBlendFactorToVkEnum(srcAlpha),
|
||||||
MG_Util::ConvertBlendFactorToVkEnum(dstAlpha),
|
MG_Util::ConvertBlendFactorToVkEnum(dstAlpha),
|
||||||
|
MG_Util::ConvertBlendEquationToVkEnum(alphaEquation),
|
||||||
attachmentColorWriteMask);
|
attachmentColorWriteMask);
|
||||||
}
|
}
|
||||||
return m_pipelineFactory->GetOrCreatePipeline(payload);
|
return m_pipelineFactory->GetOrCreatePipeline(payload);
|
||||||
@@ -2431,6 +2448,14 @@ void main() {
|
|||||||
activeRenderPass = nullptr;
|
activeRenderPass = nullptr;
|
||||||
renderPassEntry = &m_renderPassManager->GetOrCreateRenderPass(*drawFbo, m_imageIndexAcquired);
|
renderPassEntry = &m_renderPassManager->GetOrCreateRenderPass(*drawFbo, m_imageIndexAcquired);
|
||||||
}
|
}
|
||||||
|
if (renderPassEntry->attachmentCount == 0 || renderPassEntry->extent.x() <= 0 || renderPassEntry->extent.y() <= 0) {
|
||||||
|
MGLOG_D("SetupDraw skipped: drawFbo=%u resolved to an empty render pass (attachmentCount=%u extent=%dx%d)",
|
||||||
|
drawFbo->GetExternalIndex(),
|
||||||
|
renderPassEntry->attachmentCount,
|
||||||
|
renderPassEntry->extent.x(),
|
||||||
|
renderPassEntry->extent.y());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto pipeline = GetOrCreatePipeline(mode, program, programObj, transformFlags, vao, *renderPassEntry);
|
auto pipeline = GetOrCreatePipeline(mode, program, programObj, transformFlags, vao, *renderPassEntry);
|
||||||
activeRenderPass = VkRenderPassManager::GetActiveRenderPass();
|
activeRenderPass = VkRenderPassManager::GetActiveRenderPass();
|
||||||
|
|||||||
@@ -502,7 +502,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLboolean IsBuffer_State(GLuint buffer) {
|
GLboolean IsBuffer_State(GLuint buffer) {
|
||||||
if (!BufferImpl::ValidateBufferName(buffer)) return GL_FALSE;
|
if (buffer == 0) return GL_FALSE;
|
||||||
return MG_State::pGLContext->ValidateBufferObject(buffer) ? GL_TRUE : GL_FALSE;
|
return MG_State::pGLContext->ValidateBufferObject(buffer) ? GL_TRUE : GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ DECLARE_GL_FUNCTION_HEAD(void, BindRenderbuffer, GLenum target, GLuint renderbuf
|
|||||||
DECLARE_GL_FUNCTION_HEAD(void, BindTexture, GLenum target, GLuint texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindTexture, target, texture)
|
DECLARE_GL_FUNCTION_HEAD(void, BindTexture, GLenum target, GLuint texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindTexture, target, texture)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, BlendColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlendColor, red, green, blue, alpha)
|
DECLARE_GL_FUNCTION_HEAD(void, BlendColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlendColor, red, green, blue, alpha)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, BlendEquation, GLenum mode) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlendEquation, mode)
|
DECLARE_GL_FUNCTION_HEAD(void, BlendEquation, GLenum mode) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlendEquation, mode)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationSeparate, modeRGB, modeAlpha)
|
DECLARE_GL_FUNCTION_HEAD(void, BlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlendEquationSeparate, modeRGB, modeAlpha)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, BlendFunc, GLenum sfactor, GLenum dfactor) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlendFunc, sfactor, dfactor)
|
DECLARE_GL_FUNCTION_HEAD(void, BlendFunc, GLenum sfactor, GLenum dfactor) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlendFunc, sfactor, dfactor)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, BlendFuncSeparate, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlendFuncSeparate, sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha)
|
DECLARE_GL_FUNCTION_HEAD(void, BlendFuncSeparate, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlendFuncSeparate, sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, BufferData, GLenum target, GLsizeiptr size, const void* data, GLenum usage) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BufferData, target, size, data, usage)
|
DECLARE_GL_FUNCTION_HEAD(void, BufferData, GLenum target, GLsizeiptr size, const void* data, GLenum usage) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BufferData, target, size, data, usage)
|
||||||
|
|||||||
@@ -67,7 +67,86 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GetFramebufferAttachmentParameteriv_State(GLenum target, GLenum attachment, GLenum pname, GLint* params) {
|
void GetFramebufferAttachmentParameteriv_State(GLenum target, GLenum attachment, GLenum pname, GLint* params) {
|
||||||
// TODO: implement
|
if (params == nullptr) return;
|
||||||
|
if (target == GL_FRAMEBUFFER) {
|
||||||
|
target = GL_DRAW_FRAMEBUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
FramebufferTarget framebufferTarget = MG_Util::ConvertGLEnumToFramebufferTarget(target);
|
||||||
|
if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return;
|
||||||
|
|
||||||
|
const Bool depthStencilAlias = attachment == GL_DEPTH_STENCIL_ATTACHMENT;
|
||||||
|
FramebufferAttachmentType attachmentType = depthStencilAlias
|
||||||
|
? FramebufferAttachmentType::Depth
|
||||||
|
: MG_Util::ConvertGLEnumToFramebufferAttachmentType(attachment);
|
||||||
|
if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return;
|
||||||
|
|
||||||
|
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget);
|
||||||
|
auto& framebufferObject = bindingSlot.GetBoundObject();
|
||||||
|
if (!framebufferObject) {
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidOperation,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetFramebufferAttachmentParameteriv_State",
|
||||||
|
"Framebuffer target is bound to no framebuffer object."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* attachmentObject = [&]() -> const MG_State::GLState::FramebufferAttachmentObject* {
|
||||||
|
if (!depthStencilAlias) {
|
||||||
|
return &framebufferObject->GetAttachment(attachmentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& depthAttachment = framebufferObject->GetAttachment(FramebufferAttachmentType::Depth);
|
||||||
|
if (depthAttachment.IsValid() && !depthAttachment.IsEmpty()) return &depthAttachment;
|
||||||
|
|
||||||
|
const auto& stencilAttachment = framebufferObject->GetAttachment(FramebufferAttachmentType::Stencil);
|
||||||
|
if (stencilAttachment.IsValid() && !stencilAttachment.IsEmpty()) return &stencilAttachment;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}();
|
||||||
|
|
||||||
|
switch (pname) {
|
||||||
|
case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
|
||||||
|
if (attachmentObject == nullptr || attachmentObject->IsEmpty() || !attachmentObject->IsValid()) {
|
||||||
|
*params = GL_NONE;
|
||||||
|
} else if (attachmentObject->IsTexture()) {
|
||||||
|
*params = GL_TEXTURE;
|
||||||
|
} else if (attachmentObject->IsRenderbuffer()) {
|
||||||
|
*params = GL_RENDERBUFFER;
|
||||||
|
} else {
|
||||||
|
*params = GL_NONE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
|
||||||
|
if (attachmentObject == nullptr || attachmentObject->IsEmpty() || !attachmentObject->IsValid()) {
|
||||||
|
*params = 0;
|
||||||
|
} else if (attachmentObject->IsTexture()) {
|
||||||
|
const auto& textureObject = attachmentObject->GetTexture();
|
||||||
|
*params = textureObject ? static_cast<GLint>(textureObject->GetExternalIndex()) : 0;
|
||||||
|
} else if (attachmentObject->IsRenderbuffer()) {
|
||||||
|
const auto& renderbufferObject = attachmentObject->GetRenderbuffer();
|
||||||
|
*params = renderbufferObject ? static_cast<GLint>(renderbufferObject->GetExternalIndex()) : 0;
|
||||||
|
} else {
|
||||||
|
*params = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
|
||||||
|
*params = (attachmentObject != nullptr && attachmentObject->IsTexture() && attachmentObject->IsValid())
|
||||||
|
? static_cast<GLint>(attachmentObject->GetTextureLevel())
|
||||||
|
: 0;
|
||||||
|
break;
|
||||||
|
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
|
||||||
|
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
|
||||||
|
*params = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidEnum,
|
||||||
|
MakeUnique<GenericErrorInfo>(
|
||||||
|
"MG_Impl/GLImpl", "GetFramebufferAttachmentParameteriv_State",
|
||||||
|
std::format("pname {} is not an accepted value.", MG_Util::ConvertGLEnumToString(pname))));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenRenderbuffers_State(GLsizei n, GLuint* renderbuffers) {
|
void GenRenderbuffers_State(GLsizei n, GLuint* renderbuffers) {
|
||||||
@@ -111,6 +190,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
|
if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||||
FramebufferTexture2D_State(target, GL_DEPTH_ATTACHMENT, textarget, texture, level);
|
FramebufferTexture2D_State(target, GL_DEPTH_ATTACHMENT, textarget, texture, level);
|
||||||
FramebufferTexture2D_State(target, GL_STENCIL_ATTACHMENT, textarget, texture, level);
|
FramebufferTexture2D_State(target, GL_STENCIL_ATTACHMENT, textarget, texture, level);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferAttachmentType attachmentType = MG_Util::ConvertGLEnumToFramebufferAttachmentType(attachment);
|
FramebufferAttachmentType attachmentType = MG_Util::ConvertGLEnumToFramebufferAttachmentType(attachment);
|
||||||
|
|||||||
@@ -160,31 +160,39 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
case GL_BLEND_DST_ALPHA: {
|
case GL_BLEND_DST_ALPHA: {
|
||||||
BlendFactor srcRGB, dstRGB, srcAlpha, dstAlpha;
|
BlendFactor srcRGB, dstRGB, srcAlpha, dstAlpha;
|
||||||
MG_State::pGLContext->GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
MG_State::pGLContext->GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||||
*params = static_cast<GLint>(dstAlpha);
|
*params = static_cast<GLint>(MG_Util::ConvertBlendFactorToGLEnum(dstAlpha));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GL_BLEND_DST_RGB: {
|
case GL_BLEND_DST_RGB: {
|
||||||
BlendFactor srcRGB, dstRGB, srcAlpha, dstAlpha;
|
BlendFactor srcRGB, dstRGB, srcAlpha, dstAlpha;
|
||||||
MG_State::pGLContext->GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
MG_State::pGLContext->GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||||
*params = static_cast<GLint>(dstRGB);
|
*params = static_cast<GLint>(MG_Util::ConvertBlendFactorToGLEnum(dstRGB));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GL_BLEND_EQUATION_RGB:
|
case GL_BLEND_EQUATION_RGB: {
|
||||||
*params = 0; // TODO
|
BlendEquation colorEquation = BlendEquation::Add;
|
||||||
|
BlendEquation alphaEquation = BlendEquation::Add;
|
||||||
|
MG_State::pGLContext->GetBlendEquation(colorEquation, alphaEquation);
|
||||||
|
*params = static_cast<GLint>(MG_Util::ConvertBlendEquationToGLEnum(colorEquation));
|
||||||
break;
|
break;
|
||||||
case GL_BLEND_EQUATION_ALPHA:
|
}
|
||||||
*params = 0; // TODO
|
case GL_BLEND_EQUATION_ALPHA: {
|
||||||
|
BlendEquation colorEquation = BlendEquation::Add;
|
||||||
|
BlendEquation alphaEquation = BlendEquation::Add;
|
||||||
|
MG_State::pGLContext->GetBlendEquation(colorEquation, alphaEquation);
|
||||||
|
*params = static_cast<GLint>(MG_Util::ConvertBlendEquationToGLEnum(alphaEquation));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case GL_BLEND_SRC_ALPHA: {
|
case GL_BLEND_SRC_ALPHA: {
|
||||||
BlendFactor srcRGB, dstRGB, srcAlpha, dstAlpha;
|
BlendFactor srcRGB, dstRGB, srcAlpha, dstAlpha;
|
||||||
MG_State::pGLContext->GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
MG_State::pGLContext->GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||||
*params = static_cast<GLint>(srcAlpha);
|
*params = static_cast<GLint>(MG_Util::ConvertBlendFactorToGLEnum(srcAlpha));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GL_BLEND_SRC_RGB: {
|
case GL_BLEND_SRC_RGB: {
|
||||||
BlendFactor srcRGB, dstRGB, srcAlpha, dstAlpha;
|
BlendFactor srcRGB, dstRGB, srcAlpha, dstAlpha;
|
||||||
MG_State::pGLContext->GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
MG_State::pGLContext->GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||||
*params = static_cast<GLint>(srcRGB);
|
*params = static_cast<GLint>(MG_Util::ConvertBlendFactorToGLEnum(srcRGB));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GL_COLOR_CLEAR_VALUE:
|
case GL_COLOR_CLEAR_VALUE:
|
||||||
@@ -252,6 +260,9 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
case GL_CULL_FACE:
|
case GL_CULL_FACE:
|
||||||
*params = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::CullFace) ? GL_TRUE : GL_FALSE;
|
*params = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::CullFace) ? GL_TRUE : GL_FALSE;
|
||||||
break;
|
break;
|
||||||
|
case GL_CULL_FACE_MODE:
|
||||||
|
*params = static_cast<GLint>(MG_Util::ConvertCullFaceModeToGLEnum(MG_State::pGLContext->GetCullFaceMode()));
|
||||||
|
break;
|
||||||
case GL_CURRENT_PROGRAM: {
|
case GL_CURRENT_PROGRAM: {
|
||||||
const auto& currentProgram = MG_State::pGLContext->GetCurrentProgram();
|
const auto& currentProgram = MG_State::pGLContext->GetCurrentProgram();
|
||||||
*params = currentProgram ? (GLint)currentProgram->GetExternalIndex() : 0;
|
*params = currentProgram ? (GLint)currentProgram->GetExternalIndex() : 0;
|
||||||
@@ -592,6 +603,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
case GL_POINT_SIZE:
|
case GL_POINT_SIZE:
|
||||||
*params = 0; // TODO
|
*params = 0; // TODO
|
||||||
break;
|
break;
|
||||||
|
case GL_POLYGON_MODE:
|
||||||
|
params[0] = GL_FILL;
|
||||||
|
params[1] = GL_FILL;
|
||||||
|
break;
|
||||||
case GL_POINT_SIZE_GRANULARITY:
|
case GL_POINT_SIZE_GRANULARITY:
|
||||||
*params = 0; // TODO
|
*params = 0; // TODO
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -462,7 +462,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
* A program object marked for deletion with glDeleteProgram but still in use as part of current
|
* A program object marked for deletion with glDeleteProgram but still in use as part of current
|
||||||
* rendering state is still considered a program object and glIsProgram will return GL_TRUE.
|
* rendering state is still considered a program object and glIsProgram will return GL_TRUE.
|
||||||
*/
|
*/
|
||||||
return CheckProgramNameValidity(program);
|
if (program == 0) return GL_FALSE;
|
||||||
|
return MG_State::pGLContext->ValidateProgramName(program) ? GL_TRUE : GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLboolean IsShader_State(GLuint shader) {
|
GLboolean IsShader_State(GLuint shader) {
|
||||||
@@ -470,7 +471,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
* A shader object marked for deletion with glDeleteShader but still attached to a program object is still
|
* A shader object marked for deletion with glDeleteShader but still attached to a program object is still
|
||||||
* considered a shader object and glIsShader will return GL_TRUE.
|
* considered a shader object and glIsShader will return GL_TRUE.
|
||||||
*/
|
*/
|
||||||
return CheckShaderNameValidity(shader);
|
if (shader == 0) return GL_FALSE;
|
||||||
|
return MG_State::pGLContext->ValidateShaderName(shader) ? GL_TRUE : GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkProgram_State(GLuint program) {
|
void LinkProgram_State(GLuint program) {
|
||||||
|
|||||||
@@ -14,6 +14,19 @@
|
|||||||
#include <MG_Util/Converters/MGToStr/RenderStateEnumConverter.h>
|
#include <MG_Util/Converters/MGToStr/RenderStateEnumConverter.h>
|
||||||
|
|
||||||
namespace MobileGL::MG_Impl::GLImpl {
|
namespace MobileGL::MG_Impl::GLImpl {
|
||||||
|
static Bool TryConvertBlendEquation(GLenum mode, const char* functionName,
|
||||||
|
::MobileGL::BlendEquation& outEquation) {
|
||||||
|
outEquation = MG_Util::ConvertGLEnumToBlendEquation(mode);
|
||||||
|
if (outEquation != ::MobileGL::BlendEquation::Unknown) return true;
|
||||||
|
|
||||||
|
MG_State::pGLContext->RecordError(
|
||||||
|
ErrorCode::InvalidEnum,
|
||||||
|
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName,
|
||||||
|
"Blend equation enum " + MG_Util::ConvertGLEnumToString(mode) +
|
||||||
|
" is not supported."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Viewport_State(GLint x, GLint y, GLsizei width, GLsizei height) {
|
void Viewport_State(GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||||
if (width < 0 || height < 0) {
|
if (width < 0 || height < 0) {
|
||||||
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
|
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
|
||||||
@@ -249,7 +262,19 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BlendEquation_State(GLenum mode) {
|
void BlendEquation_State(GLenum mode) {
|
||||||
// TODO: implement
|
::MobileGL::BlendEquation blendEquation = ::MobileGL::BlendEquation::Unknown;
|
||||||
|
if (!TryConvertBlendEquation(mode, "BlendEquation_State", blendEquation)) return;
|
||||||
|
MG_State::pGLContext->SetBlendEquation(blendEquation, blendEquation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlendEquationSeparate_State(GLenum modeRGB, GLenum modeAlpha) {
|
||||||
|
::MobileGL::BlendEquation colorEquation = ::MobileGL::BlendEquation::Unknown;
|
||||||
|
if (!TryConvertBlendEquation(modeRGB, "BlendEquationSeparate_State", colorEquation)) return;
|
||||||
|
|
||||||
|
::MobileGL::BlendEquation alphaEquation = ::MobileGL::BlendEquation::Unknown;
|
||||||
|
if (!TryConvertBlendEquation(modeAlpha, "BlendEquationSeparate_State", alphaEquation)) return;
|
||||||
|
|
||||||
|
MG_State::pGLContext->SetBlendEquation(colorEquation, alphaEquation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlendColor_State(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
void BlendColor_State(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
||||||
@@ -455,6 +480,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
BlendEquation_State(mode);
|
BlendEquation_State(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
|
||||||
|
BlendEquationSeparate_State(modeRGB, modeAlpha);
|
||||||
|
}
|
||||||
|
|
||||||
void BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
void BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
||||||
BlendColor_State(red, green, blue, alpha);
|
BlendColor_State(red, green, blue, alpha);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
void ClampColor(GLenum target, GLenum clamp);
|
void ClampColor(GLenum target, GLenum clamp);
|
||||||
void BlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
void BlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||||
void BlendEquation(GLenum mode);
|
void BlendEquation(GLenum mode);
|
||||||
|
void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
|
||||||
void BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
void BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||||
void ClearStencil(GLint s);
|
void ClearStencil(GLint s);
|
||||||
void ClearDepth(GLclampd depth);
|
void ClearDepth(GLclampd depth);
|
||||||
|
|||||||
@@ -1303,6 +1303,13 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some desktop-side helper code saves GL_ACTIVE_TEXTURE and later feeds it back into glBindTexture
|
||||||
|
// as if it were a texture name. Treating that as a no-op preserves the previous "invalid bind does not
|
||||||
|
// change texture state" behavior, but avoids poisoning the error state every frame.
|
||||||
|
if (!MG_State::pGLContext->ValidateTextureName(texture) && texture >= GL_TEXTURE0 && texture <= GL_TEXTURE31) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!TextureImpl::ValidateTextureName(texture, true)) return;
|
if (!TextureImpl::ValidateTextureName(texture, true)) return;
|
||||||
|
|
||||||
// ======================= Processing ================================
|
// ======================= Processing ================================
|
||||||
|
|||||||
@@ -156,21 +156,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLboolean IsVertexArray_State(GLuint array) {
|
GLboolean IsVertexArray_State(GLuint array) {
|
||||||
if (array == 0) {
|
if (array == 0) return GL_FALSE;
|
||||||
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
|
return MG_State::pGLContext->ValidateVertexArrayObject(array) ? GL_TRUE : GL_FALSE;
|
||||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "IsVertexArray_State",
|
|
||||||
"Vertex array name 0 is not supported."));
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
|
||||||
if (!VertexArrayImpl::ValidateVertexArrayName(array)) return GL_FALSE;
|
|
||||||
if (!MG_State::pGLContext->ValidateVertexArrayObject(array)) {
|
|
||||||
MG_State::pGLContext->RecordError(
|
|
||||||
ErrorCode::InvalidOperation,
|
|
||||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "IsVertexArray_State",
|
|
||||||
std::format("Vertex array object {} does not exist.", array)));
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
|
||||||
return GL_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexAttribDivisor_State(GLuint index, GLuint divisor) {
|
void VertexAttribDivisor_State(GLuint index, GLuint divisor) {
|
||||||
|
|||||||
@@ -313,6 +313,22 @@ namespace MobileGL::MG_State {
|
|||||||
m_renderState.GetBlendFuncIndexed(index, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
m_renderState.GetBlendFuncIndexed(index, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLContext::SetBlendEquation(BlendEquation color, BlendEquation alpha) {
|
||||||
|
m_renderState.SetBlendEquation(color, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext::GetBlendEquation(BlendEquation& color, BlendEquation& alpha) const {
|
||||||
|
m_renderState.GetBlendEquation(color, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext::SetBlendEquationIndexed(Uint index, BlendEquation color, BlendEquation alpha) {
|
||||||
|
m_renderState.SetBlendEquationIndexed(index, color, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLContext::GetBlendEquationIndexed(Uint index, BlendEquation& color, BlendEquation& alpha) const {
|
||||||
|
m_renderState.GetBlendEquationIndexed(index, color, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
void GLContext::SetDepthFunc(DepthTestFunc func) {
|
void GLContext::SetDepthFunc(DepthTestFunc func) {
|
||||||
m_renderState.SetDepthFunc(func);
|
m_renderState.SetDepthFunc(func);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,10 @@ namespace MobileGL {
|
|||||||
BlendFactor dstAlpha);
|
BlendFactor dstAlpha);
|
||||||
void GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
void GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
||||||
BlendFactor& dstAlpha) const;
|
BlendFactor& dstAlpha) const;
|
||||||
|
void SetBlendEquation(BlendEquation color, BlendEquation alpha);
|
||||||
|
void GetBlendEquation(BlendEquation& color, BlendEquation& alpha) const;
|
||||||
|
void SetBlendEquationIndexed(Uint index, BlendEquation color, BlendEquation alpha);
|
||||||
|
void GetBlendEquationIndexed(Uint index, BlendEquation& color, BlendEquation& alpha) const;
|
||||||
void SetDepthFunc(DepthTestFunc func);
|
void SetDepthFunc(DepthTestFunc func);
|
||||||
DepthTestFunc GetDepthFunc() const;
|
DepthTestFunc GetDepthFunc() const;
|
||||||
void SetDepthMask(Bool flag);
|
void SetDepthMask(Bool flag);
|
||||||
|
|||||||
@@ -164,6 +164,48 @@ namespace MobileGL {
|
|||||||
dstAlpha = m_parameters.BlendStates[index].DstFactorAlpha;
|
dstAlpha = m_parameters.BlendStates[index].DstFactorAlpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderState::SetBlendEquation(BlendEquation color, BlendEquation alpha) {
|
||||||
|
Bool stateChanged = false;
|
||||||
|
for (auto& blendState : m_parameters.BlendStates) {
|
||||||
|
if (blendState.ColorEquation == color && blendState.AlphaEquation == alpha) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
blendState.ColorEquation = color;
|
||||||
|
blendState.AlphaEquation = alpha;
|
||||||
|
stateChanged = true;
|
||||||
|
}
|
||||||
|
if (!stateChanged) return;
|
||||||
|
++m_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderState::GetBlendEquation(BlendEquation& color, BlendEquation& alpha) const {
|
||||||
|
color = m_parameters.BlendStates[0].ColorEquation;
|
||||||
|
alpha = m_parameters.BlendStates[0].AlphaEquation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderState::SetBlendEquationIndexed(Uint index, BlendEquation color, BlendEquation alpha) {
|
||||||
|
if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||||
|
MOBILEGL_ASSERT(false, "Blend equation index out of range: %d", index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PerBufferBlendState& blendState = m_parameters.BlendStates[index];
|
||||||
|
if (blendState.ColorEquation == color && blendState.AlphaEquation == alpha) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
blendState.ColorEquation = color;
|
||||||
|
blendState.AlphaEquation = alpha;
|
||||||
|
++m_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderState::GetBlendEquationIndexed(Uint index, BlendEquation& color, BlendEquation& alpha) const {
|
||||||
|
if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||||
|
MOBILEGL_ASSERT(false, "Blend equation index out of range: %d", index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
color = m_parameters.BlendStates[index].ColorEquation;
|
||||||
|
alpha = m_parameters.BlendStates[index].AlphaEquation;
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------- Depth --------------------
|
// -------------------- Depth --------------------
|
||||||
void RenderState::SetDepthFunc(DepthTestFunc func) {
|
void RenderState::SetDepthFunc(DepthTestFunc func) {
|
||||||
if (m_parameters.DepthFunc == func) return;
|
if (m_parameters.DepthFunc == func) return;
|
||||||
|
|||||||
@@ -31,6 +31,16 @@ namespace MobileGL {
|
|||||||
Unknown = -1
|
Unknown = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class BlendEquation {
|
||||||
|
Add,
|
||||||
|
Subtract,
|
||||||
|
ReverseSubtract,
|
||||||
|
Min,
|
||||||
|
Max,
|
||||||
|
BlendEquationCount,
|
||||||
|
Unknown = -1
|
||||||
|
};
|
||||||
|
|
||||||
enum class DepthTestFunc {
|
enum class DepthTestFunc {
|
||||||
Never,
|
Never,
|
||||||
Less,
|
Less,
|
||||||
@@ -134,6 +144,8 @@ namespace MobileGL {
|
|||||||
BlendFactor DstFactorRGB = BlendFactor::Zero;
|
BlendFactor DstFactorRGB = BlendFactor::Zero;
|
||||||
BlendFactor SrcFactorAlpha = BlendFactor::One;
|
BlendFactor SrcFactorAlpha = BlendFactor::One;
|
||||||
BlendFactor DstFactorAlpha = BlendFactor::Zero;
|
BlendFactor DstFactorAlpha = BlendFactor::Zero;
|
||||||
|
BlendEquation ColorEquation = BlendEquation::Add;
|
||||||
|
BlendEquation AlphaEquation = BlendEquation::Add;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RenderStateParameters {
|
struct RenderStateParameters {
|
||||||
@@ -192,6 +204,10 @@ namespace MobileGL {
|
|||||||
BlendFactor dstAlpha);
|
BlendFactor dstAlpha);
|
||||||
void GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
void GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
||||||
BlendFactor& dstAlpha) const;
|
BlendFactor& dstAlpha) const;
|
||||||
|
void SetBlendEquation(BlendEquation color, BlendEquation alpha);
|
||||||
|
void GetBlendEquation(BlendEquation& color, BlendEquation& alpha) const;
|
||||||
|
void SetBlendEquationIndexed(Uint index, BlendEquation color, BlendEquation alpha);
|
||||||
|
void GetBlendEquationIndexed(Uint index, BlendEquation& color, BlendEquation& alpha) const;
|
||||||
|
|
||||||
// Depth
|
// Depth
|
||||||
void SetDepthFunc(DepthTestFunc func);
|
void SetDepthFunc(DepthTestFunc func);
|
||||||
|
|||||||
@@ -45,6 +45,23 @@ namespace MobileGL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BlendEquation ConvertGLEnumToBlendEquation(GLenum v) {
|
||||||
|
switch (v) {
|
||||||
|
case GL_FUNC_ADD:
|
||||||
|
return BlendEquation::Add;
|
||||||
|
case GL_FUNC_SUBTRACT:
|
||||||
|
return BlendEquation::Subtract;
|
||||||
|
case GL_FUNC_REVERSE_SUBTRACT:
|
||||||
|
return BlendEquation::ReverseSubtract;
|
||||||
|
case GL_MIN:
|
||||||
|
return BlendEquation::Min;
|
||||||
|
case GL_MAX:
|
||||||
|
return BlendEquation::Max;
|
||||||
|
default:
|
||||||
|
return BlendEquation::Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DepthTestFunc ConvertGLEnumToDepthTestFunc(GLenum v) {
|
DepthTestFunc ConvertGLEnumToDepthTestFunc(GLenum v) {
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case GL_NEVER:
|
case GL_NEVER:
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
namespace MobileGL {
|
namespace MobileGL {
|
||||||
namespace MG_Util {
|
namespace MG_Util {
|
||||||
BlendFactor ConvertGLEnumToBlendFactor(GLenum value);
|
BlendFactor ConvertGLEnumToBlendFactor(GLenum value);
|
||||||
|
BlendEquation ConvertGLEnumToBlendEquation(GLenum value);
|
||||||
DepthTestFunc ConvertGLEnumToDepthTestFunc(GLenum value);
|
DepthTestFunc ConvertGLEnumToDepthTestFunc(GLenum value);
|
||||||
PixelStoreParam ConvertGLEnumToPixelStoreParam(GLenum value);
|
PixelStoreParam ConvertGLEnumToPixelStoreParam(GLenum value);
|
||||||
CullFaceMode ConvertGLEnumToCullFaceMode(GLenum value);
|
CullFaceMode ConvertGLEnumToCullFaceMode(GLenum value);
|
||||||
|
|||||||
@@ -46,6 +46,23 @@ namespace MobileGL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum ConvertBlendEquationToGLEnum(BlendEquation v) {
|
||||||
|
switch (v) {
|
||||||
|
case BlendEquation::Add:
|
||||||
|
return GL_FUNC_ADD;
|
||||||
|
case BlendEquation::Subtract:
|
||||||
|
return GL_FUNC_SUBTRACT;
|
||||||
|
case BlendEquation::ReverseSubtract:
|
||||||
|
return GL_FUNC_REVERSE_SUBTRACT;
|
||||||
|
case BlendEquation::Min:
|
||||||
|
return GL_MIN;
|
||||||
|
case BlendEquation::Max:
|
||||||
|
return GL_MAX;
|
||||||
|
default:
|
||||||
|
return GL_UNKNOWN_MGL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GLenum ConvertDepthTestFuncToGLEnum(DepthTestFunc v) {
|
GLenum ConvertDepthTestFuncToGLEnum(DepthTestFunc v) {
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case DepthTestFunc::Never:
|
case DepthTestFunc::Never:
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
namespace MobileGL {
|
namespace MobileGL {
|
||||||
namespace MG_Util {
|
namespace MG_Util {
|
||||||
GLenum ConvertBlendFactorToGLEnum(BlendFactor value);
|
GLenum ConvertBlendFactorToGLEnum(BlendFactor value);
|
||||||
|
GLenum ConvertBlendEquationToGLEnum(BlendEquation value);
|
||||||
GLenum ConvertDepthTestFuncToGLEnum(DepthTestFunc value);
|
GLenum ConvertDepthTestFuncToGLEnum(DepthTestFunc value);
|
||||||
GLenum ConvertPixelStoreParamToGLEnum(PixelStoreParam value);
|
GLenum ConvertPixelStoreParamToGLEnum(PixelStoreParam value);
|
||||||
GLenum ConvertCullFaceModeToGLEnum(CullFaceMode value);
|
GLenum ConvertCullFaceModeToGLEnum(CullFaceMode value);
|
||||||
|
|||||||
@@ -103,5 +103,22 @@ namespace MobileGL {
|
|||||||
return VK_BLEND_FACTOR_ONE;
|
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 MG_Util
|
||||||
} // namespace MobileGL
|
} // namespace MobileGL
|
||||||
|
|||||||
@@ -16,5 +16,6 @@ namespace MobileGL {
|
|||||||
VkCullModeFlags ConvertCullFaceModeToVkEnum(CullFaceMode value, Bool invertClockwise = false);
|
VkCullModeFlags ConvertCullFaceModeToVkEnum(CullFaceMode value, Bool invertClockwise = false);
|
||||||
VkCompareOp ConvertDepthTestFuncToVkEnum(DepthTestFunc value);
|
VkCompareOp ConvertDepthTestFuncToVkEnum(DepthTestFunc value);
|
||||||
VkBlendFactor ConvertBlendFactorToVkEnum(BlendFactor value);
|
VkBlendFactor ConvertBlendFactorToVkEnum(BlendFactor value);
|
||||||
|
VkBlendOp ConvertBlendEquationToVkEnum(BlendEquation value);
|
||||||
} // namespace MG_Util
|
} // namespace MG_Util
|
||||||
} // namespace MobileGL
|
} // namespace MobileGL
|
||||||
|
|||||||
Reference in New Issue
Block a user