/*
* Copyright (c) 2024 Huawei Device 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.
*/
#ifndef GLES_RENDER_BACKEND_GLES_H
#define GLES_RENDER_BACKEND_GLES_H
#include
#include
#include
#include "nodecontext/render_command_list.h"
#include "render_backend.h"
#if defined(RENDER_PERF_ENABLED) && (RENDER_PERF_ENABLED == 1)
#include
#include "device/gpu_buffer.h"
#include "perf/cpu_timer.h"
#include "perf/gpu_query_manager.h"
#endif
RENDER_BEGIN_NAMESPACE()
class GpuShaderProgramGLES;
class GpuComputeProgramGLES;
class GpuSamplerGLES;
class GpuImageGLES;
class GpuBufferGLES;
class Device;
class DeviceGLES;
class GpuResourceManager;
class NodeContextPsoManager;
class NodeContextPoolManager;
class RenderBarrierList;
class RenderCommandList;
struct RenderCommandContext;
struct LowLevelCommandBuffer;
struct LowlevelFramebufferGL;
class ComputePipelineStateObjectGLES;
class GraphicsPipelineStateObjectGLES;
struct NodeGraphBackBufferConfiguration;
struct OES_Bind;
namespace Gles {
struct CombinedSamplerInfo;
struct PushConstantReflection;
struct BindMaps;
struct Bind;
} // namespace Gles
struct GpuBufferPlatformDataGL;
struct GpuSamplerPlatformDataGL;
struct GpuImagePlatformDataGL;
/**
RenderBackGLES.
OpenGLES 3.2+ render backend.
(also used for OpenGL 4.5+ on desktop)
**/
class RenderBackendGLES final : public RenderBackend {
public:
RenderBackendGLES(Device& device, GpuResourceManager& gpuResourceManager);
~RenderBackendGLES();
void Render(RenderCommandFrameData& renderCommandFrameData,
const RenderBackendBackBufferConfiguration& backBufferConfig) override;
void Present(const RenderBackendBackBufferConfiguration& backBufferConfig) override;
private:
void RenderSingleCommandList(const RenderCommandContext& renderCommandCtx);
void RenderProcessEndCommandLists(
RenderCommandFrameData& renderCommandFrameData, const RenderBackendBackBufferConfiguration& backBufferConfig);
void RenderCommandDraw(const RenderCommandWithType&);
void RenderCommandDrawIndirect(const RenderCommandWithType&);
void RenderCommandDispatch(const RenderCommandWithType&);
void RenderCommandDispatchIndirect(const RenderCommandWithType&);
void RenderCommandBindPipeline(const RenderCommandWithType&);
void BindGraphicsPipeline(const struct RenderCommandBindPipeline&);
void BindComputePipeline(const struct RenderCommandBindPipeline&);
void RenderCommandBindVertexBuffers(const RenderCommandWithType&);
void RenderCommandBindIndexBuffer(const RenderCommandWithType&);
void RenderCommandBeginRenderPass(const RenderCommandWithType&);
void RenderCommandNextSubpass(const RenderCommandWithType&);
void RenderCommandEndRenderPass(const RenderCommandWithType&);
void RenderCommandCopyBuffer(const RenderCommandWithType&);
void RenderCommandCopyBufferImage(const RenderCommandWithType&);
void RenderCommandCopyImage(const RenderCommandWithType&);
void RenderCommandBlitImage(const RenderCommandWithType&);
void RenderCommandBarrierPoint(const RenderCommandWithType&);
void RenderCommandBindDescriptorSets(const RenderCommandWithType&);
void RenderCommandPushConstant(const RenderCommandWithType&);
void RenderCommandClearColorImage(const RenderCommandWithType&);
void RenderCommandDynamicStateViewport(const RenderCommandWithType&);
void RenderCommandDynamicStateScissor(const RenderCommandWithType&);
void RenderCommandDynamicStateLineWidth(const RenderCommandWithType&);
void RenderCommandDynamicStateDepthBias(const RenderCommandWithType&);
void RenderCommandDynamicStateBlendConstants(const RenderCommandWithType&);
void RenderCommandDynamicStateDepthBounds(const RenderCommandWithType&);
void RenderCommandDynamicStateStencil(const RenderCommandWithType&);
void RenderCommandFragmentShadingRate(const RenderCommandWithType& renderCmd);
void RenderCommandExecuteBackendFramePosition(const RenderCommandWithType&);
void RenderCommandWriteTimestamp(const RenderCommandWithType&);
void RenderCommandUndefined(const RenderCommandWithType&);
typedef void (RenderBackendGLES::*RenderCommandHandler)(const RenderCommandWithType&);
// Following array must match in order of RenderCommandType
// Count of render command types
static constexpr uint32_t RENDER_COMMAND_COUNT = (static_cast(RenderCommandType::COUNT));
static constexpr RenderCommandHandler COMMAND_HANDLERS[RENDER_COMMAND_COUNT] = {
&RenderBackendGLES::RenderCommandUndefined, &RenderBackendGLES::RenderCommandDraw,
&RenderBackendGLES::RenderCommandDrawIndirect, &RenderBackendGLES::RenderCommandDispatch,
&RenderBackendGLES::RenderCommandDispatchIndirect, &RenderBackendGLES::RenderCommandBindPipeline,
&RenderBackendGLES::RenderCommandBeginRenderPass, &RenderBackendGLES::RenderCommandNextSubpass,
&RenderBackendGLES::RenderCommandEndRenderPass, &RenderBackendGLES::RenderCommandBindVertexBuffers,
&RenderBackendGLES::RenderCommandBindIndexBuffer, &RenderBackendGLES::RenderCommandCopyBuffer,
&RenderBackendGLES::RenderCommandCopyBufferImage, &RenderBackendGLES::RenderCommandCopyImage,
&RenderBackendGLES::RenderCommandBlitImage, &RenderBackendGLES::RenderCommandBarrierPoint,
&RenderBackendGLES::RenderCommandBindDescriptorSets, &RenderBackendGLES::RenderCommandPushConstant,
&RenderBackendGLES::RenderCommandUndefined, /* RenderCommandBuildAccelerationStructure */
&RenderBackendGLES::RenderCommandClearColorImage, &RenderBackendGLES::RenderCommandDynamicStateViewport,
&RenderBackendGLES::RenderCommandDynamicStateScissor, &RenderBackendGLES::RenderCommandDynamicStateLineWidth,
&RenderBackendGLES::RenderCommandDynamicStateDepthBias,
&RenderBackendGLES::RenderCommandDynamicStateBlendConstants,
&RenderBackendGLES::RenderCommandDynamicStateDepthBounds, &RenderBackendGLES::RenderCommandDynamicStateStencil,
&RenderBackendGLES::RenderCommandFragmentShadingRate,
&RenderBackendGLES::RenderCommandExecuteBackendFramePosition, &RenderBackendGLES::RenderCommandWriteTimestamp,
&RenderBackendGLES::RenderCommandUndefined, /* RenderCommandGpuQueueTransferRelease */
&RenderBackendGLES::RenderCommandUndefined /* RenderCommandGpuQueueTransferAcquire */
};
void PrimeCache(const GraphicsState& graphicsState); // Forces the graphics state..
void PrimeDepthStencilState(const GraphicsState& graphicsState);
void PrimeBlendState(const GraphicsState& graphicsState);
void DoGraphicsState(const GraphicsState& graphicsState);
void SetViewport(const RenderPassDesc::RenderArea& ra, const ViewportDesc& vd);
void SetScissor(const RenderPassDesc::RenderArea& ra, const ScissorDesc& sd);
void HandleColorAttachments(const BASE_NS::array_view colorAttachments);
void HandleDepthAttachment(const RenderPassDesc::AttachmentDesc& depthAttachment);
void ClearScissorInit(const RenderPassDesc::RenderArea& aArea);
void ClearScissorSet();
void ClearScissorReset();
static void SetPushConstant(uint32_t program, const Gles::PushConstantReflection& pc, const void* data);
void SetPushConstants(uint32_t program, const BASE_NS::array_view& pushConstants);
void DoSubPass(uint32_t subPass);
struct Managers {
NodeContextPsoManager* psoMgr { nullptr };
NodeContextPoolManager* poolMgr { nullptr };
NodeContextDescriptorSetManager* descriptorSetMgr { nullptr };
const RenderBarrierList* rbList { nullptr };
};
Managers managers_;
DeviceGLES& device_;
GpuResourceManager& gpuResourceMgr_;
struct PresentationInfo {
uint32_t swapchainImageIndex { ~0u };
};
PresentationInfo presentationInfo_;
#if defined(RENDER_PERF_ENABLED) && (RENDER_PERF_ENABLED == 1)
struct PerfCounters {
uint32_t drawCount;
uint32_t drawIndirectCount;
uint32_t dispatchCount;
uint32_t dispatchIndirectCount;
uint32_t renderPassCount;
uint32_t bindProgram;
uint32_t bindSampler;
uint32_t bindTexture;
uint32_t bindBuffer;
uint32_t triangleCount;
uint32_t instanceCount;
};
PerfCounters perfCounters_;
bool validGpuQueries_;
BASE_NS::unique_ptr gpuQueryMgr_;
struct PerfDataSet {
EngineResourceHandle gpuHandle;
CpuTimer cpuTimer;
uint32_t counter;
};
BASE_NS::unordered_map timers_;
void StartFrameTimers(const RenderCommandFrameData& renderCommandFrameData);
void EndFrameTimers();
void CopyPerfTimeStamp(BASE_NS::string_view aName, PerfDataSet& perfDataSet);
struct CommonBackendCpuTimers {
CpuTimer full;
CpuTimer acquire;
CpuTimer execute;
CpuTimer submit;
CpuTimer present;
};
CommonBackendCpuTimers commonCpuTimers_;
std::atomic_int64_t fullGpuCounter_ { 0 };
#endif
PolygonMode polygonMode_ = PolygonMode::CORE_POLYGON_MODE_FILL;
PrimitiveTopology topology_ = PrimitiveTopology::CORE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
struct ProgramState {
bool setPushConstants { false };
struct RenderCommandPushConstant pushConstants {};
} boundProgram_;
struct {
uint32_t id { 0 };
uintptr_t offset { 0 };
IndexType type { CORE_INDEX_TYPE_UINT32 };
} boundIndexBuffer_;
void ResetState();
void ResetBindings();
void SetupCache(const PipelineLayout& pipelineLayout);
struct BindState {
bool dirty { false };
#if defined(RENDER_HAS_GLES_BACKEND) && (RENDER_HAS_GLES_BACKEND == 1)
BASE_NS::vector oesBinds;
#endif
BASE_NS::vector resources;
};
BindState boundObjects_[PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT];
static Gles::Bind& SetupBind(const DescriptorSetLayoutBinding& res, BASE_NS::vector& resources);
void BindSampler(const BindableSampler& res, Gles::Bind& obj, uint32_t index);
void BindImage(const BindableImage& res, const GpuResourceState& resState, Gles::Bind& obj, uint32_t index);
void BindImageSampler(const BindableImage& res, const GpuResourceState& resState, Gles::Bind& obj, uint32_t index);
void BindBuffer(const BindableBuffer& res, Gles::Bind& obj, uint32_t dynamicOffset, uint32_t index);
void BindVertexInputs(
const VertexInputDeclarationData& decldata, const BASE_NS::array_view& vertexInputs);
void ProcessBindings(const struct RenderCommandBindDescriptorSets& renderCmd,
const DescriptorSetLayoutBindingResources& data, uint32_t set);
void ScanPasses(const RenderPassDesc& rpd);
int32_t InvalidateColor(BASE_NS::array_view invalidateAttachment, const RenderPassDesc& rpd,
const RenderPassSubpassDesc& currentSubPass);
int32_t InvalidateDepthStencil(BASE_NS::array_view invalidateAttachment, const RenderPassDesc& rpd,
const RenderPassSubpassDesc& currentSubPass);
uint32_t ResolveMSAA(const RenderPassDesc& rpd, const RenderPassSubpassDesc& currentSubPass);
void UpdateBlendState(const GraphicsState& graphicsState);
void UpdateDepthState(const GraphicsState& graphicsState);
void UpdateStencilState(const GraphicsState& graphicsState);
void UpdateDepthStencilState(const GraphicsState& graphicsState);
void UpdateRasterizationState(const GraphicsState& graphicsState);
void BindResources();
enum StencilSetFlags { SETOP = 1, SETCOMPAREMASK = 2, SETCOMPAREOP = 4, SETREFERENCE = 8, SETWRITEMASK = 16 };
void SetStencilState(const uint32_t frontFlags, const GraphicsState::StencilOpState& front,
const uint32_t backFlags, const GraphicsState::StencilOpState& back);
const ComputePipelineStateObjectGLES* boundComputePipeline_ = nullptr;
const GraphicsPipelineStateObjectGLES* boundGraphicsPipeline_ = nullptr;
RenderHandle currentPsoHandle_;
RenderPassDesc::RenderArea renderArea_;
struct RenderCommandBeginRenderPass activeRenderPass_;
uint32_t currentSubPass_ = 0;
const LowlevelFramebufferGL* currentFrameBuffer_ = nullptr;
// caching state
GraphicsState cacheState_;
bool cachePrimed_ = false;
DynamicStateFlags dynamicStateFlags_ = DynamicStateFlagBits::CORE_DYNAMIC_STATE_UNDEFINED;
bool viewportPrimed_ = false;
bool clearScissorSet_ = false;
bool resetScissor_ = false;
RenderPassDesc::RenderArea clearScissor_;
bool scissorPrimed_ = false;
ScissorDesc scissorBox_;
ViewportDesc viewport_;
static constexpr uint32_t MAX_VERTEXINPUT_BINDINGS { 16 };
uint32_t vertexAttribBinds_ = 0;
struct {
uint32_t id = 0;
intptr_t offset = 0;
} vertexAttribBindSlots_[MAX_VERTEXINPUT_BINDINGS];
// attachments are cleared on first use, and marked as cleared here.
bool attachmentCleared_[PipelineStateConstants::MAX_RENDER_PASS_ATTACHMENT_COUNT] = { false };
// subpass index where attachment is first used. (just for book keeping for now. clearing need is handled by
// "attachmentCleared" )
uint32_t attachmentFirstUse_[PipelineStateConstants::MAX_RENDER_PASS_ATTACHMENT_COUNT] = { 0xFFFFFFFF };
// subpass index where attachment is last used. (for invalidation purposes)
uint32_t attachmentLastUse_[PipelineStateConstants::MAX_RENDER_PASS_ATTACHMENT_COUNT] = { 0 };
// will the attachment be resolved to backbuffer.. (if so flip coordinates)
bool resolveToBackbuffer_[PipelineStateConstants::MAX_RENDER_PASS_ATTACHMENT_COUNT] = { false };
const GpuImageGLES* attachmentImage_[PipelineStateConstants::MAX_RENDER_PASS_ATTACHMENT_COUNT] { nullptr };
bool multisampledRenderToTexture_ = false;
uint32_t blitImageSourceFbo_ { 0 };
uint32_t blitImageDestinationFbo_ { 0 };
uint32_t inRenderpass_ { 0 };
bool scissorViewportSetDefaultFbo_ { false };
bool renderingToDefaultFbo_ { false };
bool scissorEnabled_ { false };
bool scissorBoxUpdated_ { false };
bool viewportDepthRangeUpdated_ { false };
bool viewportUpdated_ { false };
bool commandListValid_ { false };
void FlushViewportScissors();
void BufferToImageCopy(const struct RenderCommandCopyBufferImage& renderCmd);
void ImageToBufferCopy(const struct RenderCommandCopyBufferImage& renderCmd);
#if defined(RENDER_HAS_GLES_BACKEND) && (RENDER_HAS_GLES_BACKEND == 1)
BASE_NS::vector oesBinds_;
#endif
};
RENDER_END_NAMESPACE()
#endif // GLES_RENDER_BACKEND_GLES_H