mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Feat] (MG_Backend/DirectVulkan): properly handle Vulkan surface transform (pre-rotation)
This commit is contained in:
@@ -135,7 +135,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bool InsertPositionFixup(spvtools::opt::IRContext* context, spvtools::opt::Instruction* insertBefore,
|
Bool InsertPositionFixup(spvtools::opt::IRContext* context, spvtools::opt::Instruction* insertBefore,
|
||||||
const PositionTargetInfo& target, Uint32 halfConstId, Bool doYFlip, Bool doZRemap) {
|
const PositionTargetInfo& target, Uint32 halfConstId, Bool doYFlip, Bool doZRemap,
|
||||||
|
Bool doSurfaceRotate90, Bool doSurfaceRotate180, Bool doSurfaceRotate270) {
|
||||||
using namespace spvtools::opt;
|
using namespace spvtools::opt;
|
||||||
InstructionBuilder builder(context, insertBefore,
|
InstructionBuilder builder(context, insertBefore,
|
||||||
IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
|
IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
|
||||||
@@ -157,8 +158,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
auto* w = builder.AddCompositeExtract(target.floatTypeId, position->result_id(), {3});
|
auto* w = builder.AddCompositeExtract(target.floatTypeId, position->result_id(), {3});
|
||||||
if (!x || !y || !z || !w) return false;
|
if (!x || !y || !z || !w) return false;
|
||||||
|
|
||||||
if (!doYFlip && !doZRemap) return false;
|
if (!doYFlip && !doZRemap && !doSurfaceRotate90 && !doSurfaceRotate180 && !doSurfaceRotate270) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 xValueId = x->result_id();
|
||||||
Uint32 yValueId = y->result_id();
|
Uint32 yValueId = y->result_id();
|
||||||
if (doYFlip) {
|
if (doYFlip) {
|
||||||
auto* negY = builder.AddUnaryOp(target.floatTypeId, spv::Op::OpFNegate, y->result_id());
|
auto* negY = builder.AddUnaryOp(target.floatTypeId, spv::Op::OpFNegate, y->result_id());
|
||||||
@@ -166,6 +170,24 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
yValueId = negY->result_id();
|
yValueId = negY->result_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (doSurfaceRotate90) {
|
||||||
|
auto* negY = builder.AddUnaryOp(target.floatTypeId, spv::Op::OpFNegate, yValueId);
|
||||||
|
if (!negY) return false;
|
||||||
|
xValueId = negY->result_id();
|
||||||
|
yValueId = x->result_id();
|
||||||
|
} else if (doSurfaceRotate180) {
|
||||||
|
auto* negX = builder.AddUnaryOp(target.floatTypeId, spv::Op::OpFNegate, xValueId);
|
||||||
|
auto* negY = builder.AddUnaryOp(target.floatTypeId, spv::Op::OpFNegate, yValueId);
|
||||||
|
if (!negX || !negY) return false;
|
||||||
|
xValueId = negX->result_id();
|
||||||
|
yValueId = negY->result_id();
|
||||||
|
} else if (doSurfaceRotate270) {
|
||||||
|
auto* negX = builder.AddUnaryOp(target.floatTypeId, spv::Op::OpFNegate, xValueId);
|
||||||
|
if (!negX) return false;
|
||||||
|
xValueId = yValueId;
|
||||||
|
yValueId = negX->result_id();
|
||||||
|
}
|
||||||
|
|
||||||
Uint32 zValueId = z->result_id();
|
Uint32 zValueId = z->result_id();
|
||||||
if (doZRemap) {
|
if (doZRemap) {
|
||||||
auto* zPlusW = builder.AddBinaryOp(target.floatTypeId, spv::Op::OpFAdd, z->result_id(), w->result_id());
|
auto* zPlusW = builder.AddBinaryOp(target.floatTypeId, spv::Op::OpFAdd, z->result_id(), w->result_id());
|
||||||
@@ -177,7 +199,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto* fixedPosition = builder.AddCompositeConstruct(target.vectorTypeId,
|
auto* fixedPosition = builder.AddCompositeConstruct(target.vectorTypeId,
|
||||||
{x->result_id(), yValueId, zValueId, w->result_id()});
|
{xValueId, yValueId, zValueId, w->result_id()});
|
||||||
if (!fixedPosition) return false;
|
if (!fixedPosition) return false;
|
||||||
|
|
||||||
return builder.AddStore(positionPtrId, fixedPosition->result_id()) != nullptr;
|
return builder.AddStore(positionPtrId, fixedPosition->result_id()) != nullptr;
|
||||||
@@ -205,6 +227,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
const Bool doYFlip = (m_transformFlags & ProgramFactory::CompileOptionBit::PositionYFlip);
|
const Bool doYFlip = (m_transformFlags & ProgramFactory::CompileOptionBit::PositionYFlip);
|
||||||
const Bool doZRemap = (m_transformFlags & ProgramFactory::CompileOptionBit::PositionZRemap);
|
const Bool doZRemap = (m_transformFlags & ProgramFactory::CompileOptionBit::PositionZRemap);
|
||||||
|
const Bool doSurfaceRotate90 = (m_transformFlags & ProgramFactory::CompileOptionBit::SurfaceRotate90);
|
||||||
|
const Bool doSurfaceRotate180 =
|
||||||
|
(m_transformFlags & ProgramFactory::CompileOptionBit::SurfaceRotate180);
|
||||||
|
const Bool doSurfaceRotate270 =
|
||||||
|
(m_transformFlags & ProgramFactory::CompileOptionBit::SurfaceRotate270);
|
||||||
|
|
||||||
Bool modified = false;
|
Bool modified = false;
|
||||||
for (auto& entryPoint : get_module()->entry_points()) {
|
for (auto& entryPoint : get_module()->entry_points()) {
|
||||||
@@ -228,7 +255,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
(model != spv::ExecutionModel::Geometry && inst->opcode() == spv::Op::OpReturn);
|
(model != spv::ExecutionModel::Geometry && inst->opcode() == spv::Op::OpReturn);
|
||||||
if (!needsFixup) continue;
|
if (!needsFixup) continue;
|
||||||
|
|
||||||
modified |= InsertPositionFixup(context(), inst, target, halfConstId, doYFlip, doZRemap);
|
modified |= InsertPositionFixup(context(), inst, target, halfConstId, doYFlip, doZRemap,
|
||||||
|
doSurfaceRotate90, doSurfaceRotate180, doSurfaceRotate270);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
None = 0,
|
None = 0,
|
||||||
PositionYFlip = 1 << 0,
|
PositionYFlip = 1 << 0,
|
||||||
PositionZRemap = 1 << 1,
|
PositionZRemap = 1 << 1,
|
||||||
|
SurfaceRotate90 = 1 << 2,
|
||||||
|
SurfaceRotate180 = 1 << 3,
|
||||||
|
SurfaceRotate270 = 1 << 4,
|
||||||
};
|
};
|
||||||
using CompileOptionFlags = Flags<CompileOptionBit>;
|
using CompileOptionFlags = Flags<CompileOptionBit>;
|
||||||
using HashType = Uint64;
|
using HashType = Uint64;
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
m_surfaceFormat = {createInfo.imageFormat, createInfo.imageColorSpace};
|
m_surfaceFormat = {createInfo.imageFormat, createInfo.imageColorSpace};
|
||||||
m_extent = createInfo.imageExtent;
|
m_extent = createInfo.imageExtent;
|
||||||
|
m_preTransform = createInfo.preTransform;
|
||||||
|
|
||||||
VK_VERIFY(vkCreateSwapchainKHR(device, &createInfo, nullptr, &m_swapchain));
|
VK_VERIFY(vkCreateSwapchainKHR(device, &createInfo, nullptr, &m_swapchain));
|
||||||
|
|
||||||
@@ -202,6 +203,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
m_images.clear();
|
m_images.clear();
|
||||||
m_imageLayouts.clear();
|
m_imageLayouts.clear();
|
||||||
|
m_preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkImage SwapchainObject::GetImage(Uint32 index) const {
|
VkImage SwapchainObject::GetImage(Uint32 index) const {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkSwapchainKHR GetHandle() const { return m_swapchain; }
|
VkSwapchainKHR GetHandle() const { return m_swapchain; }
|
||||||
const VkSurfaceFormatKHR& GetSurfaceFormat() const { return m_surfaceFormat; }
|
const VkSurfaceFormatKHR& GetSurfaceFormat() const { return m_surfaceFormat; }
|
||||||
VkExtent2D GetExtent() const { return m_extent; }
|
VkExtent2D GetExtent() const { return m_extent; }
|
||||||
|
VkSurfaceTransformFlagBitsKHR GetPreTransform() const { return m_preTransform; }
|
||||||
const Vector<VkImage>& GetImages() const { return m_images; }
|
const Vector<VkImage>& GetImages() const { return m_images; }
|
||||||
const Vector<VkImageView>& GetImageViews() const { return m_imageViews; }
|
const Vector<VkImageView>& GetImageViews() const { return m_imageViews; }
|
||||||
VkImage GetImage(Uint32 index) const;
|
VkImage GetImage(Uint32 index) const;
|
||||||
@@ -54,6 +55,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
|
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
|
||||||
VkSurfaceFormatKHR m_surfaceFormat{};
|
VkSurfaceFormatKHR m_surfaceFormat{};
|
||||||
VkExtent2D m_extent{};
|
VkExtent2D m_extent{};
|
||||||
|
VkSurfaceTransformFlagBitsKHR m_preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||||
Vector<VkImage> m_images;
|
Vector<VkImage> m_images;
|
||||||
Vector<VkImageView> m_imageViews;
|
Vector<VkImageView> m_imageViews;
|
||||||
Vector<VkImageLayout> m_imageLayouts;
|
Vector<VkImageLayout> m_imageLayouts;
|
||||||
|
|||||||
@@ -62,12 +62,25 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Shutdown();
|
Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ProgramFactory::CompileOptionFlags GetShaderTransformFlags() {
|
inline ProgramFactory::CompileOptionFlags GetShaderTransformFlags(VkSurfaceTransformFlagBitsKHR preTransform) {
|
||||||
ProgramFactory::CompileOptionFlags flags = ProgramFactory::CompileOptionBit::PositionZRemap;
|
ProgramFactory::CompileOptionFlags flags = ProgramFactory::CompileOptionBit::PositionZRemap;
|
||||||
const auto& currentDrawFBO =
|
const auto& currentDrawFBO =
|
||||||
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||||
if (currentDrawFBO == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO) {
|
if (currentDrawFBO == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO) {
|
||||||
flags |= ProgramFactory::CompileOptionBit::PositionYFlip;
|
flags |= ProgramFactory::CompileOptionBit::PositionYFlip;
|
||||||
|
switch (preTransform) {
|
||||||
|
case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
|
||||||
|
flags |= ProgramFactory::CompileOptionBit::SurfaceRotate90;
|
||||||
|
break;
|
||||||
|
case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
|
||||||
|
flags |= ProgramFactory::CompileOptionBit::SurfaceRotate180;
|
||||||
|
break;
|
||||||
|
case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
|
||||||
|
flags |= ProgramFactory::CompileOptionBit::SurfaceRotate270;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
@@ -77,7 +90,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
const VkPipelineVertexInputStateCreateInfo& vertexInputState) {
|
const VkPipelineVertexInputStateCreateInfo& vertexInputState) {
|
||||||
MOBILEGL_ASSERT(m_pipelineFactory != nullptr, "PipelineFactory is not initialized");
|
MOBILEGL_ASSERT(m_pipelineFactory != nullptr, "PipelineFactory is not initialized");
|
||||||
MOBILEGL_ASSERT(m_programFactory != nullptr, "ProgramFactory is not initialized");
|
MOBILEGL_ASSERT(m_programFactory != nullptr, "ProgramFactory is not initialized");
|
||||||
ProgramFactory::CompileOptionFlags transformFlags = GetShaderTransformFlags();
|
ProgramFactory::CompileOptionFlags transformFlags = GetShaderTransformFlags(m_swapchainObject.GetPreTransform());
|
||||||
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");
|
||||||
|
|||||||
Reference in New Issue
Block a user