#include <dali/internal/render/common/render-debug.h>
#include <dali/internal/render/common/render-instruction.h>
#include <dali/internal/render/common/render-list.h>
-#include <dali/internal/render/gl-resources/context.h>
#include <dali/internal/render/renderers/render-renderer.h>
#include <dali/internal/update/nodes/scene-graph-layer.h>
{
namespace
{
-// Table for fast look-up of Dali::DepthFunction enum to a GL depth function.
-// Note: These MUST be in the same order as Dali::DepthFunction enum.
-const int DaliDepthToGLDepthTable[] = {GL_NEVER, GL_ALWAYS, GL_LESS, GL_GREATER, GL_EQUAL, GL_NOTEQUAL, GL_LEQUAL, GL_GEQUAL};
+struct GraphicsDepthCompareOp
+{
+ constexpr explicit GraphicsDepthCompareOp(DepthFunction::Type compareOp)
+ {
+ switch(compareOp)
+ {
+ case DepthFunction::NEVER:
+ op = Graphics::CompareOp::NEVER;
+ break;
+ case DepthFunction::LESS:
+ op = Graphics::CompareOp::LESS;
+ break;
+ case DepthFunction::EQUAL:
+ op = Graphics::CompareOp::EQUAL;
+ break;
+ case DepthFunction::LESS_EQUAL:
+ op = Graphics::CompareOp::LESS_OR_EQUAL;
+ break;
+ case DepthFunction::GREATER:
+ op = Graphics::CompareOp::GREATER;
+ break;
+ case DepthFunction::NOT_EQUAL:
+ op = Graphics::CompareOp::NOT_EQUAL;
+ break;
+ case DepthFunction::GREATER_EQUAL:
+ op = Graphics::CompareOp::GREATER_OR_EQUAL;
+ break;
+ case DepthFunction::ALWAYS:
+ op = Graphics::CompareOp::ALWAYS;
+ break;
+ }
+ }
+ Graphics::CompareOp op{Graphics::CompareOp::NEVER};
+};
-// Table for fast look-up of Dali::StencilFunction enum to a GL stencil function.
-// Note: These MUST be in the same order as Dali::StencilFunction enum.
-const int DaliStencilFunctionToGL[] = {GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS};
+struct GraphicsStencilCompareOp
+{
+ constexpr explicit GraphicsStencilCompareOp(StencilFunction::Type compareOp)
+ {
+ switch(compareOp)
+ {
+ case StencilFunction::NEVER:
+ op = Graphics::CompareOp::NEVER;
+ break;
+ case StencilFunction::LESS:
+ op = Graphics::CompareOp::LESS;
+ break;
+ case StencilFunction::EQUAL:
+ op = Graphics::CompareOp::EQUAL;
+ break;
+ case StencilFunction::LESS_EQUAL:
+ op = Graphics::CompareOp::LESS_OR_EQUAL;
+ break;
+ case StencilFunction::GREATER:
+ op = Graphics::CompareOp::GREATER;
+ break;
+ case StencilFunction::NOT_EQUAL:
+ op = Graphics::CompareOp::NOT_EQUAL;
+ break;
+ case StencilFunction::GREATER_EQUAL:
+ op = Graphics::CompareOp::GREATER_OR_EQUAL;
+ break;
+ case StencilFunction::ALWAYS:
+ op = Graphics::CompareOp::ALWAYS;
+ break;
+ }
+ }
+ Graphics::CompareOp op{Graphics::CompareOp::NEVER};
+};
-// Table for fast look-up of Dali::StencilOperation enum to a GL stencil operation.
-// Note: These MUST be in the same order as Dali::StencilOperation enum.
-const int DaliStencilOperationToGL[] = {GL_ZERO, GL_KEEP, GL_REPLACE, GL_INCR, GL_DECR, GL_INVERT, GL_INCR_WRAP, GL_DECR_WRAP};
+struct GraphicsStencilOp
+{
+ constexpr explicit GraphicsStencilOp(StencilOperation::Type stencilOp)
+ {
+ switch(stencilOp)
+ {
+ case Dali::StencilOperation::KEEP:
+ op = Graphics::StencilOp::KEEP;
+ break;
+ case Dali::StencilOperation::ZERO:
+ op = Graphics::StencilOp::ZERO;
+ break;
+ case Dali::StencilOperation::REPLACE:
+ op = Graphics::StencilOp::REPLACE;
+ break;
+ case Dali::StencilOperation::INCREMENT:
+ op = Graphics::StencilOp::INCREMENT_AND_CLAMP;
+ break;
+ case Dali::StencilOperation::DECREMENT:
+ op = Graphics::StencilOp::DECREMENT_AND_CLAMP;
+ break;
+ case Dali::StencilOperation::INVERT:
+ op = Graphics::StencilOp::INVERT;
+ break;
+ case Dali::StencilOperation::INCREMENT_WRAP:
+ op = Graphics::StencilOp::INCREMENT_AND_WRAP;
+ break;
+ case Dali::StencilOperation::DECREMENT_WRAP:
+ op = Graphics::StencilOp::DECREMENT_AND_WRAP;
+ break;
+ }
+ }
+ Graphics::StencilOp op{Graphics::StencilOp::KEEP};
+};
inline Graphics::Viewport ViewportFromClippingBox(ClippingBox clippingBox, int orientation)
{
Graphics::Viewport viewport{static_cast<float>(clippingBox.x), static_cast<float>(clippingBox.y), static_cast<float>(clippingBox.width), static_cast<float>(clippingBox.height), 0.0f, 0.0f};
- if(orientation == 80 || orientation == 270)
+ if(orientation == 90 || orientation == 270)
{
viewport.width = static_cast<float>(clippingBox.height);
viewport.height = static_cast<float>(clippingBox.width);
/**
* @brief Set up the stencil and color buffer for automatic clipping (StencilMode::AUTO).
* @param[in] item The current RenderItem about to be rendered
- * @param[in] context The context
- * @param[in/out] lastClippingDepth The stencil depth of the last renderer drawn.
- * @param[in/out] lastClippingId The clipping ID of the last renderer drawn.
+ * @param[in,out] commandBuffer The command buffer to write stencil commands into
+ * @param[in,out] lastClippingDepth The stencil depth of the last renderer drawn.
+ * @param[in,out] lastClippingId The clipping ID of the last renderer drawn.
*/
-inline void SetupStencilClipping(const RenderItem& item, Context& context, uint32_t& lastClippingDepth, uint32_t& lastClippingId)
+inline void SetupStencilClipping(const RenderItem& item, Graphics::CommandBuffer& commandBuffer, uint32_t& lastClippingDepth, uint32_t& lastClippingId)
{
const Dali::Internal::SceneGraph::Node* node = item.mNode;
const uint32_t clippingId = node->GetClippingId();
if(clippingId == 0u)
{
// Exit immediately if there are no clipping actions to perform (EG. we have not yet hit a clipping node).
- context.EnableStencilBuffer(false);
+ commandBuffer.SetStencilTestEnable(false);
return;
}
-
- context.EnableStencilBuffer(true);
+ commandBuffer.SetStencilTestEnable(true);
const uint32_t clippingDepth = node->GetClippingDepth();
{
// We are enabling the stencil-buffer for the first time within this render list.
// Clear the buffer at this point.
- context.StencilMask(0xff);
- context.Clear(GL_STENCIL_BUFFER_BIT, Context::CHECK_CACHED_VALUES);
+
+ commandBuffer.SetStencilWriteMask(0xFF);
+ commandBuffer.ClearStencilBuffer();
}
else if((clippingDepth < lastClippingDepth) ||
((clippingDepth == lastClippingDepth) && (clippingId > lastClippingId)))
// This has the effect of clearing everything except the bit-planes up to (and including) our current depth.
const uint32_t stencilClearMask = (currentDepthMask >> 1u) ^ 0xff;
- context.StencilMask(stencilClearMask);
- context.Clear(GL_STENCIL_BUFFER_BIT, Context::CHECK_CACHED_VALUES);
+ commandBuffer.SetStencilWriteMask(stencilClearMask);
+ commandBuffer.ClearStencilBuffer();
}
// We keep track of the last clipping Id and depth so we can determine when we are
// As the mask is made up of contiguous "1" values, we can do this quickly with a bit-shift.
const uint32_t testMask = currentDepthMask >> 1u;
- context.StencilFunc(GL_EQUAL, currentDepthMask, testMask); // Test against existing stencil bit-planes. All must match up to (but not including) this depth.
- context.StencilMask(currentDepthMask); // Write to the new stencil bit-plane (the other previous bit-planes are also written to).
- context.StencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
+ // Test against existing stencil bit-planes. All must match up to (but not including) this depth.
+ commandBuffer.SetStencilFunc(Graphics::CompareOp::EQUAL, currentDepthMask, testMask);
+ // Write to the new stencil bit-plane (the other previous bit-planes are also written to).
+ commandBuffer.SetStencilWriteMask(currentDepthMask);
+ commandBuffer.SetStencilOp(Graphics::StencilOp::KEEP, Graphics::StencilOp::REPLACE, Graphics::StencilOp::REPLACE);
}
else
{
// We are reading from the stencil buffer. Set up the stencil accordingly
// This calculation sets all the bits up to the current depth bit.
// This has the effect of testing that the pixel being written to exists in every bit-plane up to the current depth.
- context.StencilFunc(GL_EQUAL, currentDepthMask, currentDepthMask);
- context.StencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ commandBuffer.SetStencilFunc(Graphics::CompareOp::EQUAL, currentDepthMask, currentDepthMask);
+ commandBuffer.SetStencilOp(Graphics::StencilOp::KEEP, Graphics::StencilOp::KEEP, Graphics::StencilOp::KEEP);
}
}
* - If AUTO is selected for reading, the decision will be based on the Layer Behavior.
* - If AUTO is selected for writing, the decision will be based on the items opacity.
* @param[in] item The RenderItem to set up the depth buffer for.
- * @param[in] context The context used to execute GL commands.
+ * @param[in,out] secondaryCommandBuffer The secondary command buffer to write depth commands to
* @param[in] depthTestEnabled True if depth testing has been enabled.
* @param[in/out] firstDepthBufferUse Initialize to true on the first call, this method will set it to false afterwards.
*/
-inline void SetupDepthBuffer(const RenderItem& item, Context& context, bool depthTestEnabled, bool& firstDepthBufferUse)
+inline void SetupDepthBuffer(const RenderItem& item, Graphics::CommandBuffer& commandBuffer, bool depthTestEnabled, bool& firstDepthBufferUse)
{
// Set up whether or not to write to the depth buffer.
const DepthWriteMode::Type depthWriteMode = item.mRenderer->GetDepthWriteMode();
// Set up whether or not to read from (test) the depth buffer.
const DepthTestMode::Type depthTestMode = item.mRenderer->GetDepthTestMode();
+
// Most common mode (AUTO) is tested first.
const bool enableDepthTest = ((depthTestMode == DepthTestMode::AUTO) && depthTestEnabled) ||
(depthTestMode == DepthTestMode::ON);
if(enableDepthWrite || enableDepthTest)
{
// The depth buffer must be enabled if either reading or writing.
- context.EnableDepthBuffer(true);
+ commandBuffer.SetDepthTestEnable(true);
- // Look-up the GL depth function from the Dali::DepthFunction enum, and set it.
- context.DepthFunc(DaliDepthToGLDepthTable[item.mRenderer->GetDepthFunction()]);
+ // Look-up the depth function from the Dali::DepthFunction enum, and set it.
+ commandBuffer.SetDepthCompareOp(GraphicsDepthCompareOp(item.mRenderer->GetDepthFunction()).op);
// If this is the first use of the depth buffer this RenderTask, perform a clear.
// Note: We could do this at the beginning of the RenderTask and rely on the
- // context cache to ignore the clear if not required, but, we would have to enable
- // the depth buffer to do so, which could be a redundant enable.
+ // graphics implementation to ignore the clear if not required, but, we would
+ // have to enable the depth buffer to do so, which could be a redundant enable.
if(DALI_UNLIKELY(firstDepthBufferUse))
{
// This is the first time the depth buffer is being written to or read.
firstDepthBufferUse = false;
// Note: The buffer will only be cleared if written to since a previous clear.
- context.DepthMask(true);
- context.Clear(GL_DEPTH_BUFFER_BIT, Context::CHECK_CACHED_VALUES);
+ commandBuffer.SetDepthWriteEnable(true);
+ commandBuffer.ClearDepthBuffer();
}
// Set up the depth mask based on our depth write setting.
- context.DepthMask(enableDepthWrite);
+ commandBuffer.SetDepthWriteEnable(enableDepthWrite);
}
else
{
// The depth buffer is not being used by this renderer, so we must disable it to stop it being tested.
- context.EnableDepthBuffer(false);
+ commandBuffer.SetDepthTestEnable(false);
}
}
* A stack of scissor clips at each depth of clipping is maintained, so it can be applied and unapplied.
* As the clips are hierarchical, this RenderItems AABB is clipped against the current "active" scissor bounds via an intersection operation.
* @param[in] item The current RenderItem about to be rendered
- * @param[in] context The context
+ * @param[in,out] commandBuffer The command buffer to write into
* @param[in] instruction The render-instruction to process.
+ * @param[in] orientation The Scene's surface orientation.
*/
-inline void RenderAlgorithms::SetupScissorClipping(const RenderItem& item, Context& context, const RenderInstruction& instruction)
+inline void RenderAlgorithms::SetupScissorClipping(
+ const RenderItem& item,
+ Graphics::CommandBuffer& commandBuffer,
+ const RenderInstruction& instruction,
+ int orientation)
{
// Get the number of child scissors in the stack (do not include layer or root box).
size_t childStackDepth = mScissorStack.size() - 1u;
// This is a clipping node. We generate the AABB for this node and intersect it with the previous intersection further up the tree.
// Get the AABB bounding box for the current render item.
- const ClippingBox scissorBox(item.CalculateViewportSpaceAABB(item.mSize, mViewportRectangle.width, mViewportRectangle.height));
+ const ClippingBox scissorBox(RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, item.mSize, mViewportRectangle.width, mViewportRectangle.height));
// Get the AABB for the parent item that we must intersect with.
const ClippingBox& parentBox(mScissorStack.back());
// The scissor test is enabled if we have any children on the stack, OR, if there are none but it is a user specified layer scissor box.
// IE. It is not enabled if we are at the top of the stack and the layer does not have a specified clipping box.
- const bool scissorEnabled = (mScissorStack.size() > 0u) || mHasLayerScissor;
+ const bool scissorEnabled = (!mScissorStack.empty()) || mHasLayerScissor;
// Enable the scissor test based on the above calculation
- context.SetScissorTest(scissorEnabled);
+ if(scissorEnabled)
+ {
+ commandBuffer.SetScissorTestEnable(scissorEnabled);
+ }
// If scissor is enabled, we use the calculated screen-space coordinates (now in the stack).
if(scissorEnabled)
{
useScissorBox.y = (instruction.mFrameBuffer->GetHeight() - useScissorBox.height) - useScissorBox.y;
}
- context.Scissor(useScissorBox.x, useScissorBox.y, useScissorBox.width, useScissorBox.height);
+
+ Graphics::Viewport graphicsViewport = ViewportFromClippingBox(mViewportRectangle, 0);
+ commandBuffer.SetScissor(Rect2DFromClippingBox(useScissorBox, orientation, graphicsViewport));
}
}
}
inline void RenderAlgorithms::SetupClipping(const RenderItem& item,
- Context& context,
+ Graphics::CommandBuffer& commandBuffer,
bool& usedStencilBuffer,
uint32_t& lastClippingDepth,
uint32_t& lastClippingId,
Integration::StencilBufferAvailable stencilBufferAvailable,
- const RenderInstruction& instruction)
+ const RenderInstruction& instruction,
+ int orientation)
{
RenderMode::Type renderMode = RenderMode::AUTO;
const Renderer* renderer = item.mRenderer;
case RenderMode::AUTO:
{
// Turn the color buffer on as we always want to render this renderer, regardless of clipping hierarchy.
- context.ColorMask(true);
+ commandBuffer.SetColorMask(true);
// The automatic clipping feature will manage the scissor and stencil functions, only if stencil buffer is available for the latter.
// As both scissor and stencil clips can be nested, we may be simultaneously traversing up the scissor tree, requiring a scissor to be un-done. Whilst simultaneously adding a new stencil clip.
// We process both based on our current and old clipping depths for each mode.
// Both methods with return rapidly if there is nothing to be done for that type of clipping.
- SetupScissorClipping(item, context, instruction);
+ SetupScissorClipping(item, commandBuffer, instruction, orientation);
if(stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
{
- SetupStencilClipping(item, context, lastClippingDepth, lastClippingId);
+ SetupStencilClipping(item, commandBuffer, lastClippingDepth, lastClippingId);
}
break;
}
// The stencil buffer will not be used at all, but we only need to disable it if it's available.
if(stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
{
- context.EnableStencilBuffer(false);
+ commandBuffer.SetStencilTestEnable(false);
}
// Setup the color buffer based on the RenderMode.
- context.ColorMask(renderMode == RenderMode::COLOR);
+ commandBuffer.SetColorMask(renderMode == RenderMode::COLOR);
break;
}
// We are using the low-level Renderer Stencil API.
// The stencil buffer must be enabled for every renderer with stencil mode on, as renderers in between can disable it.
// Note: As the command state is cached, it is only sent when needed.
- context.EnableStencilBuffer(true);
+ commandBuffer.SetStencilTestEnable(true);
// Setup the color buffer based on the RenderMode.
- context.ColorMask(renderMode == RenderMode::COLOR_STENCIL);
+ commandBuffer.SetColorMask(renderMode == RenderMode::COLOR_STENCIL);
// If this is the first use of the stencil buffer within this RenderList, clear it (this avoids unnecessary clears).
if(!usedStencilBuffer)
{
- context.Clear(GL_STENCIL_BUFFER_BIT, Context::CHECK_CACHED_VALUES);
+ commandBuffer.ClearStencilBuffer();
usedStencilBuffer = true;
}
- // Setup the stencil buffer based on the renderers properties.
- context.StencilFunc(DaliStencilFunctionToGL[renderer->GetStencilFunction()],
- renderer->GetStencilFunctionReference(),
- renderer->GetStencilFunctionMask());
- context.StencilOp(DaliStencilOperationToGL[renderer->GetStencilOperationOnFail()],
- DaliStencilOperationToGL[renderer->GetStencilOperationOnZFail()],
- DaliStencilOperationToGL[renderer->GetStencilOperationOnZPass()]);
- context.StencilMask(renderer->GetStencilMask());
+ // Setup the stencil buffer based on the renderer's properties.
+ commandBuffer.SetStencilOp(GraphicsStencilOp(renderer->GetStencilOperationOnFail()).op,
+ GraphicsStencilOp(renderer->GetStencilOperationOnZPass()).op,
+ GraphicsStencilOp(renderer->GetStencilOperationOnZFail()).op);
+ commandBuffer.SetStencilFunc(GraphicsStencilCompareOp(renderer->GetStencilFunction()).op,
+ renderer->GetStencilFunctionReference(),
+ renderer->GetStencilFunctionMask());
+ commandBuffer.SetStencilWriteMask(renderer->GetStencilMask());
}
break;
}
}
inline void RenderAlgorithms::ProcessRenderList(const RenderList& renderList,
- Context& context,
BufferIndex bufferIndex,
const Matrix& viewMatrix,
const Matrix& projectionMatrix,
bool usedStencilBuffer(false);
bool firstDepthBufferUse(true);
- if(!mGraphicsCommandBuffer)
- {
- mGraphicsCommandBuffer = mGraphicsController.CreateCommandBuffer(
- Graphics::CommandBufferCreateInfo()
- .SetLevel(Graphics::CommandBufferLevel::SECONDARY),
- nullptr);
- }
- else
- {
- mGraphicsCommandBuffer->Reset();
- }
-
mViewportRectangle = viewport;
- mGraphicsCommandBuffer->SetViewport(ViewportFromClippingBox(mViewportRectangle, orientation));
+
+ auto* mutableRenderList = const_cast<RenderList*>(&renderList);
+ auto& secondaryCommandBuffer = mutableRenderList->GetCommandBuffer(mGraphicsController);
+ secondaryCommandBuffer.Reset();
+
+ secondaryCommandBuffer.SetViewport(ViewportFromClippingBox(mViewportRectangle, orientation));
mHasLayerScissor = false;
// Setup Scissor testing (for both viewport and per-node scissor)
if(!rootClippingRect.IsEmpty())
{
Graphics::Viewport graphicsViewport = ViewportFromClippingBox(mViewportRectangle, 0);
- mGraphicsCommandBuffer->SetScissorTestEnable(true);
- mGraphicsCommandBuffer->SetScissor(Rect2DFromRect(rootClippingRect, orientation, graphicsViewport));
+ secondaryCommandBuffer.SetScissorTestEnable(true);
+ secondaryCommandBuffer.SetScissor(Rect2DFromRect(rootClippingRect, orientation, graphicsViewport));
mScissorStack.push_back(rootClippingRect);
}
// We are not performing a layer clip and no clipping rect set. Add the viewport as the root scissor rectangle.
else if(!renderList.IsClipping())
{
- mGraphicsCommandBuffer->SetScissorTestEnable(false);
+ secondaryCommandBuffer.SetScissorTestEnable(false);
mScissorStack.push_back(mViewportRectangle);
}
if(renderList.IsClipping())
{
Graphics::Viewport graphicsViewport = ViewportFromClippingBox(mViewportRectangle, 0);
- mGraphicsCommandBuffer->SetScissorTestEnable(true);
+ secondaryCommandBuffer.SetScissorTestEnable(true);
const ClippingBox& layerScissorBox = renderList.GetClippingBox();
- mGraphicsCommandBuffer->SetScissor(Rect2DFromClippingBox(layerScissorBox, orientation, graphicsViewport));
+ secondaryCommandBuffer.SetScissor(Rect2DFromClippingBox(layerScissorBox, orientation, graphicsViewport));
mScissorStack.push_back(layerScissorBox);
mHasLayerScissor = true;
}
- // Submit scissor/viewport
- Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH};
- submitInfo.cmdBuffer.push_back(mGraphicsCommandBuffer.get());
- mGraphicsController.SubmitCommandBuffers(submitInfo);
-
- // Loop through all RenderList in the RenderList, set up any prerequisites to render them, then perform the render.
+ // Loop through all RenderItems in the RenderList, set up any prerequisites to render them, then perform the render.
for(uint32_t index = 0u; index < count; ++index)
{
const RenderItem& item = renderList.GetItem(index);
bool skip = true;
if(!rootClippingRect.IsEmpty())
{
- auto rect = item.CalculateViewportSpaceAABB(item.mUpdateSize, mViewportRectangle.width, mViewportRectangle.height);
+ auto rect = RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, item.mUpdateSize, mViewportRectangle.width, mViewportRectangle.height);
if(rect.Intersect(rootClippingRect))
{
// Set up clipping based on both the Renderer and Actor APIs.
// The Renderer API will be used if specified. If AUTO, the Actors automatic clipping feature will be used.
- SetupClipping(item, context, usedStencilBuffer, lastClippingDepth, lastClippingId, stencilBufferAvailable, instruction);
+ SetupClipping(item, secondaryCommandBuffer, usedStencilBuffer, lastClippingDepth, lastClippingId, stencilBufferAvailable, instruction, orientation);
if(DALI_LIKELY(item.mRenderer))
{
// Set up the depth buffer based on per-renderer flags if depth buffer is available
// If the per renderer flags are set to "ON" or "OFF", they will always override any Layer depth mode or
// draw-mode state, such as Overlays.
- // If the flags are set to "AUTO", the behavior then depends on the type of renderer. Overlay Renderers will always
- // disable depth testing and writing. Color Renderers will enable them if the Layer does.
+ // If the flags are set to "AUTO", the behavior then depends on the type of renderer. Overlay Renderers will
+ // always disable depth testing and writing. Color Renderers will enable them if the Layer does.
if(depthBufferAvailable == Integration::DepthBufferAvailable::TRUE)
{
- SetupDepthBuffer(item, context, autoDepthTestMode, firstDepthBufferUse);
+ SetupDepthBuffer(item, secondaryCommandBuffer, autoDepthTestMode, firstDepthBufferUse);
}
// Depending on whether the renderer has draw commands attached or not the rendering process will
auto const MAX_QUEUE = item.mRenderer->GetDrawCommands().empty() ? 1 : DevelRenderer::RENDER_QUEUE_MAX;
for(auto queue = 0u; queue < MAX_QUEUE; ++queue)
{
- // Render the item.
- item.mRenderer->Render(context, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque, boundTextures, instruction, queue);
+ // Render the item. It will write into the command buffer everything it has to render
+ item.mRenderer->Render(secondaryCommandBuffer, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque, boundTextures, instruction, queue);
}
}
}
{
}
+void RenderAlgorithms::ResetCommandBuffer()
+{
+ // Reset main command buffer
+ if(!mGraphicsCommandBuffer)
+ {
+ mGraphicsCommandBuffer = mGraphicsController.CreateCommandBuffer(
+ Graphics::CommandBufferCreateInfo()
+ .SetLevel(Graphics::CommandBufferLevel::PRIMARY),
+ nullptr);
+ }
+ else
+ {
+ mGraphicsCommandBuffer->Reset();
+ }
+}
+
+void RenderAlgorithms::SubmitCommandBuffer()
+{
+ // Submit main command buffer
+ Graphics::SubmitInfo submitInfo;
+ submitInfo.cmdBuffer.push_back(mGraphicsCommandBuffer.get());
+ submitInfo.flags = 0 | Graphics::SubmitFlagBits::FLUSH;
+ mGraphicsController.SubmitCommandBuffers(submitInfo);
+}
+
void RenderAlgorithms::ProcessRenderInstruction(const RenderInstruction& instruction,
- Context& context,
BufferIndex bufferIndex,
Integration::DepthBufferAvailable depthBufferAvailable,
Integration::StencilBufferAvailable stencilBufferAvailable,
if(viewMatrix && projectionMatrix)
{
- const RenderListContainer::SizeType count = instruction.RenderListCount();
+ std::vector<const Graphics::CommandBuffer*> buffers;
+ const RenderListContainer::SizeType count = instruction.RenderListCount();
// Iterate through each render list in order. If a pair of render lists
// are marked as interleaved, then process them together.
if(renderList && !renderList->IsEmpty())
{
ProcessRenderList(*renderList,
- context,
bufferIndex,
*viewMatrix,
*projectionMatrix,
viewport,
rootClippingRect,
orientation);
+
+ // Execute command buffer
+ auto* commandBuffer = renderList->GetCommandBuffer();
+ if(commandBuffer)
+ {
+ buffers.push_back(commandBuffer);
+ }
}
}
+ if(!buffers.empty())
+ {
+ mGraphicsCommandBuffer->ExecuteCommandBuffers(std::move(buffers));
+ }
}
}