mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Fix] (MG_Backend/DirectVulkan): Properly handle front face state. save VkDevice as static member
This commit is contained in:
@@ -24,7 +24,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||||
Uint32 subpass = 0;
|
Uint32 subpass = 0;
|
||||||
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
VkCullModeFlags cullMode = VK_CULL_MODE_NONE;
|
VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT;
|
||||||
VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE;
|
VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||||
Bool depthTestEnable = false;
|
Bool depthTestEnable = false;
|
||||||
Bool depthWriteEnable = false;
|
Bool depthWriteEnable = false;
|
||||||
|
|||||||
@@ -364,7 +364,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto& entry = m_cache[hash];
|
auto& entry = m_cache[hash];
|
||||||
entry.device = m_device;
|
|
||||||
entry.hash = hash;
|
entry.hash = hash;
|
||||||
auto& shaders = program.GetAttachedShaders();
|
auto& shaders = program.GetAttachedShaders();
|
||||||
auto& spirv = program.GetGeneratedSpirv();
|
auto& spirv = program.GetGeneratedSpirv();
|
||||||
|
|||||||
@@ -26,39 +26,35 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
};
|
};
|
||||||
using CompileOptionFlags = Flags<CompileOptionBit>;
|
using CompileOptionFlags = Flags<CompileOptionBit>;
|
||||||
using HashType = Uint64;
|
using HashType = Uint64;
|
||||||
struct BackendProgramObject {
|
struct VkProgramObject {
|
||||||
HashType hash = 0;
|
HashType hash = 0;
|
||||||
VkDevice device = VK_NULL_HANDLE;
|
|
||||||
Vector<VkPipelineShaderStageCreateInfo> stages;
|
Vector<VkPipelineShaderStageCreateInfo> stages;
|
||||||
Vector<VkShaderModule> modules;
|
Vector<VkShaderModule> modules;
|
||||||
|
static inline VkDevice s_device = VK_NULL_HANDLE;
|
||||||
|
|
||||||
BackendProgramObject() = default;
|
VkProgramObject() = default;
|
||||||
BackendProgramObject(const BackendProgramObject&) = delete;
|
VkProgramObject(const VkProgramObject&) = delete;
|
||||||
BackendProgramObject& operator=(const BackendProgramObject&) = delete;
|
VkProgramObject& operator=(const VkProgramObject&) = delete;
|
||||||
BackendProgramObject(BackendProgramObject&& other) noexcept {
|
VkProgramObject(VkProgramObject&& other) noexcept {
|
||||||
hash = other.hash;
|
hash = other.hash;
|
||||||
device = other.device;
|
|
||||||
stages = std::move(other.stages);
|
stages = std::move(other.stages);
|
||||||
modules = std::move(other.modules);
|
modules = std::move(other.modules);
|
||||||
other.hash = 0;
|
other.hash = 0;
|
||||||
other.device = VK_NULL_HANDLE;
|
|
||||||
}
|
}
|
||||||
BackendProgramObject& operator=(BackendProgramObject&& other) noexcept {
|
VkProgramObject& operator=(VkProgramObject&& other) noexcept {
|
||||||
if (this == &other) {
|
if (this == &other) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
DestroyModules();
|
DestroyModules();
|
||||||
stages.clear();
|
stages.clear();
|
||||||
hash = other.hash;
|
hash = other.hash;
|
||||||
device = other.device;
|
|
||||||
stages = std::move(other.stages);
|
stages = std::move(other.stages);
|
||||||
modules = std::move(other.modules);
|
modules = std::move(other.modules);
|
||||||
other.hash = 0;
|
other.hash = 0;
|
||||||
other.device = VK_NULL_HANDLE;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~BackendProgramObject() {
|
~VkProgramObject() {
|
||||||
DestroyModules();
|
DestroyModules();
|
||||||
stages.clear();
|
stages.clear();
|
||||||
}
|
}
|
||||||
@@ -66,8 +62,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
private:
|
private:
|
||||||
void DestroyModules() {
|
void DestroyModules() {
|
||||||
for (auto module : modules) {
|
for (auto module : modules) {
|
||||||
if (module != VK_NULL_HANDLE && device != VK_NULL_HANDLE) {
|
if (module != VK_NULL_HANDLE && s_device != VK_NULL_HANDLE) {
|
||||||
vkDestroyShaderModule(device, module, nullptr);
|
vkDestroyShaderModule(s_device, module, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
modules.clear();
|
modules.clear();
|
||||||
@@ -75,7 +71,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
};
|
};
|
||||||
|
|
||||||
explicit ProgramFactory(VkDevice device, const VulkanRendererConfig& config)
|
explicit ProgramFactory(VkDevice device, const VulkanRendererConfig& config)
|
||||||
: m_device(device), m_config(config) {}
|
: m_device(device), m_config(config) {
|
||||||
|
VkProgramObject::s_device = device;
|
||||||
|
}
|
||||||
~ProgramFactory();
|
~ProgramFactory();
|
||||||
ProgramFactory(const ProgramFactory&) = delete;
|
ProgramFactory(const ProgramFactory&) = delete;
|
||||||
|
|
||||||
@@ -87,7 +85,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
VkDevice m_device = VK_NULL_HANDLE;
|
VkDevice m_device = VK_NULL_HANDLE;
|
||||||
UnorderedMap<HashType, BackendProgramObject> m_cache;
|
UnorderedMap<HashType, VkProgramObject> m_cache;
|
||||||
const VulkanRendererConfig& m_config;
|
const VulkanRendererConfig& m_config;
|
||||||
static inline XXH64_state_t* m_hashState = XXH64_createState();
|
static inline XXH64_state_t* m_hashState = XXH64_createState();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -337,6 +337,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
const MG_State::GLState::VertexArrayObject& vao,
|
const MG_State::GLState::VertexArrayObject& vao,
|
||||||
const MG_State::GLState::FramebufferObject& drawFbo) {
|
const MG_State::GLState::FramebufferObject& drawFbo) {
|
||||||
ProgramFactory::CompileOptionFlags transformFlags = GetShaderTransformFlags(m_swapchainObject.GetPreTransform());
|
ProgramFactory::CompileOptionFlags transformFlags = GetShaderTransformFlags(m_swapchainObject.GetPreTransform());
|
||||||
|
Bool invertClockwise = transformFlags & ProgramFactory::CompileOptionBit::PositionYFlip;
|
||||||
auto& stages = m_programFactory->GetOrCreatePipelineShaderStages(program, transformFlags);
|
auto& stages = m_programFactory->GetOrCreatePipelineShaderStages(program, transformFlags);
|
||||||
if (stages.empty()) {
|
if (stages.empty()) {
|
||||||
MGLOG_D("GetOrCreatePipeline skipped: program has no shader stages");
|
MGLOG_D("GetOrCreatePipeline skipped: program has no shader stages");
|
||||||
@@ -364,10 +365,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
.renderPass = renderPassEntry.renderPass,
|
.renderPass = renderPassEntry.renderPass,
|
||||||
.subpass = 0,
|
.subpass = 0,
|
||||||
.topology = MG_Util::ConvertPrimitiveModeToVkEnum(mode),
|
.topology = MG_Util::ConvertPrimitiveModeToVkEnum(mode),
|
||||||
// .cullMode = cullFaceEnabled
|
.cullMode = cullFaceEnabled
|
||||||
// ? MG_Util::ConvertCullFaceModeToVkEnum(MG_State::pGLContext->GetCullFaceMode())
|
? MG_Util::ConvertCullFaceModeToVkEnum(MG_State::pGLContext->GetCullFaceMode(), invertClockwise)
|
||||||
// : VK_CULL_MODE_NONE,
|
: VK_CULL_MODE_NONE,
|
||||||
.cullMode = VK_CULL_MODE_NONE,
|
|
||||||
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
||||||
.depthTestEnable = depthTestEnabled,
|
.depthTestEnable = depthTestEnabled,
|
||||||
.depthWriteEnable = depthTestEnabled && MG_State::pGLContext->GetDepthMask(),
|
.depthWriteEnable = depthTestEnabled && MG_State::pGLContext->GetDepthMask(),
|
||||||
@@ -389,17 +389,23 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::SetupDraw(FrameContext::FrameData& frame, GLenum mode, Flags<DrawSetupAspect> aspects) {
|
void VulkanRenderer::SetupDraw(FrameContext::FrameData& frame, GLenum mode, Flags<DrawSetupAspect> aspects) {
|
||||||
|
// Prepare render pass
|
||||||
|
const auto& drawFbo =
|
||||||
|
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||||
|
auto& renderPassEntry = m_renderPassManager->GetOrCreateRenderPass(*drawFbo, m_imageIndexAcquired);
|
||||||
|
|
||||||
|
// Prepare pipeline
|
||||||
|
const auto& vao = *MG_State::pGLContext->GetBoundVertexArray();
|
||||||
|
const auto& program = *MG_State::pGLContext->GetCurrentProgram();
|
||||||
|
auto pipeline = GetOrCreatePipeline(mode, program, vao, *drawFbo);
|
||||||
|
|
||||||
// Begin command recording if not yet
|
// Begin command recording if not yet
|
||||||
if (!frame.isCommandRecording) {
|
if (!frame.isCommandRecording) {
|
||||||
m_frameContext.BeginCommandRecording();
|
m_frameContext.BeginCommandRecording();
|
||||||
m_uniformDescriptorBinder->BeginFrame(m_frameContext.GetCurrentFrameIndex());
|
m_uniformDescriptorBinder->BeginFrame(m_frameContext.GetCurrentFrameIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& drawFbo =
|
|
||||||
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
|
||||||
|
|
||||||
// Begin render pass, and handle clear
|
// Begin render pass, and handle clear
|
||||||
auto& renderPassEntry = m_renderPassManager->GetOrCreateRenderPass(*drawFbo, m_imageIndexAcquired);
|
|
||||||
auto* activeRenderPass = VkRenderPassManager::GetActiveRenderPass();
|
auto* activeRenderPass = VkRenderPassManager::GetActiveRenderPass();
|
||||||
|
|
||||||
if (activeRenderPass && (activeRenderPass == &renderPassEntry || activeRenderPass->CompatibleWith(renderPassEntry))) {
|
if (activeRenderPass && (activeRenderPass == &renderPassEntry || activeRenderPass->CompatibleWith(renderPassEntry))) {
|
||||||
@@ -413,9 +419,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MOBILEGL_ASSERT(ok, "%s: BeginRenderPass failed", __func__);
|
MOBILEGL_ASSERT(ok, "%s: BeginRenderPass failed", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& vao = *MG_State::pGLContext->GetBoundVertexArray();
|
|
||||||
const auto& program = *MG_State::pGLContext->GetCurrentProgram();
|
|
||||||
auto pipeline = GetOrCreatePipeline(mode, program, vao, *drawFbo);
|
|
||||||
vkCmdBindPipeline(frame.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
vkCmdBindPipeline(frame.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
|
||||||
m_uniformDescriptorBinder->BindProgramUniformBuffers(frame.commandBuffer, program,
|
m_uniformDescriptorBinder->BindProgramUniformBuffers(frame.commandBuffer, program,
|
||||||
|
|||||||
@@ -31,12 +31,12 @@ namespace MobileGL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkCullModeFlags ConvertCullFaceModeToVkEnum(CullFaceMode v) {
|
VkCullModeFlags ConvertCullFaceModeToVkEnum(CullFaceMode v, Bool invertClockwise) {
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case CullFaceMode::Front:
|
case CullFaceMode::Front:
|
||||||
return VK_CULL_MODE_FRONT_BIT;
|
return invertClockwise ? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_FRONT_BIT;
|
||||||
case CullFaceMode::Back:
|
case CullFaceMode::Back:
|
||||||
return VK_CULL_MODE_BACK_BIT;
|
return invertClockwise ? VK_CULL_MODE_FRONT_BIT : VK_CULL_MODE_BACK_BIT;
|
||||||
case CullFaceMode::FrontAndBack:
|
case CullFaceMode::FrontAndBack:
|
||||||
return VK_CULL_MODE_FRONT_AND_BACK;
|
return VK_CULL_MODE_FRONT_AND_BACK;
|
||||||
case CullFaceMode::Unknown:
|
case CullFaceMode::Unknown:
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
namespace MobileGL {
|
namespace MobileGL {
|
||||||
namespace MG_Util {
|
namespace MG_Util {
|
||||||
VkPrimitiveTopology ConvertPrimitiveModeToVkEnum(GLenum mode);
|
VkPrimitiveTopology ConvertPrimitiveModeToVkEnum(GLenum mode);
|
||||||
VkCullModeFlags ConvertCullFaceModeToVkEnum(CullFaceMode value);
|
VkCullModeFlags ConvertCullFaceModeToVkEnum(CullFaceMode value, Bool invertClockwise = false);
|
||||||
VkCompareOp ConvertDepthTestFuncToVkEnum(DepthTestFunc value);
|
VkCompareOp ConvertDepthTestFuncToVkEnum(DepthTestFunc value);
|
||||||
VkBlendFactor ConvertBlendFactorToVkEnum(BlendFactor value);
|
VkBlendFactor ConvertBlendFactorToVkEnum(BlendFactor value);
|
||||||
} // namespace MG_Util
|
} // namespace MG_Util
|
||||||
|
|||||||
Reference in New Issue
Block a user