From 40fc317f69857138ba812a913f6469b608d3009d Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Mon, 16 Feb 2026 14:06:34 +0800 Subject: [PATCH] [Fix] (MG_Backend/DirectVulkan): Add shader position transforms & correct namespace name. --- CMakeLists.txt | 2 +- .../MG_Backend/DirectVulkan/DirectVulkan.cpp | 4 +- .../DirectVulkan/Managers/ProgramManager.cpp | 360 +++++++++++++++++- .../DirectVulkan/Managers/ProgramManager.h | 19 +- MobileGL/MG_Backend/DirectVulkan/TmpImpl.cpp | 37 +- MobileGL/MG_Backend/DirectVulkan/TmpImpl.h | 4 +- .../EGLImpl/EGLForVulkan/EGLForVulkan.cpp | 4 +- 7 files changed, 401 insertions(+), 29 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a59dd5e..53e2d500 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -347,4 +347,4 @@ if (NOT ANDROID) if (MOBILEGL_BUILD_BENCHMARK) add_subdirectory(MobileGL/MG_Benchmark) endif() -endif() \ No newline at end of file +endif() diff --git a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp index 235729c0..0aad7786 100644 --- a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp @@ -15,14 +15,14 @@ namespace MobileGL::MG_Backend::DirectVulkan { void Clear(GLbitfield mask) { if (USE_TMP_IMPL) { - MobileGL::Backend::DirectVulkan::TmpImpl::Clear(mask); + MobileGL::MG_Backend::DirectVulkan::TmpImpl::Clear(mask); return; } } void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) { if (USE_TMP_IMPL) { - MobileGL::Backend::DirectVulkan::TmpImpl::DrawElements(mode, count, type, indices); + MobileGL::MG_Backend::DirectVulkan::TmpImpl::DrawElements(mode, count, type, indices); return; } pVulkanRenderer->RenderFrame(); diff --git a/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.cpp index ee690109..2483e154 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.cpp @@ -8,7 +8,296 @@ #include "ProgramManager.h" +#include "MG_Util/Debug/Log.h" +#include "spirv-tools/libspirv.h" +#include "spirv-tools/optimizer.hpp" +#include "source/opt/constants.h" +#include "source/opt/instruction.h" +#include "source/opt/ir_builder.h" +#include "source/opt/ir_context.h" +#include "source/opt/module.h" +#include "source/opt/pass.h" +#include "source/opt/type_manager.h" + +#include + namespace MobileGL::MG_Backend::DirectVulkan::VkManager { + namespace { + using ProgramObject = MG_State::GLState::ProgramObject; + using ShaderObject = MG_State::GLState::ShaderObject; + + struct PositionTargetInfo { + uint32_t variableId = 0; + uint32_t vectorTypeId = 0; + uint32_t floatTypeId = 0; + uint32_t vectorPtrTypeId = 0; + uint32_t memberIndex = 0; + bool isMember = false; + }; + + bool IsVec4Float32(spvtools::opt::IRContext* context, uint32_t typeId, uint32_t* outFloatTypeId) { + auto* vecInst = context->get_def_use_mgr()->GetDef(typeId); + if (!vecInst || vecInst->opcode() != spv::Op::OpTypeVector) return false; + if (vecInst->GetSingleWordInOperand(1) != 4) return false; + + const uint32_t floatTypeId = vecInst->GetSingleWordInOperand(0); + auto* floatInst = context->get_def_use_mgr()->GetDef(floatTypeId); + if (!floatInst || floatInst->opcode() != spv::Op::OpTypeFloat) return false; + if (floatInst->GetSingleWordInOperand(0) != 32) return false; + + if (outFloatTypeId) *outFloatTypeId = floatTypeId; + return true; + } + + bool ResolveDirectPositionTarget(spvtools::opt::IRContext* context, uint32_t variableId, + PositionTargetInfo* outTarget) { + auto* varInst = context->get_def_use_mgr()->GetDef(variableId); + if (!varInst || varInst->opcode() != spv::Op::OpVariable) return false; + if (varInst->GetSingleWordInOperand(0) != static_cast(spv::StorageClass::Output)) return false; + + auto* ptrTypeInst = context->get_def_use_mgr()->GetDef(varInst->type_id()); + if (!ptrTypeInst || ptrTypeInst->opcode() != spv::Op::OpTypePointer) return false; + if (ptrTypeInst->GetSingleWordInOperand(0) != static_cast(spv::StorageClass::Output)) + return false; + + PositionTargetInfo target{}; + target.variableId = variableId; + target.vectorTypeId = ptrTypeInst->GetSingleWordInOperand(1); + if (!IsVec4Float32(context, target.vectorTypeId, &target.floatTypeId)) return false; + target.vectorPtrTypeId = varInst->type_id(); + target.isMember = false; + + *outTarget = target; + return true; + } + + uint32_t FindOutputVectorPointerTypeId(spvtools::opt::IRContext* context, uint32_t vectorTypeId) { + auto* vectorType = context->get_type_mgr()->GetType(vectorTypeId); + if (!vectorType) return 0; + spvtools::opt::analysis::Pointer ptrType(vectorType, spv::StorageClass::Output); + return context->get_type_mgr()->GetTypeInstruction(&ptrType); + } + + bool ResolveMemberPositionTarget(spvtools::opt::IRContext* context, uint32_t structTypeId, uint32_t memberIndex, + PositionTargetInfo* outTarget) { + auto* structInst = context->get_def_use_mgr()->GetDef(structTypeId); + if (!structInst || structInst->opcode() != spv::Op::OpTypeStruct) return false; + if (memberIndex >= structInst->NumInOperands()) return false; + + const uint32_t vectorTypeId = structInst->GetSingleWordInOperand(memberIndex); + uint32_t floatTypeId = 0; + if (!IsVec4Float32(context, vectorTypeId, &floatTypeId)) return false; + + const uint32_t vectorPtrTypeId = FindOutputVectorPointerTypeId(context, vectorTypeId); + if (vectorPtrTypeId == 0) return false; + + for (auto& inst : context->module()->types_values()) { + if (inst.opcode() != spv::Op::OpVariable) continue; + if (inst.GetSingleWordInOperand(0) != static_cast(spv::StorageClass::Output)) continue; + + auto* ptrTypeInst = context->get_def_use_mgr()->GetDef(inst.type_id()); + if (!ptrTypeInst || ptrTypeInst->opcode() != spv::Op::OpTypePointer) continue; + if (ptrTypeInst->GetSingleWordInOperand(0) != static_cast(spv::StorageClass::Output)) + continue; + if (ptrTypeInst->GetSingleWordInOperand(1) != structTypeId) continue; + + PositionTargetInfo target{}; + target.variableId = inst.result_id(); + target.vectorTypeId = vectorTypeId; + target.floatTypeId = floatTypeId; + target.vectorPtrTypeId = vectorPtrTypeId; + target.memberIndex = memberIndex; + target.isMember = true; + *outTarget = target; + return true; + } + + return false; + } + + bool FindPositionTarget(spvtools::opt::IRContext* context, PositionTargetInfo* outTarget) { + Vector> memberCandidates; + constexpr uint32_t kDecorationBuiltIn = static_cast(spv::Decoration::BuiltIn); + constexpr uint32_t kBuiltInPosition = static_cast(spv::BuiltIn::Position); + + for (auto& inst : context->module()->annotations()) { + if (inst.opcode() == spv::Op::OpDecorate) { + if (inst.NumInOperands() < 3) continue; + if (inst.GetSingleWordInOperand(1) != kDecorationBuiltIn) continue; + if (inst.GetSingleWordInOperand(2) != kBuiltInPosition) continue; + if (ResolveDirectPositionTarget(context, inst.GetSingleWordInOperand(0), outTarget)) return true; + } else if (inst.opcode() == spv::Op::OpMemberDecorate) { + if (inst.NumInOperands() < 4) continue; + if (inst.GetSingleWordInOperand(2) != kDecorationBuiltIn) continue; + if (inst.GetSingleWordInOperand(3) != kBuiltInPosition) continue; + memberCandidates.emplace_back(inst.GetSingleWordInOperand(0), inst.GetSingleWordInOperand(1)); + } + } + + for (const auto& [structTypeId, memberIndex] : memberCandidates) { + if (ResolveMemberPositionTarget(context, structTypeId, memberIndex, outTarget)) return true; + } + return false; + } + + bool InsertPositionFixup(spvtools::opt::IRContext* context, spvtools::opt::Instruction* insertBefore, + const PositionTargetInfo& target, uint32_t halfConstId, bool doYFlip, bool doZRemap) { + using namespace spvtools::opt; + InstructionBuilder builder(context, insertBefore, + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); + + uint32_t positionPtrId = target.variableId; + if (target.isMember) { + const uint32_t memberIndexId = builder.GetUintConstantId(target.memberIndex); + if (memberIndexId == 0) return false; + auto* access = builder.AddAccessChain(target.vectorPtrTypeId, target.variableId, {memberIndexId}); + if (!access) return false; + positionPtrId = access->result_id(); + } + + auto* position = builder.AddLoad(target.vectorTypeId, positionPtrId); + if (!position) return false; + auto* x = builder.AddCompositeExtract(target.floatTypeId, position->result_id(), {0}); + auto* y = builder.AddCompositeExtract(target.floatTypeId, position->result_id(), {1}); + auto* z = builder.AddCompositeExtract(target.floatTypeId, position->result_id(), {2}); + auto* w = builder.AddCompositeExtract(target.floatTypeId, position->result_id(), {3}); + if (!x || !y || !z || !w) return false; + + if (!doYFlip && !doZRemap) return false; + + uint32_t yValueId = y->result_id(); + if (doYFlip) { + auto* negY = builder.AddUnaryOp(target.floatTypeId, spv::Op::OpFNegate, y->result_id()); + if (!negY) return false; + yValueId = negY->result_id(); + } + + uint32_t zValueId = z->result_id(); + if (doZRemap) { + auto* zPlusW = builder.AddBinaryOp(target.floatTypeId, spv::Op::OpFAdd, z->result_id(), w->result_id()); + if (!zPlusW) return false; + auto* mappedZ = + builder.AddBinaryOp(target.floatTypeId, spv::Op::OpFMul, zPlusW->result_id(), halfConstId); + if (!mappedZ) return false; + zValueId = mappedZ->result_id(); + } + + auto* fixedPosition = builder.AddCompositeConstruct(target.vectorTypeId, + {x->result_id(), yValueId, zValueId, w->result_id()}); + if (!fixedPosition) return false; + + return builder.AddStore(positionPtrId, fixedPosition->result_id()) != nullptr; + } + + class GlToVulkanPositionFixPass final : public spvtools::opt::Pass { + public: + const char* name() const override { return "gl-to-vulkan-position-fix"; } + explicit GlToVulkanPositionFixPass(ShaderTransformFlags transformFlags) + : m_transformFlags(transformFlags) {} + + Status Process() override { + if (!m_transformFlags) return Status::SuccessWithoutChange; + PositionTargetInfo target{}; + if (!FindPositionTarget(context(), &target)) return Status::SuccessWithoutChange; + + auto* floatType = context()->get_type_mgr()->GetType(target.floatTypeId); + if (!floatType) return Status::SuccessWithoutChange; + + const uint32_t halfBits = std::bit_cast(0.5f); + const auto* halfConst = context()->get_constant_mgr()->GetConstant(floatType, {halfBits}); + auto* halfInst = context()->get_constant_mgr()->GetDefiningInstruction(halfConst); + if (!halfInst) return Status::SuccessWithoutChange; + const uint32_t halfConstId = halfInst->result_id(); + + const bool doYFlip = (m_transformFlags & ShaderTransformBit::PositionYFlip); + const bool doZRemap = (m_transformFlags & ShaderTransformBit::PositionZRemap); + + bool modified = false; + for (auto& entryPoint : get_module()->entry_points()) { + if (entryPoint.opcode() != spv::Op::OpEntryPoint) continue; + if (entryPoint.NumInOperands() < 2) continue; + + const auto model = static_cast(entryPoint.GetSingleWordInOperand(0)); + if (model != spv::ExecutionModel::Vertex && model != spv::ExecutionModel::TessellationEvaluation && + model != spv::ExecutionModel::Geometry) { + continue; + } + + auto* function = context()->GetFunction(entryPoint.GetSingleWordInOperand(1)); + if (!function) continue; + + for (auto& bb : *function) { + for (auto instIter = bb.begin(); instIter != bb.end(); ++instIter) { + auto* inst = &*instIter; + const bool needsFixup = + (model == spv::ExecutionModel::Geometry && inst->opcode() == spv::Op::OpEmitVertex) || + (model != spv::ExecutionModel::Geometry && inst->opcode() == spv::Op::OpReturn); + if (!needsFixup) continue; + + modified |= InsertPositionFixup(context(), inst, target, halfConstId, doYFlip, doZRemap); + } + } + } + + if (!modified) return Status::SuccessWithoutChange; + context()->InvalidateAnalysesExceptFor(spvtools::opt::IRContext::kAnalysisDefUse | + spvtools::opt::IRContext::kAnalysisInstrToBlockMapping); + return Status::SuccessWithChange; + } + + private: + ShaderTransformFlags m_transformFlags; + }; + + spvtools::Optimizer::PassToken CreateGlToVulkanPositionFixPass(ShaderTransformFlags transformFlags) { + return spvtools::Optimizer::PassToken(MakeUnique(transformFlags)); + } + + bool TransformSpirvForVulkanPositionFix(const Vector& input, Vector& output, + ShaderTransformFlags transformFlags) { + if (input.empty()) { + output.clear(); + return true; + } + + if (!transformFlags) { + output = input; + return true; + } + + spvtools::Optimizer optimizer(SPV_ENV_VULKAN_1_3); + spvtools::OptimizerOptions options; + options.set_run_validator(false); + optimizer.RegisterPass(CreateGlToVulkanPositionFixPass(transformFlags)); + + const bool success = optimizer.Run(input.data(), input.size(), &output, options); + if (!success) { + MGLOG_E("Vulkan: failed to run GL->Vulkan position fix pass"); + output = input; + } + return success; + } + + ShaderStage PickClipFixupStage(const Vector>& shaders) { + bool hasGeometry = false; + bool hasTessEval = false; + bool hasVertex = false; + + for (const auto& shader : shaders) { + if (!shader) continue; + const auto stage = shader->GetShaderStage(); + hasGeometry |= (stage == ShaderStage::Geometry); + hasTessEval |= (stage == ShaderStage::TessEval); + hasVertex |= (stage == ShaderStage::Vertex); + } + + if (hasGeometry) return ShaderStage::Geometry; + if (hasTessEval) return ShaderStage::TessEval; + if (hasVertex) return ShaderStage::Vertex; + return ShaderStage::Unknown; + } + } // namespace + ProgramManager::~ProgramManager() { for (auto& [_, stages] : m_cache) { DestroyStages(stages); @@ -16,7 +305,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::VkManager { m_cache.clear(); } - ProgramManager::HashType ProgramManager::ComputeSpvHash(MG_State::GLState::ProgramObject* program) const { + ProgramManager::HashType ProgramManager::ComputeSourceSpvHash(MG_State::GLState::ProgramObject* program) const { if (!program) return 0; XXH64_state_t* state = XXH64_createState(); XXH64_reset(state, 0xC0FFEEu); @@ -30,6 +319,60 @@ namespace MobileGL::MG_Backend::DirectVulkan::VkManager { return hash; } + ProgramManager::HashType ProgramManager::ComputeSpvHash(const Vector>& spirvs) const { + XXH64_state_t* state = XXH64_createState(); + XXH64_reset(state, 0xC0FFEEu); + for (const auto& spv : spirvs) { + if (spv.empty()) continue; + XXH64_update(state, spv.data(), spv.size() * sizeof(Uint32)); + } + HashType hash = XXH64_digest(state); + XXH64_freeState(state); + return hash; + } + + void ProgramManager::BuildPipelineSpirvModules(MG_State::GLState::ProgramObject* program, + Vector>& outSpirvs, + ShaderTransformFlags transformFlags) const { + outSpirvs.clear(); + if (!program) return; + + auto& spirvs = program->GetGeneratedSpirv(); + auto& shaders = program->GetAttachedShaders(); + const ShaderStage fixupStage = PickClipFixupStage(shaders); + + outSpirvs.reserve(spirvs.size()); + for (SizeT i = 0; i < spirvs.size(); ++i) { + Vector module = spirvs[i]; + + ShaderStage stage = ShaderStage::Unknown; + if (i < shaders.size() && shaders[i]) stage = shaders[i]->GetShaderStage(); + + if (!module.empty() && fixupStage != ShaderStage::Unknown && stage == fixupStage) { + Vector transformed; + TransformSpirvForVulkanPositionFix(module, transformed, transformFlags); + module = Move(transformed); + } + outSpirvs.push_back(Move(module)); + } + } + + ProgramManager::HashType ProgramManager::ComputeSpvHash(MG_State::GLState::ProgramObject* program, + ShaderTransformFlags transformFlags) const { + Vector> spirvs; + BuildPipelineSpirvModules(program, spirvs, transformFlags); + return ComputeSpvHash(spirvs); + } + + ProgramManager::HashType ProgramManager::ComputeProgramHash(MG_State::GLState::ProgramObject* program, + ShaderTransformFlags transformFlags) const { + if (!program) return 0; + const HashType sourceHash = ComputeSourceSpvHash(program); + auto it = m_cache.find(program); + if (it != m_cache.end() && it->second.sourceHash == sourceHash) return it->second.hash; + return ComputeSpvHash(program, transformFlags); + } + VkShaderStageFlagBits ProgramManager::ToVkStage(ShaderStage stage) const { switch (stage) { case ShaderStage::Vertex: @@ -57,21 +400,24 @@ namespace MobileGL::MG_Backend::DirectVulkan::VkManager { } stages.modules.clear(); stages.stages.clear(); + stages.sourceHash = 0; stages.hash = 0; } Vector& ProgramManager::CreatePipelineShaderStages( - MG_State::GLState::ProgramObject* program) { + MG_State::GLState::ProgramObject* program, ShaderTransformFlags transformFlags) { auto& entry = m_cache[program]; - HashType newHash = ComputeSpvHash(program); - if (!entry.stages.empty() && entry.hash == newHash) return entry.stages; + HashType sourceHash = ComputeSourceSpvHash(program); + if (!entry.stages.empty() && entry.sourceHash == sourceHash) return entry.stages; DestroyStages(entry); - entry.hash = newHash; + entry.sourceHash = sourceHash; if (!program) return entry.stages; - auto& spirvs = program->GetGeneratedSpirv(); + Vector> spirvs; + BuildPipelineSpirvModules(program, spirvs, transformFlags); + entry.hash = ComputeSpvHash(spirvs); auto& shaders = program->GetAttachedShaders(); for (SizeT i = 0; i < spirvs.size(); ++i) { @@ -87,7 +433,7 @@ namespace MobileGL::MG_Backend::DirectVulkan::VkManager { VkPipelineShaderStageCreateInfo stage{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO}; ShaderStage shaderStage = ShaderStage::Unknown; - if (i < shaders.size()) shaderStage = shaders[i]->GetShaderStage(); + if (i < shaders.size() && shaders[i]) shaderStage = shaders[i]->GetShaderStage(); stage.stage = ToVkStage(shaderStage); stage.module = module; stage.pName = "main"; diff --git a/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.h b/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.h index 35b4f151..b1f36473 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.h +++ b/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.h @@ -13,6 +13,13 @@ #include "MG_State/GLState/ProgramState/ProgramObject.h" namespace MobileGL::MG_Backend::DirectVulkan::VkManager { + enum class ShaderTransformBit : Uint { + None = 0, + PositionYFlip = 1 << 0, + PositionZRemap = 1 << 1, + }; + using ShaderTransformFlags = Flags; + class ProgramManager { public: using HashType = Uint64; @@ -24,17 +31,25 @@ namespace MobileGL::MG_Backend::DirectVulkan::VkManager { ProgramManager& operator=(const ProgramManager&) = delete; Vector& CreatePipelineShaderStages( - MG_State::GLState::ProgramObject* program); + MG_State::GLState::ProgramObject* program, + ShaderTransformFlags transformFlags = ShaderTransformBit::PositionZRemap); + HashType ComputeProgramHash(MG_State::GLState::ProgramObject* program, + ShaderTransformFlags transformFlags = ShaderTransformBit::PositionZRemap) const; private: struct ProgramStages { + HashType sourceHash = 0; HashType hash = 0; Vector stages; Vector modules; }; void DestroyStages(ProgramStages& stages); - HashType ComputeSpvHash(MG_State::GLState::ProgramObject* program) const; + HashType ComputeSourceSpvHash(MG_State::GLState::ProgramObject* program) const; + HashType ComputeSpvHash(MG_State::GLState::ProgramObject* program, ShaderTransformFlags transformFlags) const; + HashType ComputeSpvHash(const Vector>& spirvs) const; + void BuildPipelineSpirvModules(MG_State::GLState::ProgramObject* program, Vector>& outSpirvs, + ShaderTransformFlags transformFlags) const; VkShaderStageFlagBits ToVkStage(ShaderStage stage) const; VulkanContext& m_ctx; diff --git a/MobileGL/MG_Backend/DirectVulkan/TmpImpl.cpp b/MobileGL/MG_Backend/DirectVulkan/TmpImpl.cpp index dc7b1ae7..3a189a51 100644 --- a/MobileGL/MG_Backend/DirectVulkan/TmpImpl.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/TmpImpl.cpp @@ -20,7 +20,7 @@ #include #define DEBUG_TRACE_POINT() MGLOG_D("DV TmpImpl Trace: %s:%d", __func__, __LINE__) -namespace MobileGL::Backend::DirectVulkan::TmpImpl { +namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl { namespace { class PendingClearInfo; void BeginRenderPass(GLbitfield clearMask, const PendingClearInfo* clearInfo); @@ -411,7 +411,7 @@ namespace MobileGL::Backend::DirectVulkan::TmpImpl { if (view != VK_NULL_HANDLE) trash.mipViews.push_back(view); } } - frame.TrashImages.push_back(std::move(trash)); + frame.TrashImages.push_back(Move(trash)); res.view = VK_NULL_HANDLE; res.image = VK_NULL_HANDLE; @@ -1434,8 +1434,8 @@ namespace MobileGL::Backend::DirectVulkan::TmpImpl { DestroyBackendFramebuffer(backend); - backend.attachments = std::move(newAttachments); - backend.attachmentIndex = std::move(newIndex); + backend.attachments = Move(newAttachments); + backend.attachmentIndex = Move(newIndex); backend.extent = extent; backend.colorAttachmentCount = nEffectiveBuffers; backend.hasDepth = useDepthAttachment; @@ -2119,6 +2119,16 @@ namespace MobileGL::Backend::DirectVulkan::TmpImpl { Memset(g.nullUbo.mapped, 0, 256); } + VkManager::ShaderTransformFlags GetShaderTransformFlags() { + VkManager::ShaderTransformFlags flags = VkManager::ShaderTransformBit::PositionZRemap; + const auto& currentDrawFBO = + MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); + if (currentDrawFBO == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO) { + flags |= VkManager::ShaderTransformBit::PositionYFlip; + } + return flags; + } + ProgramResource& GetProgramResource(ProgramObject* program) { auto& slot = g.programs[program]; Uint64 newHash = ComputeProgramSpvHash(program); @@ -2131,10 +2141,11 @@ namespace MobileGL::Backend::DirectVulkan::TmpImpl { slot.program = program; slot.spvHash = newHash; - slot.programHash = newHash; + VkManager::ShaderTransformFlags transformFlags = GetShaderTransformFlags(); if (!g.programMgr) g.programMgr = MakeUnique(*g.ctx); - slot.shaderStages = &g.programMgr->CreatePipelineShaderStages(program); + slot.shaderStages = &g.programMgr->CreatePipelineShaderStages(program, transformFlags); + slot.programHash = g.programMgr->ComputeProgramHash(program, transformFlags); ReflectProgramResources(program, slot); @@ -2239,7 +2250,7 @@ namespace MobileGL::Backend::DirectVulkan::TmpImpl { VkRenderPass renderPass, Uint32 colorAttachmentCount, Bool hasDepth, Uint64 renderPassKey) { if (!g.programMgr) g.programMgr = MakeUnique(*g.ctx); - prog.shaderStages = &g.programMgr->CreatePipelineShaderStages(prog.program); + prog.shaderStages = &g.programMgr->CreatePipelineShaderStages(prog.program, GetShaderTransformFlags()); if (!prog.shaderStages || prog.shaderStages->empty()) { MGLOG_E("Vulkan: shader stages are empty for program %u (hash=%llu)", prog.program->GetExternalIndex(), static_cast(prog.programHash)); @@ -2274,8 +2285,8 @@ namespace MobileGL::Backend::DirectVulkan::TmpImpl { key.depthTest = rs.DepthTestEnabled ? 1u : 0u; key.depthWrite = rs.DepthMask ? 1u : 0u; key.depthFunc = static_cast(rs.DepthFunc); - key.cullEnable = rs.CullFaceEnabled ? 1u : 0u; - key.cullMode = static_cast(rs.CullFaceModeSetting); + key.cullEnable = 0; + key.cullMode = 0; key.colorMask = (rs.ColorMask.x() ? 1u : 0u) | (rs.ColorMask.y() ? 2u : 0u) | (rs.ColorMask.z() ? 4u : 0u) | (rs.ColorMask.w() ? 8u : 0u); key.srcRGB = static_cast(rs.BlendStates[0].SrcFactorRGB); @@ -2337,7 +2348,7 @@ namespace MobileGL::Backend::DirectVulkan::TmpImpl { DEBUG_TRACE_POINT(); VkPipelineRasterizationStateCreateInfo raster{VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO}; raster.polygonMode = VK_POLYGON_MODE_FILL; - raster.cullMode = rs.CullFaceEnabled ? ToVkCullMode(rs.CullFaceModeSetting) : VK_CULL_MODE_NONE; + raster.cullMode = VK_CULL_MODE_NONE; raster.frontFace = VK_FRONT_FACE_CLOCKWISE; raster.lineWidth = 1.0f; @@ -2703,7 +2714,7 @@ namespace MobileGL::Backend::DirectVulkan::TmpImpl { VK_VERIFY(vkCreateFramebuffer(g.ctx->GetDevice(), &fbci, nullptr, &fb), "vkCreateFramebuffer"); fbs.push_back(fb); } - g.swapchain->SetFramebuffers(std::move(fbs)); + g.swapchain->SetFramebuffers(Move(fbs)); } void DestroyFrameResources() { @@ -2722,7 +2733,7 @@ namespace MobileGL::Backend::DirectVulkan::TmpImpl { for (Uint32 i = 0; i < frames; ++i) { auto fr = MakeUnique(); fr->Initialize(*g.ctx, g.commandPool); - g.frames.push_back(std::move(fr)); + g.frames.push_back(Move(fr)); } g.frameDescriptorPools.clear(); g.frameDescriptorPools.resize(frames); @@ -3445,4 +3456,4 @@ namespace MobileGL::Backend::DirectVulkan::TmpImpl { } clearInfo.mask |= validMask; } -} // namespace MobileGL::Backend::DirectVulkan::TmpImpl +} // namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl diff --git a/MobileGL/MG_Backend/DirectVulkan/TmpImpl.h b/MobileGL/MG_Backend/DirectVulkan/TmpImpl.h index c4c5f254..278a2be5 100644 --- a/MobileGL/MG_Backend/DirectVulkan/TmpImpl.h +++ b/MobileGL/MG_Backend/DirectVulkan/TmpImpl.h @@ -9,7 +9,7 @@ #pragma once #include -namespace MobileGL::Backend::DirectVulkan::TmpImpl { +namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl { void Present(); void FrameBegin(); void InitVulkan(ANativeWindow* window); @@ -50,4 +50,4 @@ namespace MobileGL::Backend::DirectVulkan::TmpImpl { GLsizei height); void GenerateMipmap(GLenum target); void Present(); -} // namespace MobileGL::Backend::DirectVulkan::TmpImpl \ No newline at end of file +} // namespace MobileGL::MG_Backend::DirectVulkan::TmpImpl \ No newline at end of file diff --git a/MobileGL/MG_Impl/EGLImpl/EGLForVulkan/EGLForVulkan.cpp b/MobileGL/MG_Impl/EGLImpl/EGLForVulkan/EGLForVulkan.cpp index db35de54..80b34546 100644 --- a/MobileGL/MG_Impl/EGLImpl/EGLForVulkan/EGLForVulkan.cpp +++ b/MobileGL/MG_Impl/EGLImpl/EGLForVulkan/EGLForVulkan.cpp @@ -89,7 +89,7 @@ namespace MobileGL { } void CreateWindowSurfaceForVulkan(NativeWindowType window) { - MobileGL::Backend::DirectVulkan::TmpImpl::InitVulkan(window); + MobileGL::MG_Backend::DirectVulkan::TmpImpl::InitVulkan(window); return; MG_Backend::DirectVulkan::pVulkanRenderer = MakeUnique(window); MG_Backend::DirectVulkan::pVulkanRenderer->Initialize(); @@ -105,7 +105,7 @@ namespace MobileGL { } EGLBoolean SwapBuffers(EGLDisplay dpy, EGLSurface draw) { - MobileGL::Backend::DirectVulkan::TmpImpl::Present(); + MobileGL::MG_Backend::DirectVulkan::TmpImpl::Present(); return EGL_TRUE; if (!MG_Backend::DirectVulkan::pVulkanRenderer) { MGLOG_E("EGLForVulkan::SwapBuffers called but VulkanRenderer is null");