CLEAR_DEPTH_BUFFER = 1 << 19,
SET_STENCIL_TEST_ENABLE = 1 << 20,
SET_STENCIL_WRITE_MASK = 1 << 21,
- SET_STENCIL_OP = 1 << 22,
- SET_STENCIL_FUNC = 1 << 23,
- SET_DEPTH_COMPARE_OP = 1 << 24,
- SET_DEPTH_TEST_ENABLE = 1 << 25,
- SET_DEPTH_WRITE_ENABLE = 1 << 26,
- DRAW_NATIVE = 1 << 27,
- BEGIN = 1 << 28,
- END = 1 << 29
+ SET_STENCIL_STATE = 1 << 22,
+ SET_DEPTH_COMPARE_OP = 1 << 23,
+ SET_DEPTH_TEST_ENABLE = 1 << 24,
+ SET_DEPTH_WRITE_ENABLE = 1 << 25,
+ DRAW_NATIVE = 1 << 26,
+ BEGIN = 1 << 27,
+ END = 1 << 28
};
std::ostream& operator<<(std::ostream& os, Graphics::StencilOp op);
data.stencilTest.enabled = rhs.data.stencilTest.enabled;
break;
}
- case CommandType::SET_STENCIL_FUNC:
- {
- data.stencilFunc.compareMask = rhs.data.stencilFunc.compareMask;
- data.stencilFunc.compareOp = rhs.data.stencilFunc.compareOp;
- data.stencilFunc.reference = rhs.data.stencilFunc.reference;
- break;
- }
case CommandType::SET_STENCIL_WRITE_MASK:
{
data.stencilWriteMask.mask = rhs.data.stencilWriteMask.mask;
break;
}
- case CommandType::SET_STENCIL_OP:
+ case CommandType::SET_STENCIL_STATE:
{
- data.stencilOp.failOp = rhs.data.stencilOp.failOp;
- data.stencilOp.depthFailOp = rhs.data.stencilOp.depthFailOp;
- data.stencilOp.passOp = rhs.data.stencilOp.passOp;
+ data.stencilState.compareMask = rhs.data.stencilState.compareMask;
+ data.stencilState.compareOp = rhs.data.stencilState.compareOp;
+ data.stencilState.reference = rhs.data.stencilState.reference;
+ data.stencilState.failOp = rhs.data.stencilState.failOp;
+ data.stencilState.depthFailOp = rhs.data.stencilState.depthFailOp;
+ data.stencilState.passOp = rhs.data.stencilState.passOp;
break;
}
data.stencilWriteMask.mask = rhs.data.stencilWriteMask.mask;
break;
}
- case CommandType::SET_STENCIL_OP:
- {
- data.stencilOp.failOp = rhs.data.stencilOp.failOp;
- data.stencilOp.depthFailOp = rhs.data.stencilOp.depthFailOp;
- data.stencilOp.passOp = rhs.data.stencilOp.passOp;
- break;
- }
- case CommandType::SET_STENCIL_FUNC:
+ case CommandType::SET_STENCIL_STATE:
{
- data.stencilFunc.compareMask = rhs.data.stencilFunc.compareMask;
- data.stencilFunc.compareOp = rhs.data.stencilFunc.compareOp;
- data.stencilFunc.reference = rhs.data.stencilFunc.reference;
+ data.stencilState.failOp = rhs.data.stencilState.failOp;
+ data.stencilState.depthFailOp = rhs.data.stencilState.depthFailOp;
+ data.stencilState.passOp = rhs.data.stencilState.passOp;
+ data.stencilState.compareMask = rhs.data.stencilState.compareMask;
+ data.stencilState.compareOp = rhs.data.stencilState.compareOp;
+ data.stencilState.reference = rhs.data.stencilState.reference;
break;
}
case CommandType::SET_DEPTH_COMPARE_OP:
Graphics::StencilOp failOp;
Graphics::StencilOp passOp;
Graphics::StencilOp depthFailOp;
- } stencilOp;
+ uint32_t compareMask;
+ Graphics::CompareOp compareOp;
+ uint32_t reference;
+ } stencilState;
struct
{
uint32_t mask;
} stencilWriteMask;
- struct
- {
- uint32_t compareMask;
- Graphics::CompareOp compareOp;
- uint32_t reference;
- } stencilFunc;
-
struct
{
bool enabled;
mCommands.back().data.stencilWriteMask.mask = writeMask;
}
- void SetStencilOp(Graphics::StencilOp failOp,
- Graphics::StencilOp passOp,
- Graphics::StencilOp depthFailOp) override
+ void SetStencilState(Graphics::CompareOp compareOp,
+ uint32_t reference,
+ uint32_t compareMask,
+ Graphics::StencilOp failOp,
+ Graphics::StencilOp passOp,
+ Graphics::StencilOp depthFailOp) override
{
TraceCallStack::NamedParams params;
params["failOp"] << failOp;
params["passOp"] << passOp;
params["depthFailOp"] << depthFailOp;
- mCallStack.PushCall("SetStencilOp", params.str(), params);
- mCommands.emplace_back();
- mCommands.back().type = CommandType::SET_STENCIL_OP;
- mCommands.back().data.stencilOp.failOp = failOp;
- mCommands.back().data.stencilOp.passOp = passOp;
- mCommands.back().data.stencilOp.depthFailOp = depthFailOp;
- }
-
- void SetStencilFunc(Graphics::CompareOp compareOp,
- uint32_t reference,
- uint32_t compareMask) override
- {
- TraceCallStack::NamedParams params;
params["compareOp"] << compareOp;
params["compareMask"] << std::hex << compareMask;
params["reference"] << std::hex << reference;
- mCallStack.PushCall("SetStencilFunc", params.str(), params);
-
+ mCallStack.PushCall("SetStencilState", params.str(), params);
mCommands.emplace_back();
- mCommands.back().type = CommandType::SET_STENCIL_FUNC;
-
- mCommands.back().data.stencilFunc.compareOp = compareOp;
- mCommands.back().data.stencilFunc.compareMask = compareMask;
- mCommands.back().data.stencilFunc.reference = reference;
+ mCommands.back().type = CommandType::SET_STENCIL_STATE;
+ mCommands.back().data.stencilState.failOp = failOp;
+ mCommands.back().data.stencilState.passOp = passOp;
+ mCommands.back().data.stencilState.depthFailOp = depthFailOp;
+ mCommands.back().data.stencilState.compareOp = compareOp;
+ mCommands.back().data.stencilState.compareMask = compareMask;
+ mCommands.back().data.stencilState.reference = reference;
}
void SetDepthCompareOp(Graphics::CompareOp compareOp) override
break;
}
- case CommandType::SET_STENCIL_FUNC:
- {
- mGl.StencilFunc(GLCompareOp(cmd.data.stencilFunc.compareOp).op,
- cmd.data.stencilFunc.reference,
- cmd.data.stencilFunc.compareMask);
- break;
- }
-
case CommandType::SET_STENCIL_WRITE_MASK:
{
mGl.StencilMask(cmd.data.stencilWriteMask.mask);
break;
}
- case CommandType::SET_STENCIL_OP:
+ case CommandType::SET_STENCIL_STATE:
{
- mGl.StencilOp(GLStencilOp(cmd.data.stencilOp.failOp).op,
- GLStencilOp(cmd.data.stencilOp.depthFailOp).op,
- GLStencilOp(cmd.data.stencilOp.passOp).op);
+ mGl.StencilFunc(GLCompareOp(cmd.data.stencilState.compareOp).op,
+ cmd.data.stencilState.reference,
+ cmd.data.stencilState.compareMask);
+ mGl.StencilOp(GLStencilOp(cmd.data.stencilState.failOp).op,
+ GLStencilOp(cmd.data.stencilState.depthFailOp).op,
+ GLStencilOp(cmd.data.stencilState.passOp).op);
break;
}
mGl.GenerateMipmap(gfxTexture->GetTarget());
}
-bool TestGraphicsController::EnableDepthStencilBuffer(bool enableDepth, bool enableStencil)
+bool TestGraphicsController::EnableDepthStencilBuffer(const Graphics::RenderTarget& renderTarget,
+ bool enableDepth,
+ bool enableStencil)
{
TraceCallStack::NamedParams namedParams;
namedParams["enableDepth"] << (enableDepth ? "T" : "F");
namedParams["enableStencil"] << (enableStencil ? "T" : "F");
- mCallStack.PushCall("EnableDepthStencilBuffer", "", namedParams);
- return false;
+ mCallStack.PushCall("EnableDepthStencilBuffer", namedParams.str(), namedParams);
+ return true;
}
void TestGraphicsController::RunGarbageCollector(size_t numberOfDiscardedRenderers)
*/
void GenerateTextureMipmaps(const Graphics::Texture& texture) override;
- /**
- * TBD: do we need those functions in the new implementation?
- */
- bool EnableDepthStencilBuffer(bool enableDepth, bool enableStencil) override;
+ bool EnableDepthStencilBuffer(const Graphics::RenderTarget& surface, bool enableDepth, bool enableStencil) override;
void RunGarbageCollector(size_t numberOfDiscardedRenderers) override;
SET(TC_SOURCES
utc-Dali-VkGraphicsBuffer.cpp
+ utc-Dali-VkClipMatrix.cpp
)
SET(TC_SOURCE_LIST ${TC_SOURCES} CACHE STRING "List of test sources")
--- /dev/null
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-test-suite-utils.h>
+#include <dali/dali.h>
+
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
+#include <test-actor-utils.h>
+#include <test-graphics-framebuffer.h>
+#include <test-graphics-vk-application.h>
+
+using namespace Dali;
+
+namespace
+{
+} // namespace
+
+int UtcDaliClipMatrix01(void)
+{
+ TestGraphicsApplication app;
+ tet_infoline("UtcDaliClipMatrix01 Test that various points in clip space are mapped properly");
+
+ auto& controller = app.GetGraphicsController();
+
+ // GL clip space:
+ // Y up, x/y range: -1:1 z range -1:1
+ //
+ // Vulkan clip space:
+ // Y down, x/y range: -1:1, z range 0:1
+
+ const Vector3 testPoints[] = {Vector3(0.f, 0.f, 0.f),
+ Vector3(-1.f, 0.f, 0.f),
+ Vector3(1.f, 0.f, 0.f),
+ Vector3(0.f, -1.f, 0.f),
+ Vector3(0.f, 1.f, 0.f),
+ Vector3(0.f, 0.f, -1.f),
+ Vector3(0.f, 0.f, 1.f),
+ Vector3(0.2f, 0.2f, 0.2f)};
+
+ const Vector3 resultPoints[] = {Vector3(0.f, 0.0f, 0.5f),
+ Vector3(-1.f, 0.f, 0.5f),
+ Vector3(1.f, 0.f, 0.5f),
+ Vector3(0.f, 1.f, 0.5f),
+ Vector3(0.f, -1.f, 0.5f),
+ Vector3(0.f, 0.f, 0.0f),
+ Vector3(0.f, 0.f, 1.f),
+ Vector3(0.2f, -0.2f, 0.6f)};
+
+ const int numTests = sizeof(testPoints) / sizeof(Vector3);
+
+ DALI_TEST_EQUALS(controller.HasClipMatrix(), true, TEST_LOCATION);
+ const Matrix& clipMatrix = controller.GetClipMatrix();
+
+ for(int i = 0; i < numTests; ++i)
+ {
+ auto testVec = Vector4(testPoints[i].x, testPoints[i].y, testPoints[i].z, 1.0f);
+ auto resultVec = Vector4(resultPoints[i].x, resultPoints[i].y, resultPoints[i].z, 1.0f);
+
+ auto outVec = clipMatrix * testVec;
+ tet_printf(
+ "In Vec: (%3.1f, %3.1f, %3.1f) => Out vec: (%3.1f, %3.1f, %3.1f)\n"
+ " Expected: (%3.1f, %3.1f, %3.1f) %s\n",
+ testPoints[i].x,
+ testPoints[i].y,
+ testPoints[i].z,
+ outVec.x,
+ outVec.y,
+ outVec.z,
+ resultVec.x,
+ resultVec.y,
+ resultVec.z,
+ resultVec == outVec ? "PASS" : "FAIL");
+ DALI_TEST_EQUALS(outVec, resultVec, TEST_LOCATION);
+ }
+
+ END_TEST;
+}
break;
}
- case GLES::CommandType::SET_STENCIL_FUNC:
+ case GLES::CommandType::SET_STENCIL_STATE:
{
fprintf(output,
- "{\"Cmd\":\"STENCIL_FUNC\",\n"
+ "{\"Cmd\":\"STENCIL_STATE\",\n"
"\"compareOp\":\"%s\",\n"
"\"reference\":\"0x%x\",\n"
- "\"compareMask\":\"0x%x\"\n}",
- DumpCompareOp(cmd.stencilFunc.compareOp).c_str(),
- cmd.stencilFunc.reference,
- cmd.stencilFunc.compareMask);
+ "\"compareMask\":\"0x%x\"\n"
+ "\"failOp\":\"%s\",\n"
+ "\"depthFailOp\":\"%s\",\n"
+ "\"passOp\":\"%s\"\n}",
+ DumpCompareOp(cmd.stencilState.compareOp).c_str(),
+ cmd.stencilState.reference,
+ cmd.stencilState.compareMask,
+ DumpStencilOp(cmd.stencilState.failOp).c_str(),
+ DumpStencilOp(cmd.stencilState.depthFailOp).c_str(),
+ DumpStencilOp(cmd.stencilState.passOp).c_str());
break;
}
break;
}
- case GLES::CommandType::SET_STENCIL_OP:
- {
- fprintf(output,
- "{\"Cmd\":\"SET_STENCIL_OP\",\n"
- "\"failOp\":\"%s\",\n"
- "\"depthFailOp\":\"%s\",\n"
- "\"passOp\":\"%s\"\n}",
-
- DumpStencilOp(cmd.stencilOp.failOp).c_str(),
- DumpStencilOp(cmd.stencilOp.depthFailOp).c_str(),
- DumpStencilOp(cmd.stencilOp.passOp).c_str());
- break;
- }
-
case GLES::CommandType::SET_DEPTH_COMPARE_OP:
{
fprintf(output,
break;
}
- case GLES::CommandType::SET_STENCIL_FUNC:
+ case GLES::CommandType::SET_STENCIL_STATE:
{
- mCurrentContext->StencilFunc(cmd.stencilFunc.compareOp,
- cmd.stencilFunc.reference,
- cmd.stencilFunc.compareMask);
+ mCurrentContext->StencilFunc(cmd.stencilState.compareOp,
+ cmd.stencilState.reference,
+ cmd.stencilState.compareMask);
+ mCurrentContext->StencilOp(cmd.stencilState.failOp,
+ cmd.stencilState.depthFailOp,
+ cmd.stencilState.passOp);
break;
}
break;
}
- case GLES::CommandType::SET_STENCIL_OP:
- {
- mCurrentContext->StencilOp(cmd.stencilOp.failOp,
- cmd.stencilOp.depthFailOp,
- cmd.stencilOp.passOp);
- break;
- }
-
case GLES::CommandType::SET_DEPTH_COMPARE_OP:
{
mCurrentContext->SetDepthCompareOp(cmd.depth.compareOp);
/**
* @copydoc Dali::Graphics::EnableDepthStencilBuffer()
*/
- bool EnableDepthStencilBuffer(bool enableDepth, bool enableStencil) override
+ bool EnableDepthStencilBuffer(const Graphics::RenderTarget& renderTarget, bool enableDepth, bool enableStencil) override
{
return {};
}
command->stencilWriteMask.mask = writeMask;
}
-void CommandBuffer::SetStencilOp(Graphics::StencilOp failOp,
- Graphics::StencilOp passOp,
- Graphics::StencilOp depthFailOp)
-{
- auto command = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_OP);
- auto& cmd = command->stencilOp;
+void CommandBuffer::SetStencilState(Graphics::CompareOp compareOp,
+ uint32_t reference,
+ uint32_t compareMask,
+ Graphics::StencilOp failOp,
+ Graphics::StencilOp passOp,
+ Graphics::StencilOp depthFailOp)
+{
+ auto command = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_STATE);
+ auto& cmd = command->stencilState;
cmd.failOp = failOp;
cmd.passOp = passOp;
cmd.depthFailOp = depthFailOp;
-}
-
-void CommandBuffer::SetStencilFunc(Graphics::CompareOp compareOp,
- uint32_t reference,
- uint32_t compareMask)
-{
- auto command = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_FUNC);
- auto& cmd = command->stencilFunc;
cmd.compareOp = compareOp;
cmd.compareMask = compareMask;
cmd.reference = reference;
CLEAR_DEPTH_BUFFER,
SET_STENCIL_TEST_ENABLE,
SET_STENCIL_WRITE_MASK,
- SET_STENCIL_OP,
- SET_STENCIL_FUNC,
+ SET_STENCIL_STATE,
SET_DEPTH_COMPARE_OP,
SET_DEPTH_TEST_ENABLE,
SET_DEPTH_WRITE_ENABLE,
bool writeEnabled;
} depth;
- struct
- {
- Graphics::StencilOp failOp;
- Graphics::StencilOp passOp;
- Graphics::StencilOp depthFailOp;
- } stencilOp;
-
struct
{
uint32_t mask;
struct
{
- uint32_t compareMask;
Graphics::CompareOp compareOp;
+ uint32_t compareMask;
uint32_t reference;
- } stencilFunc;
+
+ Graphics::StencilOp failOp;
+ Graphics::StencilOp passOp;
+ Graphics::StencilOp depthFailOp;
+ } stencilState;
struct
{
void SetStencilWriteMask(uint32_t writeMask) override;
/**
- * @copydoc Dali::Graphics::CommandBuffer::SetStencilOp
- */
- void SetStencilOp(Graphics::StencilOp failOp,
- Graphics::StencilOp passOp,
- Graphics::StencilOp depthFailOp) override;
-
- /**
- * @copydoc Dali::Graphics::CommandBuffer::SetStencilFunc
+ * @copydoc Dali::Graphics::CommandBuffer::SetStencilState
*/
- void SetStencilFunc(Graphics::CompareOp compareOp,
- uint32_t reference,
- uint32_t compareMask) override;
+ void SetStencilState(Graphics::CompareOp compareOp,
+ uint32_t reference,
+ uint32_t compareMask,
+ Graphics::StencilOp failOp,
+ Graphics::StencilOp passOp,
+ Graphics::StencilOp depthFailOp) override;
/**
* @copydoc Dali::Graphics::CommandBuffer::SetDepthCompareOp
mCommandBuffer.setViewport(0, 1, reinterpret_cast<vk::Viewport*>(&value));
}
+void CommandBufferImpl::SetStencilTestEnable(bool stencilEnable)
+{
+ mCommandBuffer.setStencilTestEnable(stencilEnable);
+ if(!stencilEnable)
+ {
+ mCommandBuffer.setStencilWriteMask(vk::StencilFaceFlagBits::eFrontAndBack, 0x00);
+ mCommandBuffer.setStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack, 0x00);
+ mCommandBuffer.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack, 0x00);
+ mCommandBuffer.setStencilOp(vk::StencilFaceFlagBits::eFrontAndBack, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eLess);
+ }
+}
+
+void CommandBufferImpl::SetStencilWriteMask(vk::StencilFaceFlags faceMask, uint32_t writeMask)
+{
+ mCommandBuffer.setStencilWriteMask(faceMask, writeMask);
+}
+
+void CommandBufferImpl::SetStencilCompareMask(vk::StencilFaceFlags faceMask, uint32_t compareMask)
+{
+ mCommandBuffer.setStencilCompareMask(faceMask, compareMask);
+}
+
+void CommandBufferImpl::SetStencilReference(vk::StencilFaceFlags faceMask, uint32_t reference)
+{
+ mCommandBuffer.setStencilReference(faceMask, reference);
+}
+
+void CommandBufferImpl::SetStencilOp(vk::StencilFaceFlags faceMask, vk::StencilOp failOp, vk::StencilOp passOp, vk::StencilOp depthFailOp, vk::CompareOp compareOp)
+{
+ mCommandBuffer.setStencilOp(faceMask, failOp, passOp, depthFailOp, compareOp);
+}
+
+void CommandBufferImpl::SetDepthTestEnable(bool depthTestEnable)
+{
+ mCommandBuffer.setDepthTestEnable(depthTestEnable);
+ mCommandBuffer.setDepthBoundsTestEnable(false);
+ mCommandBuffer.setDepthBounds(0.0f, 1.0f);
+}
+
+void CommandBufferImpl::SetDepthWriteEnable(bool depthWriteEnable)
+{
+ mCommandBuffer.setDepthWriteEnable(depthWriteEnable);
+}
+
+void CommandBufferImpl::SetDepthCompareOp(vk::CompareOp op)
+{
+ mCommandBuffer.setDepthCompareOp(op);
+}
+
void CommandBufferImpl::BindResources(vk::DescriptorSet descriptorSet)
{
std::vector<vk::DescriptorImageInfo> imageInfos;
void SetScissor(Rect2D value);
void SetViewport(Viewport value);
+ void SetStencilTestEnable(bool stencilEnable);
+ void SetStencilWriteMask(vk::StencilFaceFlags faceMask, uint32_t writeMask);
+ void SetStencilCompareMask(vk::StencilFaceFlags faceMask, uint32_t compareMask);
+ void SetStencilReference(vk::StencilFaceFlags faceMask, uint32_t reference);
+ void SetStencilOp(vk::StencilFaceFlags faceMask, vk::StencilOp failOp, vk::StencilOp passOp, vk::StencilOp depthFailOp, vk::CompareOp compareOp);
+
+ void SetDepthTestEnable(bool depthTestEnable);
+ void SetDepthWriteEnable(bool depthWriteEnable);
+ void SetDepthCompareOp(vk::CompareOp compareOp);
+
void Draw(
uint32_t vertexCount,
uint32_t instanceCount,
void CommandBuffer::ClearStencilBuffer()
{
+ // Ignore, we should only do this in render pass
}
void CommandBuffer::ClearDepthBuffer()
{
+ // Ignore, we should only do this in render pass
}
void CommandBuffer::SetStencilTestEnable(bool stencilEnable)
{
+ mCommandBufferImpl->SetStencilTestEnable(stencilEnable);
}
void CommandBuffer::SetStencilWriteMask(uint32_t writeMask)
{
+ mCommandBufferImpl->SetStencilWriteMask(vk::StencilFaceFlagBits::eFrontAndBack, writeMask);
}
-void CommandBuffer::SetStencilFunc(Graphics::CompareOp compareOp,
- uint32_t reference,
- uint32_t compareMask)
-{
-}
-
-void CommandBuffer::SetStencilOp(Graphics::StencilOp failOp,
- Graphics::StencilOp passOp,
- Graphics::StencilOp depthFailOp)
+void CommandBuffer::SetStencilState(Graphics::CompareOp compareOp,
+ uint32_t reference,
+ uint32_t compareMask,
+ Graphics::StencilOp failOp,
+ Graphics::StencilOp passOp,
+ Graphics::StencilOp depthFailOp)
{
+ mCommandBufferImpl->SetStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack, compareMask);
+ mCommandBufferImpl->SetStencilReference(vk::StencilFaceFlagBits::eFrontAndBack, reference);
+ mCommandBufferImpl->SetStencilOp(vk::StencilFaceFlagBits::eFrontAndBack,
+ VkStencilOpType(failOp).op,
+ VkStencilOpType(passOp).op,
+ VkStencilOpType(depthFailOp).op,
+ VkCompareOpType(compareOp).op);
}
void CommandBuffer::SetDepthCompareOp(Graphics::CompareOp compareOp)
{
+ // @todo Invert comparison
+ // This makes depth test work, but implies that the conversion to NDC has the wrong sense.
+ vk::CompareOp depthOp;
+ switch(compareOp)
+ {
+ case Graphics::CompareOp::NEVER:
+ case Graphics::CompareOp::EQUAL:
+ case Graphics::CompareOp::NOT_EQUAL:
+ case Graphics::CompareOp::ALWAYS:
+ {
+ depthOp = VkCompareOpType(compareOp).op;
+ break;
+ }
+ case Graphics::CompareOp::LESS:
+ {
+ depthOp = vk::CompareOp::eGreaterOrEqual;
+ break;
+ }
+ case Graphics::CompareOp::LESS_OR_EQUAL:
+ {
+ depthOp = vk::CompareOp::eGreater;
+ break;
+ }
+ case Graphics::CompareOp::GREATER:
+ {
+ depthOp = vk::CompareOp::eLessOrEqual;
+ break;
+ }
+ case Graphics::CompareOp::GREATER_OR_EQUAL:
+ {
+ depthOp = vk::CompareOp::eLess;
+ break;
+ }
+ }
+ depthOp = VkCompareOpType(compareOp).op;
+ mCommandBufferImpl->SetDepthCompareOp(depthOp);
}
void CommandBuffer::SetDepthTestEnable(bool depthTestEnable)
{
+ mCommandBufferImpl->SetDepthTestEnable(depthTestEnable);
}
void CommandBuffer::SetDepthWriteEnable(bool depthWriteEnable)
{
+ mCommandBufferImpl->SetDepthWriteEnable(depthWriteEnable);
}
Swapchain* CommandBuffer::GetLastSwapchain() const
void SetStencilWriteMask(uint32_t writeMask) override;
/**
- * @brief Setup the stencil function
+ * @brief Setup the stencil function and how subsequent draws will affect the stencil buffer.
*
- * @param[in] compareOp How the stencil buffer, reference and compareMask are combined to determine whether to draw a pixel or not.
- * @param[in] reference A reference value that is ANDed with the mask in the compare op.
- * @param[in] compareMask The bitplanes from the stencil buffer that are active.
- */
- void SetStencilFunc(Graphics::CompareOp compareOp,
- uint32_t reference,
- uint32_t compareMask) override;
-
- /**
- * @brief Set how subsequent draws will affect the stencil buffer.
* @param[in] failOp What happens to stencil buffer if drawing a pixel fails the stencil test
* @param[in] passOp What happens to stencil buffer if drawing a pixel passes stencil & depth test
* @param[in] depthFailOp What happens to stencil buffer if drawing a pixel passes stencil but fails depth test.
+ * @param[in] compareOp How the stencil buffer, reference and compareMask are combined to determine whether to draw a pixel or not.
+ * @param[in] reference A reference value that is ANDed with the mask in the compare op.
+ * @param[in] compareMask The bitplanes from the stencil buffer that are active.
*/
- void SetStencilOp(Graphics::StencilOp failOp,
- Graphics::StencilOp passOp,
- Graphics::StencilOp depthFailOp) override;
+ void SetStencilState(Graphics::CompareOp compareOp,
+ uint32_t reference,
+ uint32_t compareMask,
+ Graphics::StencilOp failOp,
+ Graphics::StencilOp passOp,
+ Graphics::StencilOp depthFailOp) override;
/**
* @brief Defines the comparison operator for passing the depth test.
--- /dev/null
+#ifndef DALI_GRAPHICS_VULKAN_FRAMEBUFFER_ATTACHMENT_H
+#define DALI_GRAPHICS_VULKAN_FRAMEBUFFER_ATTACHMENT_H
+
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/internal/graphics/vulkan-impl/vulkan-handle.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-types.h>
+
+namespace Dali::Graphics::Vulkan
+{
+class ImageView;
+
+enum class AttachmentType
+{
+ COLOR,
+ DEPTH_STENCIL,
+ INPUT,
+ RESOLVE,
+ PRESERVE,
+ UNDEFINED
+};
+
+class FramebufferAttachment : public VkSharedResource
+{
+public:
+ /**
+ * Constructor
+ *
+ * @param[in] imageView The imageview of the attachment
+ * @param[in] clearColor The color used to clear this attachment during CLEAR_OP
+ * @param[in] type The attachment type (usually COLOR or DEPTH_STENCIL)
+ * @param[in] presentable Whether the attachment is presentable (changes final layout)
+ */
+ FramebufferAttachment(std::unique_ptr<ImageView>& imageView,
+ vk::ClearValue clearColor,
+ AttachmentType type,
+ bool presentable);
+
+ /**
+ * Creates a new color attachment.
+ *
+ * @param[in] imageView The imageview of the attachment
+ * @param[in] clearColorValue The color used to clear this attachment during CLEAR_OP
+ * @param[in] presentable Whether the attachment is presentable (changes final layout)
+ */
+ static FramebufferAttachment* NewColorAttachment(std::unique_ptr<ImageView>& imageView,
+ vk::ClearColorValue clearColorValue,
+ bool presentable);
+
+ /**
+ * Creates a new depth attachment.
+ *
+ * @param[in] imageView The imageview of the attachment
+ * @param[in] clearDepthStencilValue The value used to clear this attachment during CLEAR_OP
+ */
+ static FramebufferAttachment* NewDepthAttachment(std::unique_ptr<ImageView>& imageView,
+ vk::ClearDepthStencilValue clearDepthStencilValue);
+
+ [[nodiscard]] ImageView* GetImageView() const;
+
+ [[nodiscard]] const vk::AttachmentDescription& GetDescription() const;
+
+ [[nodiscard]] const vk::ClearValue& GetClearValue() const;
+
+ [[nodiscard]] AttachmentType GetType() const;
+
+ [[nodiscard]] bool IsValid() const;
+
+private:
+ FramebufferAttachment() = default;
+
+ std::unique_ptr<ImageView> mImageView;
+ vk::AttachmentDescription mDescription;
+ vk::ClearValue mClearValue;
+ AttachmentType mType{AttachmentType::UNDEFINED};
+};
+
+using FramebufferAttachmentHandle = Vulkan::Handle<FramebufferAttachment>; // Can share attachments
+using SharedAttachments = std::vector<FramebufferAttachmentHandle>;
+
+} // namespace Dali::Graphics::Vulkan
+
+#endif // DALI_GRAPHICS_VULKAN_FRAMEBUFFER_ATTACHMENT_H
#include <dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-handle.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-image-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-image-view-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.h>
// FramebufferImpl -------------------------------
FramebufferImpl* FramebufferImpl::New(
- Vulkan::Device& device,
- RenderPassHandle renderPass,
- OwnedAttachments& attachments,
- uint32_t width,
- uint32_t height,
- bool hasDepthAttachments)
+ Vulkan::Device& device,
+ RenderPassHandle renderPass,
+ SharedAttachments& attachments,
+ uint32_t width,
+ uint32_t height,
+ bool hasDepthAttachments)
{
DALI_ASSERT_ALWAYS(renderPass && "You require more render passes!");
}
FramebufferImpl* FramebufferImpl::New(
- Vulkan::Device& device,
- RenderPassHandle renderPass,
- OwnedAttachments& colorAttachments,
- std::unique_ptr<FramebufferAttachment>& depthAttachment,
- uint32_t width,
- uint32_t height)
+ Vulkan::Device& device,
+ RenderPassHandle renderPass,
+ SharedAttachments& colorAttachments,
+ FramebufferAttachmentHandle depthAttachment,
+ uint32_t width,
+ uint32_t height)
{
assert((!colorAttachments.empty() || depthAttachment) && "Cannot create framebuffer. Please provide at least one attachment");
- auto colorAttachmentsValid = true;
- std::vector<FramebufferAttachment*> attachments;
+ auto colorAttachmentsValid = true;
+ SharedAttachments attachments;
for(auto& attachment : colorAttachments)
{
- attachments.emplace_back(attachment.get());
+ attachments.emplace_back(attachment);
if(!attachment->IsValid())
{
colorAttachmentsValid = false;
if(!renderPass)
{
// Create compatible vulkan render pass
- renderPass = RenderPassImpl::New(device, attachments, depthAttachment.get());
+ renderPass = RenderPassImpl::New(device, attachments, depthAttachment);
}
- OwnedAttachments ownedAttachments(std::move(colorAttachments));
if(hasDepth)
{
- ownedAttachments.emplace_back(std::move(depthAttachment));
+ attachments.emplace_back(std::move(depthAttachment));
}
- return FramebufferImpl::New(device, renderPass, ownedAttachments, width, height, hasDepth);
+ return FramebufferImpl::New(device, renderPass, attachments, width, height, hasDepth);
}
-FramebufferImpl::FramebufferImpl(Device& graphicsDevice,
- OwnedAttachments& attachments,
- vk::Framebuffer vkHandle,
- RenderPassHandle renderPassImpl,
- uint32_t width,
- uint32_t height,
- bool hasDepthAttachment)
+FramebufferImpl::FramebufferImpl(Device& graphicsDevice,
+ SharedAttachments& attachments,
+ vk::Framebuffer vkHandle,
+ RenderPassHandle renderPassImpl,
+ uint32_t width,
+ uint32_t height,
+ bool hasDepthAttachment)
: mGraphicsDevice(&graphicsDevice),
mWidth(width),
mHeight(height),
- mAttachments(std::move(attachments)),
+ mAttachments(attachments),
mFramebuffer(vkHandle),
mHasDepthAttachment(hasDepthAttachment)
{
return mHeight;
}
-FramebufferAttachment* FramebufferImpl::GetAttachment(AttachmentType type, uint32_t index) const
+FramebufferAttachmentHandle FramebufferImpl::GetAttachment(AttachmentType type, uint32_t index) const
{
switch(type)
{
case AttachmentType::COLOR:
{
- return mAttachments[index].get();
+ return mAttachments[index];
}
case AttachmentType::DEPTH_STENCIL:
{
if(mHasDepthAttachment)
{
- return mAttachments.back().get();
+ return mAttachments.back();
}
}
case AttachmentType::INPUT:
break;
}
- return nullptr;
+ return {};
}
-std::vector<FramebufferAttachment*> FramebufferImpl::GetAttachments(AttachmentType type) const
+SharedAttachments FramebufferImpl::GetAttachments(AttachmentType type) const
{
- auto retval = std::vector<FramebufferAttachment*>{};
+ auto retval = SharedAttachments{};
switch(type)
{
case AttachmentType::COLOR:
retval.reserve(numColorAttachments);
for(size_t i = 0; i < numColorAttachments; ++i)
{
- retval.emplace_back(mAttachments[i].get());
+ retval.emplace_back(&*mAttachments[i]);
}
break;
}
if(mHasDepthAttachment)
{
retval.reserve(1);
- retval.emplace_back(mAttachments.back().get());
+ retval.emplace_back(&*mAttachments.back());
}
break;
}
#include <dali/internal/graphics/vulkan-impl/vulkan-types.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-framebuffer-attachment.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-image-view-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.h>
namespace Dali::Graphics::Vulkan
{
class RenderPass;
-
-enum class AttachmentType
-{
- COLOR,
- DEPTH_STENCIL,
- INPUT,
- RESOLVE,
- PRESERVE,
- UNDEFINED
-};
-
class Device;
-class FramebufferAttachment
-{
-public:
- /**
- * Constructor
- *
- * @param[in] imageView The imageview of the attachment
- * @param[in] clearColor The color used to clear this attachment during CLEAR_OP
- * @param[in] type The attachment type (usually COLOR or DEPTH_STENCIL)
- * @param[in] presentable Whether the attachment is presentable (changes final layout)
- */
- FramebufferAttachment(std::unique_ptr<ImageView>& imageView,
- vk::ClearValue clearColor,
- AttachmentType type,
- bool presentable);
-
- /**
- * Creates a new color attachment.
- *
- * @param[in] imageView The imageview of the attachment
- * @param[in] clearColorValue The color used to clear this attachment during CLEAR_OP
- * @param[in] presentable Whether the attachment is presentable (changes final layout)
- */
- static FramebufferAttachment* NewColorAttachment(std::unique_ptr<ImageView>& imageView,
- vk::ClearColorValue clearColorValue,
- bool presentable);
-
- /**
- * Creates a new depth attachment.
- *
- * @param[in] imageView The imageview of the attachment
- * @param[in] clearDepthStencilValue The value used to clear this attachment during CLEAR_OP
- */
- static FramebufferAttachment* NewDepthAttachment(std::unique_ptr<ImageView>& imageView,
- vk::ClearDepthStencilValue clearDepthStencilValue);
-
- [[nodiscard]] ImageView* GetImageView() const;
-
- [[nodiscard]] const vk::AttachmentDescription& GetDescription() const;
-
- [[nodiscard]] const vk::ClearValue& GetClearValue() const;
-
- [[nodiscard]] AttachmentType GetType() const;
-
- [[nodiscard]] bool IsValid() const;
-
-private:
- FramebufferAttachment() = default;
-
- std::unique_ptr<ImageView> mImageView;
- vk::AttachmentDescription mDescription;
- vk::ClearValue mClearValue;
- AttachmentType mType{AttachmentType::UNDEFINED};
-};
-
-using OwnedAttachments = std::vector<std::unique_ptr<FramebufferAttachment>>;
-
/**
* FramebufferImpl encapsulates following objects:
* - Images ( attachments )
* @return A new framebuffer object
*/
static FramebufferImpl* New(
- Vulkan::Device& device,
- RenderPassHandle renderPass,
- OwnedAttachments& attachments,
- uint32_t width,
- uint32_t height,
- bool hasDepthAttachment);
+ Vulkan::Device& device,
+ RenderPassHandle renderPass,
+ SharedAttachments& attachments,
+ uint32_t width,
+ uint32_t height,
+ bool hasDepthAttachment);
/**
* @brief Create a new Framebuffer
* @return A new framebuffer object
*/
static FramebufferImpl* New(
- Vulkan::Device& device,
- RenderPassHandle renderPass,
- OwnedAttachments& colorAttachments,
- std::unique_ptr<FramebufferAttachment>& depthAttachment,
- uint32_t width,
- uint32_t height);
+ Vulkan::Device& device,
+ RenderPassHandle renderPass,
+ SharedAttachments& colorAttachments,
+ FramebufferAttachmentHandle depthAttachment,
+ uint32_t width,
+ uint32_t height);
/**
* @brief Constructor
* @param[in] height Height of the framebuffer
* @param[in] hasDepthAttachment True if the last attachment is a depth buffer
*/
- FramebufferImpl(Device& graphicsDevice,
- OwnedAttachments& attachments,
- vk::Framebuffer vkHandle,
- RenderPassHandle renderPass,
- uint32_t width,
- uint32_t height,
- bool hasDepthAttachment);
+ FramebufferImpl(Device& graphicsDevice,
+ SharedAttachments& attachments,
+ vk::Framebuffer vkHandle,
+ RenderPassHandle renderPass,
+ uint32_t width,
+ uint32_t height,
+ bool hasDepthAttachment);
void Destroy();
[[nodiscard]] uint32_t GetHeight() const;
- [[nodiscard]] FramebufferAttachment* GetAttachment(AttachmentType type, uint32_t index) const;
+ [[nodiscard]] FramebufferAttachmentHandle GetAttachment(AttachmentType type, uint32_t index) const;
- [[nodiscard]] std::vector<FramebufferAttachment*> GetAttachments(AttachmentType type) const;
+ [[nodiscard]] SharedAttachments GetAttachments(AttachmentType type) const;
[[nodiscard]] uint32_t GetAttachmentCount(AttachmentType type) const;
};
using RenderPasses = std::vector<RenderPassMapElement>;
- OwnedAttachments mAttachments;
- vk::Framebuffer mFramebuffer;
- RenderPasses mRenderPasses;
- bool mHasDepthAttachment{false};
+ SharedAttachments mAttachments;
+ vk::Framebuffer mFramebuffer;
+ RenderPasses mRenderPasses;
+ bool mHasDepthAttachment{false};
};
} // Namespace Dali::Graphics::Vulkan
bool Framebuffer::InitializeResource()
{
// Create attachments
- OwnedAttachments colorAttachments;
+ SharedAttachments colorAttachments;
// for(auto& attachment : mCreateInfo.colorAttachments)
{
// auto graphicsTexture = static_cast<const Vulkan::Texture*>(attachment.texture);
// colorAttachments.push_back(FramebufferAttachment::NewColorAttachment(attachment.texture->GetVkHandle(), clearColor, AttachmentType::COLOR, false);
}
- std::unique_ptr<FramebufferAttachment> depthStencilAttachment;
+ FramebufferAttachmentHandle depthStencilAttachment;
if(mCreateInfo.depthStencilAttachment.depthTexture || mCreateInfo.depthStencilAttachment.stencilTexture)
{
// depthStencilAttachment = FramebufferAttachment::NewDepthAttachment();
return static_cast<T0*>(apiObject);
}
+namespace DepthStencilFlagBits
+{
+static constexpr uint32_t DEPTH_BUFFER_BIT = 1; // depth buffer enabled
+static constexpr uint32_t STENCIL_BUFFER_BIT = 2; // stencil buffer enabled
+} // namespace DepthStencilFlagBits
+
+// State of the depth-stencil buffer
+using DepthStencilFlags = uint32_t;
+
struct VulkanGraphicsController::Impl
{
explicit Impl(VulkanGraphicsController& controller)
}
}
+ bool EnableDepthStencilBuffer(const RenderTarget& renderTarget, bool enableDepth, bool enableStencil)
+ {
+ auto surface = static_cast<const Vulkan::RenderTarget*>(&renderTarget)->GetSurface();
+ if(!surface)
+ {
+ // Do nothing if this is not a surface.
+ return false;
+ }
+
+ auto renderSurface = static_cast<Internal::Adaptor::WindowRenderSurface*>(surface);
+ auto surfaceId = renderSurface->GetSurfaceId();
+
+ mDepthStencilBufferRequestedState = (enableDepth ? DepthStencilFlagBits::DEPTH_BUFFER_BIT : 0u) |
+ (enableStencil ? DepthStencilFlagBits::STENCIL_BUFFER_BIT : 0u);
+
+ auto retval = mDepthStencilBufferRequestedState != mDepthStencilBufferCurrentState;
+
+ // @todo move state vars to surface
+ if(surface && mDepthStencilBufferCurrentState != mDepthStencilBufferRequestedState)
+ {
+ DALI_LOG_INFO(gVulkanFilter, Debug::Verbose, "UpdateDepthStencilBuffer(): New state: DEPTH: %d, STENCIL: %d\n", int(mDepthStencilBufferRequestedState & 1), int((mDepthStencilBufferRequestedState >> 1) & 1));
+
+ // Formats
+ const std::array<vk::Format, 4> DEPTH_STENCIL_FORMATS = {
+ vk::Format::eUndefined, // no depth nor stencil needed
+ vk::Format::eD16Unorm, // only depth buffer
+ vk::Format::eS8Uint, // only stencil buffer
+ vk::Format::eD24UnormS8Uint // depth and stencil buffers
+ };
+
+ mGraphicsDevice->DeviceWaitIdle();
+
+ mGraphicsDevice->GetSwapchainForSurfaceId(surfaceId)->SetDepthStencil(DEPTH_STENCIL_FORMATS[mDepthStencilBufferRequestedState]);
+
+ // make sure GPU finished any pending work
+ mGraphicsDevice->DeviceWaitIdle();
+
+ mDepthStencilBufferCurrentState = mDepthStencilBufferRequestedState;
+ }
+ return retval;
+ }
+
/**
- * Mappign the staging buffer may take some time, so can delegate to a worker thread
+ * Mapping the staging buffer may take some time, so can delegate to a worker thread
* if necessary.
*/
Dali::SharedFuture InitializeTextureStagingBuffer(uint32_t size, bool useWorkerThread)
if(!mTextureStagingBuffer ||
mTextureStagingBuffer->GetImpl()->GetSize() < size)
{
- auto workerFunc = [&, size](auto workerIndex)
- {
+ auto workerFunc = [&, size](auto workerIndex) {
Graphics::BufferCreateInfo createInfo{};
createInfo.SetSize(size)
.SetUsage(0u | Dali::Graphics::BufferUsage::TRANSFER_SRC);
}
assert(image);
- auto predicate = [&](auto& item) -> bool
- {
+ auto predicate = [&](auto& item) -> bool {
return image->GetVkHandle() == item.image.GetVkHandle();
};
auto it = std::find_if(requestMap.begin(), requestMap.end(), predicate);
ThreadPool mThreadPool;
+ DepthStencilFlags mDepthStencilBufferCurrentState{0u};
+ DepthStencilFlags mDepthStencilBufferRequestedState{0u};
+
std::unordered_map<uint32_t, Graphics::UniquePtr<Graphics::Texture>> mExternalTextureResources; ///< Used for ResourceId.
std::queue<const Vulkan::Texture*> mTextureMipmapGenerationRequests; ///< Queue for texture mipmap generation requests
if(destTexture->GetProperties().directWriteAccessEnabled)
{
- auto taskLambda = [pInfo, sourcePtr, sourceInfoPtr, texture](auto workerIndex)
- {
+ auto taskLambda = [pInfo, sourcePtr, sourceInfoPtr, texture](auto workerIndex) {
const auto& properties = texture->GetProperties();
if(properties.emulated)
// The staging buffer is not allocated yet. The task knows pointer to the pointer which will point
// at staging buffer right before executing tasks. The function will either perform direct copy
// or will do suitable conversion if source format isn't supported and emulation is available.
- auto taskLambda = [ppStagingMemory, currentOffset, pInfo, sourcePtr, texture](auto workerThread)
- {
+ auto taskLambda = [ppStagingMemory, currentOffset, pInfo, sourcePtr, texture](auto workerThread) {
char* pStagingMemory = reinterpret_cast<char*>(*ppStagingMemory);
// Try to initialise` texture resources explicitly if they are not yet initialised
for(auto& item : updateMap)
{
auto pUpdates = &item.second;
- auto task = [pUpdates](auto workerIndex)
- {
+ auto task = [pUpdates](auto workerIndex) {
for(auto& update : *pUpdates)
{
update.copyTask(workerIndex);
{
}
-bool VulkanGraphicsController::EnableDepthStencilBuffer(bool enableDepth, bool enableStencil)
+bool VulkanGraphicsController::EnableDepthStencilBuffer(
+ const Graphics::RenderTarget& gfxRenderTarget,
+ bool enableDepth,
+ bool enableStencil)
{
- return true;
+ // if we enable depth/stencil dynamically we need to block and invalidate pipeline cache
+ auto renderTarget = static_cast<const Vulkan::RenderTarget*>(&gfxRenderTarget);
+ return mImpl->EnableDepthStencilBuffer(*renderTarget, enableDepth, enableStencil);
}
void VulkanGraphicsController::RunGarbageCollector(size_t numberOfDiscardedRenderers)
const Matrix& VulkanGraphicsController::GetClipMatrix() const
{
constexpr float CLIP_MATRIX_DATA[] = {
- 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f};
+ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f};
static const Matrix CLIP_MATRIX(CLIP_MATRIX_DATA);
return CLIP_MATRIX;
}
/**
* @brief Enables depth/stencil buffer
*
+ * @param[in] renderTarget The surface for which to enable depth/stencil buffer.
* @param[in] enableDepth True to enable depth
* @param[in] enableStencil True to enable stencil
* @return True on success
*/
- bool EnableDepthStencilBuffer(bool enableDepth, bool enableStencil) override;
+ bool EnableDepthStencilBuffer(const Graphics::RenderTarget& renderTarget, bool enableDepth, bool enableStencil) override;
/**
* @brief Runs garbage collector (if supported)
-#pragma once
+#ifndef DALI_GRAPHICS_VULKAN_HANDLE_H
+#define DALI_GRAPHICS_VULKAN_HANDLE_H
/*
* Copyright (c) 2024 Samsung Electronics Co., Ltd.
Handle& operator=(const Handle& handle);
- Handle& operator=(Handle&& handle);
+ Handle& operator=(Handle&& handle) noexcept;
Handle(Handle&& handle) noexcept;
return mObject;
}
- uint32_t GetRefCount() const
+ [[nodiscard]] uint32_t GetRefCount() const
{
return mObject->GetRefCount();
}
}
template<class T>
-Handle<T>& Handle<T>::operator=(Handle&& handle)
+Handle<T>& Handle<T>::operator=(Handle&& handle) noexcept
{
if(mObject)
{
template<class T>
Handle<T>& Handle<T>::operator=(const Handle<T>& handle)
{
- mObject = handle.mObject;
- if(mObject)
+ if(handle.mObject != this)
{
- mObject->Retain();
+ mObject = handle.mObject;
+ if(mObject)
+ {
+ mObject->Retain();
+ }
}
return *this;
}
};
} // namespace Dali::Graphics::Vulkan
+
+#endif // DALI_GRAPHICS_VULKAN_HANDLE_H
namespace Dali::Graphics::Vulkan
{
class Device;
-class Memory;
+class MemoryImpl;
// @todo use ImageImpl to make naming convention consistent
[[nodiscard]] vk::SampleCountFlagBits GetSampleCount() const;
- [[nodiscard]] MemoryImpl* GetMemory() const
+ [[nodiscard]] Vulkan::MemoryImpl* GetMemory() const
{
return mMemory.get();
}
namespace Dali::Graphics::Vulkan
{
+
class MemoryImpl
{
public:
uint32_t PipelineImpl::GetRefCount() const
{
- return 0; //mRefCount;
+ return 0; // mRefCount;
}
PipelineImpl::~PipelineImpl() = default;
if(gfxPipelineInfo.pColorBlendState)
{
auto attachmentCount = impl->GetAttachments().size();
-
+ if(impl->HasDepthAttachment())
+ {
+ attachmentCount--;
+ }
if(attachmentCount != mBlendStateAttachments.size())
{
// Make sure array is 1
std::transform(mCreateInfo.vertexInputState->bufferBindings.begin(),
mCreateInfo.vertexInputState->bufferBindings.end(),
std::back_inserter(bindings),
- [](const VertexInputState::Binding& in) -> vk::VertexInputBindingDescription {
+ [](const VertexInputState::Binding& in) -> vk::VertexInputBindingDescription
+ {
vk::VertexInputBindingDescription out;
out.setInputRate((in.inputRate == VertexInputRate::PER_VERTEX ? vk::VertexInputRate::eVertex : vk::VertexInputRate::eInstance));
out.setBinding(0u); // To be filled later using indices
std::transform(mCreateInfo.vertexInputState->attributes.begin(),
mCreateInfo.vertexInputState->attributes.end(),
std::back_inserter(attrs),
- [](const VertexInputState::Attribute& in) -> vk::VertexInputAttributeDescription {
+ [](const VertexInputState::Attribute& in) -> vk::VertexInputAttributeDescription
+ {
vk::VertexInputAttributeDescription out;
out.setBinding(in.binding);
out.setLocation(in.location);
{
auto gfxRastState = mCreateInfo.rasterizationState;
- out.setFrontFace([gfxRastState]() {
- return gfxRastState->frontFace == FrontFace::CLOCKWISE ? vk::FrontFace::eClockwise : vk::FrontFace::eCounterClockwise;
- }());
+ out.setFrontFace([gfxRastState]()
+ { return gfxRastState->frontFace == FrontFace::CLOCKWISE ? vk::FrontFace::eClockwise : vk::FrontFace::eCounterClockwise; }());
- out.setPolygonMode([polygonMode = gfxRastState->polygonMode]() {
+ out.setPolygonMode([polygonMode = gfxRastState->polygonMode]()
+ {
switch(polygonMode)
{
case PolygonMode::FILL:
return vk::PolygonMode::ePoint;
}
}
- return vk::PolygonMode{};
- }());
+ return vk::PolygonMode{}; }());
- out.setCullMode([cullMode = gfxRastState->cullMode]() -> vk::CullModeFlagBits {
+ out.setCullMode([cullMode = gfxRastState->cullMode]() -> vk::CullModeFlagBits
+ {
switch(cullMode)
{
case CullMode::NONE:
return vk::CullModeFlagBits::eFrontAndBack;
}
}
- return {};
- }());
+ return {}; }());
out.setLineWidth(1.0f); // Line with hardcoded to 1.0f
out.setDepthClampEnable(false); // no depth clamp
out.setDepthCompareOp(ConvCompareOp(in->depthCompareOp));
return true;
}
+ else
+ {
+ // If we're not setting the following through the createInfo struct, they must instead
+ // come from command buffer commands.
+ mDynamicStates.emplace_back(vk::DynamicState::eDepthTestEnable);
+ mDynamicStates.emplace_back(vk::DynamicState::eDepthWriteEnable);
+ mDynamicStates.emplace_back(vk::DynamicState::eDepthCompareOp);
+ mDynamicStates.emplace_back(vk::DynamicState::eDepthBounds);
+ mDynamicStates.emplace_back(vk::DynamicState::eDepthBoundsTestEnable);
+ mDynamicStates.emplace_back(vk::DynamicState::eStencilTestEnable);
+ mDynamicStates.emplace_back(vk::DynamicState::eStencilOp);
+ mDynamicStates.emplace_back(vk::DynamicState::eStencilCompareMask);
+ mDynamicStates.emplace_back(vk::DynamicState::eStencilWriteMask);
+ mDynamicStates.emplace_back(vk::DynamicState::eStencilReference);
+ }
return false;
}
{
auto in = mCreateInfo.colorBlendState;
- auto ConvLogicOp = [](LogicOp in) {
+ auto ConvLogicOp = [](LogicOp in)
+ {
switch(in)
{
case LogicOp::CLEAR:
return vk::LogicOp{};
};
- auto ConvBlendOp = [](BlendOp in) {
+ auto ConvBlendOp = [](BlendOp in)
+ {
switch(in)
{
case BlendOp::ADD:
return vk::BlendOp{};
};
- auto ConvBlendFactor = [](BlendFactor in) {
+ auto ConvBlendFactor = [](BlendFactor in)
+ {
switch(in)
{
case BlendFactor::ZERO:
att.setAlphaBlendOp(ConvBlendOp(in->alphaBlendOp));
att.setBlendEnable(in->blendEnable);
- //att.setColorWriteMask()
+ // att.setColorWriteMask()
att.setColorBlendOp(ConvBlendOp(in->colorBlendOp));
att.setColorWriteMask(vk::ColorComponentFlags(in->colorComponentWriteBits));
att.setColorWriteMask(vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
namespace Dali::Graphics::Vulkan
{
RenderPassHandle RenderPassImpl::New(
- Vulkan::Device& device,
- const std::vector<FramebufferAttachment*>& colorAttachments,
- FramebufferAttachment* depthAttachment)
+ Vulkan::Device& device,
+ const SharedAttachments& colorAttachments,
+ FramebufferAttachmentHandle depthAttachment)
{
auto renderPass = new RenderPassImpl(device, colorAttachments, depthAttachment);
return RenderPassHandle(renderPass);
}
-RenderPassImpl::RenderPassImpl(Vulkan::Device& device,
- const std::vector<FramebufferAttachment*>& colorAttachments,
- FramebufferAttachment* depthAttachment)
-: mGraphicsDevice(&device)
+RenderPassImpl::RenderPassImpl(Vulkan::Device& device,
+ const SharedAttachments& colorAttachments,
+ FramebufferAttachmentHandle depthAttachment)
+: mGraphicsDevice(&device),
+ mHasDepthAttachment(bool(depthAttachment))
{
CreateCompatibleCreateInfo(colorAttachments, depthAttachment);
CreateRenderPass();
}
void RenderPassImpl::CreateCompatibleCreateInfo(
- const std::vector<FramebufferAttachment*>& colorAttachments,
- FramebufferAttachment* depthAttachment)
+ const SharedAttachments& colorAttachments,
+ FramebufferAttachmentHandle depthAttachment)
{
auto hasDepth = false;
if(depthAttachment)
// Creating 2 subpass dependencies using VK_SUBPASS_EXTERNAL to leverage the implicit image layout
// transitions provided by the driver
+ vk::AccessFlags accessMask(vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite);
+ vk::PipelineStageFlags stageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput);
+ if(hasDepth)
+ {
+ accessMask |= vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
+ stageMask |= vk::PipelineStageFlagBits::eEarlyFragmentTests;
+ }
+
mCreateInfo.subpassDependencies = {
vk::SubpassDependency{}
.setSrcSubpass(VK_SUBPASS_EXTERNAL)
.setDstSubpass(0)
.setSrcStageMask(vk::PipelineStageFlagBits::eBottomOfPipe)
- .setDstStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput)
+ .setDstStageMask(stageMask)
.setSrcAccessMask(vk::AccessFlagBits::eMemoryRead)
- .setDstAccessMask(vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite)
+ .setDstAccessMask(accessMask)
.setDependencyFlags(vk::DependencyFlagBits::eByRegion),
vk::SubpassDependency{}
.setSrcSubpass(0)
.setDstSubpass(VK_SUBPASS_EXTERNAL)
- .setSrcStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput)
+ .setSrcStageMask(stageMask)
.setDstStageMask(vk::PipelineStageFlagBits::eBottomOfPipe)
- .setSrcAccessMask(vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite)
+ .setSrcAccessMask(accessMask)
.setDstAccessMask(vk::AccessFlagBits::eMemoryRead)
.setDependencyFlags(vk::DependencyFlagBits::eByRegion)};
*/
#include <dali/graphics-api/graphics-render-pass-create-info.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-framebuffer-attachment.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-handle.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-types.h>
#include <dali/public-api/common/vector-wrapper.h>
vk::RenderPassCreateInfo createInfo;
};
- static RenderPassHandle New(Vulkan::Device& device,
- const std::vector<FramebufferAttachment*>& colorAttachments,
- FramebufferAttachment* depthAttachment);
+ static RenderPassHandle New(Vulkan::Device& device,
+ const SharedAttachments& colorAttachments,
+ FramebufferAttachmentHandle depthAttachment);
- RenderPassImpl(Vulkan::Device& device, const std::vector<FramebufferAttachment*>& colorAttachments, FramebufferAttachment* depthAttachment);
+ RenderPassImpl(Vulkan::Device& device, const SharedAttachments& colorAttachments, FramebufferAttachmentHandle depthAttachment);
~RenderPassImpl();
std::vector<vk::ImageView>& GetAttachments();
+ bool HasDepthAttachment()
+ {
+ return mHasDepthAttachment;
+ }
+
CreateInfo& GetCreateInfo()
{
return mCreateInfo;
private:
void CreateCompatibleCreateInfo(
- const std::vector<FramebufferAttachment*>& colorAttachments,
- FramebufferAttachment* depthAttachment);
+ const SharedAttachments& colorAttachments,
+ FramebufferAttachmentHandle depthAttachment);
void CreateRenderPass();
CreateInfo mCreateInfo;
vk::RenderPass mVkRenderPass;
std::vector<vk::ImageView> mAttachments{};
+ bool mHasDepthAttachment;
};
} // namespace Dali::Graphics::Vulkan
// INTERNAL INCLUDES
#include <dali/internal/graphics/vulkan-impl/vulkan-fence-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-image-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-image-view-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-surface-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-swapchain-impl.h>
}
}
-void Swapchain::CreateFramebuffers()
+void Swapchain::CreateFramebuffers(FramebufferAttachmentHandle depthAttachment)
{
assert(mSwapchainKHR && "Needs a swapchain before creating framebuffers");
colorImageView.reset(ImageView::NewFromImage(mGraphicsDevice, *colorImage));
// A new color attachment for each framebuffer
- OwnedAttachments attachments;
+ SharedAttachments attachments;
attachments.emplace_back(FramebufferAttachment::NewColorAttachment(colorImageView,
clearColor,
true));
- std::unique_ptr<FramebufferAttachment> depthAttachment;
+
std::unique_ptr<FramebufferImpl, void (*)(FramebufferImpl*)> framebuffer(
FramebufferImpl::New(mGraphicsDevice,
compatibleRenderPass,
void Swapchain::SetDepthStencil(vk::Format depthStencilFormat)
{
-#if 0
- RefCountedFramebufferAttachment depthAttachment;
- auto swapchainExtent = mSwapchainCreateInfoKHR.imageExtent;
+ FramebufferAttachmentHandle depthAttachment;
+ auto swapchainExtent = mSwapchainCreateInfoKHR.imageExtent;
- if( depthStencilFormat != vk::Format::eUndefined )
+ if(depthStencilFormat != vk::Format::eUndefined)
{
// Create depth/stencil image
auto imageCreateInfo = vk::ImageCreateInfo{}
- .setFormat( depthStencilFormat )
- .setMipLevels( 1 )
- .setTiling( vk::ImageTiling::eOptimal )
- .setImageType( vk::ImageType::e2D )
- .setArrayLayers( 1 )
- .setExtent( { swapchainExtent.width, swapchainExtent.height, 1 } )
- .setUsage( vk::ImageUsageFlagBits::eDepthStencilAttachment )
- .setSharingMode( vk::SharingMode::eExclusive )
- .setInitialLayout( vk::ImageLayout::eUndefined )
- .setSamples( vk::SampleCountFlagBits::e1 );
-
- auto dsRefCountedImage = mGraphicsDevice->CreateImage( imageCreateInfo );
+ .setFormat(depthStencilFormat)
+ .setMipLevels(1)
+ .setTiling(vk::ImageTiling::eOptimal)
+ .setImageType(vk::ImageType::e2D)
+ .setArrayLayers(1)
+ .setExtent({swapchainExtent.width, swapchainExtent.height, 1})
+ .setUsage(vk::ImageUsageFlagBits::eDepthStencilAttachment)
+ .setSharingMode(vk::SharingMode::eExclusive)
+ .setInitialLayout(vk::ImageLayout::eUndefined)
+ .setSamples(vk::SampleCountFlagBits::e1);
- auto memory = mGraphicsDevice->AllocateMemory( dsRefCountedImage, vk::MemoryPropertyFlagBits::eDeviceLocal );
+ mDepthStencilBuffer.reset(Image::New(mGraphicsDevice, imageCreateInfo));
- mGraphics->BindImageMemory( dsRefCountedImage, std::move(memory), 0 );
+ mDepthStencilBuffer->AllocateAndBind(vk::MemoryPropertyFlagBits::eDeviceLocal);
// create the depth stencil ImageView to be used within framebuffer
- auto depthStencilImageView = ImageView::New(dsRefCountedImage);
- auto depthClearValue = vk::ClearDepthStencilValue{}.setDepth( 0.0 )
- .setStencil( STENCIL_DEFAULT_CLEAR_VALUE );
+ auto depthStencilImageView = std::unique_ptr<ImageView>(ImageView::NewFromImage(mGraphicsDevice, *mDepthStencilBuffer));
+ auto depthClearValue = vk::ClearDepthStencilValue{}.setDepth(0.0).setStencil(STENCIL_DEFAULT_CLEAR_VALUE);
- // A single depth attachment for the swapchain.
- depthAttachment = FramebufferAttachment::NewDepthAttachment( depthStencilImageView, depthClearValue );
- }
-
- // Get images
- auto images = VkAssert( mGraphics->GetDevice().getSwapchainImagesKHR( mSwapchainKHR ) );
-
- // allocate framebuffers
- auto framebuffers = std::vector< RefCountedFramebuffer >{};
- framebuffers.reserve( images.size() );
-
- auto clearColor = vk::ClearColorValue{}.setFloat32( { 0.0f, 0.0f, 0.0f, 1.0f } );
-
- for( auto&& image : images )
- {
- // @todo When do we kill this auto image & imageView? MemLeak.
- auto colorImageView = ImageView::New( mGraphics->CreateImageFromExternal( image, mSwapchainCreateInfoKHR.imageFormat, swapchainExtent ) );
-
- // A new color attachment for each framebuffer
- auto colorAttachment = FramebufferAttachment::NewColorAttachment(colorImageView,
- clearColor,
- true);//presentable
-
- framebuffers.push_back( mGraphics->CreateFramebuffer({colorAttachment},
- depthAttachment,
- swapchainExtent.width,
- swapchainExtent.height ) );
+ // A single depth attachment for the swapchain. Takes ownership of the image view
+ depthAttachment = FramebufferAttachmentHandle(FramebufferAttachment::NewDepthAttachment(depthStencilImageView, depthClearValue));
}
// Before replacing framebuffers in the swapchain, wait until all is done
- mGraphics->DeviceWaitIdle();
+ mGraphicsDevice.DeviceWaitIdle();
- mFramebuffers = std::move( framebuffers );
-#endif
+ CreateFramebuffers(depthAttachment);
}
uint32_t Swapchain::GetImageCount() const
*/
// INTERNAL INCLUDES
+#include <dali/internal/graphics/vulkan-impl/vulkan-framebuffer-attachment.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-types.h>
namespace Dali::Graphics::Vulkan
class FenceImpl;
class SurfaceImpl;
class Queue;
-class SwapchainBuffer;
+struct SwapchainBuffer;
/**
* Creates swapchain for given surface and queue
/**
* Automatically create framebuffers (generating compatible render passes)
+ *
+ * @param[in] depthAttachment Optional depth attachment.
*/
- void CreateFramebuffers();
+ void CreateFramebuffers(FramebufferAttachmentHandle depthAttachment);
[[nodiscard]] vk::SwapchainKHR GetVkHandle() const;
*/
using OwnedFramebuffer = std::unique_ptr<FramebufferImpl, void (*)(FramebufferImpl*)>;
std::vector<OwnedFramebuffer> mFramebuffers;
+ std::unique_ptr<Image> mDepthStencilBuffer;
/**
* Array of swapchain buffers
vk::AttachmentStoreOp storeOp{vk::AttachmentStoreOp::eDontCare};
};
+struct VkCompareOpType
+{
+ constexpr explicit VkCompareOpType(Graphics::CompareOp compareOp)
+ {
+ switch(compareOp)
+ {
+ case Graphics::CompareOp::NEVER:
+ op = vk::CompareOp::eNever;
+ break;
+ case Graphics::CompareOp::LESS:
+ op = vk::CompareOp::eLess;
+ break;
+ case Graphics::CompareOp::EQUAL:
+ op = vk::CompareOp::eEqual;
+ break;
+ case Graphics::CompareOp::LESS_OR_EQUAL:
+ op = vk::CompareOp::eLessOrEqual;
+ break;
+ case Graphics::CompareOp::GREATER:
+ op = vk::CompareOp::eGreater;
+ break;
+ case Graphics::CompareOp::NOT_EQUAL:
+ op = vk::CompareOp::eNotEqual;
+ break;
+ case Graphics::CompareOp::GREATER_OR_EQUAL:
+ op = vk::CompareOp::eGreaterOrEqual;
+ break;
+ case Graphics::CompareOp::ALWAYS:
+ op = vk::CompareOp::eAlways;
+ break;
+ }
+ }
+ vk::CompareOp op{vk::CompareOp::eLess};
+};
+
+struct VkStencilOpType
+{
+ constexpr explicit VkStencilOpType(Graphics::StencilOp stencilOp)
+ {
+ switch(stencilOp)
+ {
+ case Graphics::StencilOp::KEEP:
+ op = vk::StencilOp::eKeep;
+ break;
+ case Graphics::StencilOp::ZERO:
+ op = vk::StencilOp::eZero;
+ break;
+ case Graphics::StencilOp::REPLACE:
+ op = vk::StencilOp::eReplace;
+ break;
+ case Graphics::StencilOp::INCREMENT_AND_CLAMP:
+ op = vk::StencilOp::eIncrementAndClamp;
+ break;
+ case Graphics::StencilOp::DECREMENT_AND_CLAMP:
+ op = vk::StencilOp::eDecrementAndClamp;
+ break;
+ case Graphics::StencilOp::INVERT:
+ op = vk::StencilOp::eInvert;
+ break;
+ case Graphics::StencilOp::INCREMENT_AND_WRAP:
+ op = vk::StencilOp::eIncrementAndWrap;
+ break;
+ case Graphics::StencilOp::DECREMENT_AND_WRAP:
+ op = vk::StencilOp::eDecrementAndWrap;
+ break;
+ }
+ }
+ vk::StencilOp op{vk::StencilOp::eZero};
+};
+
} // namespace Vulkan
} // namespace Dali::Graphics
}
// @todo: Only create framebuffers if no "external" render passes.
- newSwapchain->CreateFramebuffers(); // Note, this may destroy vk swapchain if invalid.
+ FramebufferAttachmentHandle empty;
+ newSwapchain->CreateFramebuffers(empty); // Note, this may destroy vk swapchain if invalid.
return newSwapchain;
}
void Device::CreateInstance(const std::vector<const char*>& extensions,
const std::vector<const char*>& validationLayers)
{
- auto info = vk::InstanceCreateInfo{};
-
- info.setEnabledExtensionCount(U32(extensions.size()))
+ auto info = vk::InstanceCreateInfo{};
+ auto appInfo = vk::ApplicationInfo{};
+ appInfo.setApiVersion(VK_API_VERSION_1_3);
+ info
+ .setPApplicationInfo(&appInfo)
+ .setEnabledExtensionCount(U32(extensions.size()))
.setPpEnabledExtensionNames(extensions.data())
.setEnabledLayerCount(U32(validationLayers.size()))
.setPpEnabledLayerNames(validationLayers.data());
// if only one, pick first
mPhysicalDevice = nullptr;
+ int gpuId = 0;
if(devices.size() == 1)
{
mPhysicalDevice = devices[0];
++queueIndex;
}
}
+ if(mPhysicalDevice)
+ {
+ break;
+ }
+ gpuId++;
}
}
VK_API_VERSION_PATCH(mPhysicalDeviceProperties.apiVersion),
(const char*)mPhysicalDeviceProperties.deviceName,
mPhysicalDeviceProperties.driverVersion);
+
+ DALI_LOG_INFO(gVulkanFilter, Debug::Concise, "GPU ID:%d\n", gpuId);
}
void Device::GetPhysicalDeviceProperties()
std::transform(subData.commandBuffers.cbegin(),
subData.commandBuffers.cend(),
std::back_inserter(commandBufferHandles),
- [&](CommandBufferImpl* entry)
- {
+ [&](CommandBufferImpl* entry) {
return entry->GetVkHandle();
});
void DiscardResource(std::function<void()> deleter);
- FramebufferImpl* CreateFramebuffer(const std::vector<FramebufferAttachment*>& colorAttachments,
- FramebufferAttachment* depthAttachment,
- uint32_t width,
- uint32_t height,
- RenderPassImpl* externalRenderPass = nullptr);
-
Image* CreateImageFromExternal(vk::Image externalImage, vk::Format imageFormat, vk::Extent2D extent);
uint32_t GetCurrentBufferIndex() const;