diff options
Diffstat (limited to 'src/gui/rhi/qrhigles2_p.h')
-rw-r--r-- | src/gui/rhi/qrhigles2_p.h | 1128 |
1 files changed, 1110 insertions, 18 deletions
diff --git a/src/gui/rhi/qrhigles2_p.h b/src/gui/rhi/qrhigles2_p.h index e3f4fbe7d7..4139579864 100644 --- a/src/gui/rhi/qrhigles2_p.h +++ b/src/gui/rhi/qrhigles2_p.h @@ -1,8 +1,8 @@ -// Copyright (C) 2019 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only -#ifndef QRHIGLES2_H -#define QRHIGLES2_H +#ifndef QRHIGLES2_P_H +#define QRHIGLES2_P_H // // W A R N I N G @@ -15,33 +15,1125 @@ // We mean it. // -#include <private/qrhi_p.h> -#include <QtGui/qsurfaceformat.h> +#include "qrhi_p.h" +#include <rhi/qshaderdescription.h> +#include <qopengl.h> +#include <QByteArray> +#include <QWindow> +#include <QPointer> +#include <QtCore/private/qduplicatetracker_p.h> +#include <optional> QT_BEGIN_NAMESPACE -class QOpenGLContext; -class QOffscreenSurface; -class QSurface; -class QWindow; +class QOpenGLExtensions; +class QRhiGles2; -struct Q_GUI_EXPORT QRhiGles2InitParams : public QRhiInitParams +struct QGles2Buffer : public QRhiBuffer { - QRhiGles2InitParams(); + QGles2Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size); + ~QGles2Buffer(); + void destroy() override; + bool create() override; + QRhiBuffer::NativeBuffer nativeBuffer() override; + char *beginFullDynamicBufferUpdateForCurrentFrame() override; + void endFullDynamicBufferUpdateForCurrentFrame() override; - QSurfaceFormat format; - QSurface *fallbackSurface = nullptr; - QWindow *window = nullptr; - QOpenGLContext *shareContext = nullptr; + quint32 nonZeroSize = 0; + GLuint buffer = 0; + GLenum targetForDataOps; + QByteArray data; + enum Access { + AccessNone, + AccessVertex, + AccessIndex, + AccessUniform, + AccessStorageRead, + AccessStorageWrite, + AccessStorageReadWrite, + AccessUpdate + }; + struct UsageState { + Access access; + }; + UsageState usageState; + friend class QRhiGles2; +}; + +struct QGles2RenderBuffer : public QRhiRenderBuffer +{ + QGles2RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, + int sampleCount, QRhiRenderBuffer::Flags flags, + QRhiTexture::Format backingFormatHint); + ~QGles2RenderBuffer(); + void destroy() override; + bool create() override; + bool createFrom(NativeRenderBuffer src) override; + QRhiTexture::Format backingFormat() const override; + + GLuint renderbuffer = 0; + GLuint stencilRenderbuffer = 0; // when packed depth-stencil not supported + int samples; + bool owns = true; + uint generation = 0; + friend class QRhiGles2; +}; + +struct QGles2SamplerData +{ + GLenum glminfilter = 0; + GLenum glmagfilter = 0; + GLenum glwraps = 0; + GLenum glwrapt = 0; + GLenum glwrapr = 0; + GLenum gltexcomparefunc = 0; +}; + +inline bool operator==(const QGles2SamplerData &a, const QGles2SamplerData &b) +{ + return a.glminfilter == b.glminfilter + && a.glmagfilter == b.glmagfilter + && a.glwraps == b.glwraps + && a.glwrapt == b.glwrapt + && a.glwrapr == b.glwrapr + && a.gltexcomparefunc == b.gltexcomparefunc; +} + +inline bool operator!=(const QGles2SamplerData &a, const QGles2SamplerData &b) +{ + return !(a == b); +} + +struct QGles2Texture : public QRhiTexture +{ + QGles2Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth, + int arraySize, int sampleCount, Flags flags); + ~QGles2Texture(); + void destroy() override; + bool create() override; + bool createFrom(NativeTexture src) override; + NativeTexture nativeTexture() override; + + bool prepareCreate(QSize *adjustedSize = nullptr); + + GLuint texture = 0; + bool owns = true; + GLenum target; + GLenum glintformat; + GLenum glsizedintformat; + GLenum glformat; + GLenum gltype; + QGles2SamplerData samplerState; + bool specified = false; + bool zeroInitialized = false; + int mipLevelCount = 0; + + enum Access { + AccessNone, + AccessSample, + AccessFramebuffer, + AccessStorageRead, + AccessStorageWrite, + AccessStorageReadWrite, + AccessUpdate, + AccessRead + }; + struct UsageState { + Access access; + }; + UsageState usageState; + + uint generation = 0; + friend class QRhiGles2; +}; + +struct QGles2Sampler : public QRhiSampler +{ + QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, + AddressMode u, AddressMode v, AddressMode w); + ~QGles2Sampler(); + void destroy() override; + bool create() override; + + QGles2SamplerData d; + uint generation = 0; + friend class QRhiGles2; +}; + +struct QGles2RenderPassDescriptor : public QRhiRenderPassDescriptor +{ + QGles2RenderPassDescriptor(QRhiImplementation *rhi); + ~QGles2RenderPassDescriptor(); + void destroy() override; + bool isCompatible(const QRhiRenderPassDescriptor *other) const override; + QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; + QVector<quint32> serializedFormat() const override; +}; + +struct QGles2RenderTargetData +{ + QGles2RenderTargetData(QRhiImplementation *) { } + + bool isValid() const { return rp != nullptr; } + + QGles2RenderPassDescriptor *rp = nullptr; + QSize pixelSize; + float dpr = 1; + int sampleCount = 1; + int colorAttCount = 0; + int dsAttCount = 0; + bool srgbUpdateAndBlend = false; + QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList; + std::optional<QRhiSwapChain::StereoTargetBuffer> stereoTarget; +}; + +struct QGles2SwapChainRenderTarget : public QRhiSwapChainRenderTarget +{ + QGles2SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain); + ~QGles2SwapChainRenderTarget(); + void destroy() override; + + QSize pixelSize() const override; + float devicePixelRatio() const override; + int sampleCount() const override; - static QOffscreenSurface *newFallbackSurface(const QSurfaceFormat &format = QSurfaceFormat::defaultFormat()); + QGles2RenderTargetData d; }; -struct Q_GUI_EXPORT QRhiGles2NativeHandles : public QRhiNativeHandles +struct QGles2TextureRenderTarget : public QRhiTextureRenderTarget { - QOpenGLContext *context = nullptr; + QGles2TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags); + ~QGles2TextureRenderTarget(); + void destroy() override; + + QSize pixelSize() const override; + float devicePixelRatio() const override; + int sampleCount() const override; + + QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; + bool create() override; + + QGles2RenderTargetData d; + GLuint framebuffer = 0; + GLuint nonMsaaThrowawayDepthTexture = 0; + friend class QRhiGles2; +}; + +struct QGles2ShaderResourceBindings : public QRhiShaderResourceBindings +{ + QGles2ShaderResourceBindings(QRhiImplementation *rhi); + ~QGles2ShaderResourceBindings(); + void destroy() override; + bool create() override; + void updateResources(UpdateFlags flags) override; + + bool hasDynamicOffset = false; + uint generation = 0; + friend class QRhiGles2; }; +struct QGles2UniformDescription +{ + QShaderDescription::VariableType type; + int glslLocation; + int binding; + quint32 offset; + quint32 size; + int arrayDim; +}; + +Q_DECLARE_TYPEINFO(QGles2UniformDescription, Q_RELOCATABLE_TYPE); + +struct QGles2SamplerDescription +{ + int glslLocation; + int combinedBinding; + int tbinding; + int sbinding; +}; + +Q_DECLARE_TYPEINFO(QGles2SamplerDescription, Q_RELOCATABLE_TYPE); + +using QGles2UniformDescriptionVector = QVarLengthArray<QGles2UniformDescription, 8>; +using QGles2SamplerDescriptionVector = QVarLengthArray<QGles2SamplerDescription, 4>; + +struct QGles2UniformState +{ + static constexpr int MAX_TRACKED_LOCATION = 1023; + int componentCount; + float v[4]; +}; + +struct QGles2GraphicsPipeline : public QRhiGraphicsPipeline +{ + QGles2GraphicsPipeline(QRhiImplementation *rhi); + ~QGles2GraphicsPipeline(); + void destroy() override; + bool create() override; + + GLuint program = 0; + GLenum drawMode = GL_TRIANGLES; + QGles2UniformDescriptionVector uniforms; + QGles2SamplerDescriptionVector samplers; + QGles2UniformState uniformState[QGles2UniformState::MAX_TRACKED_LOCATION + 1]; + QRhiShaderResourceBindings *currentSrb = nullptr; + uint currentSrbGeneration = 0; + uint generation = 0; + friend class QRhiGles2; +}; + +struct QGles2ComputePipeline : public QRhiComputePipeline +{ + QGles2ComputePipeline(QRhiImplementation *rhi); + ~QGles2ComputePipeline(); + void destroy() override; + bool create() override; + + GLuint program = 0; + QGles2UniformDescriptionVector uniforms; + QGles2SamplerDescriptionVector samplers; + QGles2UniformState uniformState[QGles2UniformState::MAX_TRACKED_LOCATION + 1]; + QRhiShaderResourceBindings *currentSrb = nullptr; + uint currentSrbGeneration = 0; + uint generation = 0; + friend class QRhiGles2; +}; + +struct QGles2CommandBuffer : public QRhiCommandBuffer +{ + QGles2CommandBuffer(QRhiImplementation *rhi); + ~QGles2CommandBuffer(); + void destroy() override; + + // keep at a reasonably low value otherwise sizeof Command explodes + static const int MAX_DYNAMIC_OFFSET_COUNT = 8; + + struct Command { + enum Cmd { + BeginFrame, + EndFrame, + ResetFrame, + Viewport, + Scissor, + BlendConstants, + StencilRef, + BindVertexBuffer, + BindIndexBuffer, + Draw, + DrawIndexed, + BindGraphicsPipeline, + BindShaderResources, + BindFramebuffer, + Clear, + BufferSubData, + GetBufferSubData, + CopyTex, + ReadPixels, + SubImage, + CompressedImage, + CompressedSubImage, + BlitFromRenderbuffer, + BlitFromTexture, + GenMip, + BindComputePipeline, + Dispatch, + BarriersForPass, + Barrier, + InvalidateFramebuffer + }; + Cmd cmd; + + // QRhi*/QGles2* references should be kept at minimum (so no + // QRhiTexture/Buffer/etc. pointers). + union Args { + struct { + GLuint timestampQuery; + } beginFrame; + struct { + GLuint timestampQuery; + } endFrame; + struct { + float x, y, w, h; + float d0, d1; + } viewport; + struct { + int x, y, w, h; + } scissor; + struct { + float r, g, b, a; + } blendConstants; + struct { + quint32 ref; + QRhiGraphicsPipeline *ps; + } stencilRef; + struct { + QRhiGraphicsPipeline *ps; + GLuint buffer; + quint32 offset; + int binding; + } bindVertexBuffer; + struct { + GLuint buffer; + quint32 offset; + GLenum type; + } bindIndexBuffer; + struct { + QRhiGraphicsPipeline *ps; + quint32 vertexCount; + quint32 firstVertex; + quint32 instanceCount; + quint32 baseInstance; + } draw; + struct { + QRhiGraphicsPipeline *ps; + quint32 indexCount; + quint32 firstIndex; + quint32 instanceCount; + quint32 baseInstance; + qint32 baseVertex; + } drawIndexed; + struct { + QRhiGraphicsPipeline *ps; + } bindGraphicsPipeline; + struct { + QRhiGraphicsPipeline *maybeGraphicsPs; + QRhiComputePipeline *maybeComputePs; + QRhiShaderResourceBindings *srb; + int dynamicOffsetCount; + uint dynamicOffsetPairs[MAX_DYNAMIC_OFFSET_COUNT * 2]; // binding, offset + } bindShaderResources; + struct { + GLbitfield mask; + float c[4]; + float d; + quint32 s; + } clear; + struct { + GLuint fbo; + bool srgb; + int colorAttCount; + bool stereo; + QRhiSwapChain::StereoTargetBuffer stereoTarget; + } bindFramebuffer; + struct { + GLenum target; + GLuint buffer; + int offset; + int size; + const void *data; // must come from retainData() + } bufferSubData; + struct { + QRhiReadbackResult *result; + GLenum target; + GLuint buffer; + int offset; + int size; + } getBufferSubData; + struct { + GLenum srcTarget; + GLenum srcFaceTarget; + GLuint srcTexture; + int srcLevel; + int srcX; + int srcY; + int srcZ; + GLenum dstTarget; + GLuint dstTexture; + GLenum dstFaceTarget; + int dstLevel; + int dstX; + int dstY; + int dstZ; + int w; + int h; + } copyTex; + struct { + QRhiReadbackResult *result; + GLuint texture; + int w; + int h; + QRhiTexture::Format format; + GLenum readTarget; + int level; + int slice3D; + } readPixels; + struct { + GLenum target; + GLuint texture; + GLenum faceTarget; + int level; + int dx; + int dy; + int dz; + int w; + int h; + GLenum glformat; + GLenum gltype; + int rowStartAlign; + int rowLength; + const void *data; // must come from retainImage() + } subImage; + struct { + GLenum target; + GLuint texture; + GLenum faceTarget; + int level; + GLenum glintformat; + int w; + int h; + int depth; + int size; + const void *data; // must come from retainData() + } compressedImage; + struct { + GLenum target; + GLuint texture; + GLenum faceTarget; + int level; + int dx; + int dy; + int dz; + int w; + int h; + GLenum glintformat; + int size; + const void *data; // must come from retainData() + } compressedSubImage; + struct { + GLuint renderbuffer; + int w; + int h; + GLenum target; + GLuint dstTexture; + int dstLevel; + int dstLayer; + bool isDepthStencil; + } blitFromRenderbuffer; + struct { + GLenum srcTarget; + GLuint srcTexture; + int srcLevel; + int srcLayer; + int w; + int h; + GLenum dstTarget; + GLuint dstTexture; + int dstLevel; + int dstLayer; + bool isDepthStencil; + } blitFromTexture; + struct { + GLenum target; + GLuint texture; + } genMip; + struct { + QRhiComputePipeline *ps; + } bindComputePipeline; + struct { + GLuint x; + GLuint y; + GLuint z; + } dispatch; + struct { + int trackerIndex; + } barriersForPass; + struct { + GLbitfield barriers; + } barrier; + struct { + int attCount; + GLenum att[3]; + } invalidateFramebuffer; + } args; + }; + + enum PassType { + NoPass, + RenderPass, + ComputePass + }; + + QRhiBackendCommandList<Command> commands; + QVarLengthArray<QRhiPassResourceTracker, 8> passResTrackers; + int currentPassResTrackerIndex; + + PassType recordingPass; + bool passNeedsResourceTracking; + double lastGpuTime = 0; + QRhiRenderTarget *currentTarget; + QRhiGraphicsPipeline *currentGraphicsPipeline; + QRhiComputePipeline *currentComputePipeline; + uint currentPipelineGeneration; + QRhiShaderResourceBindings *currentGraphicsSrb; + QRhiShaderResourceBindings *currentComputeSrb; + uint currentSrbGeneration; + + struct GraphicsPassState { + bool valid = false; + bool scissor; + bool cullFace; + GLenum cullMode; + GLenum frontFace; + bool blendEnabled; + struct ColorMask { bool r, g, b, a; } colorMask; + struct Blend { + GLenum srcColor; + GLenum dstColor; + GLenum srcAlpha; + GLenum dstAlpha; + GLenum opColor; + GLenum opAlpha; + } blend; + bool depthTest; + bool depthWrite; + GLenum depthFunc; + bool stencilTest; + GLuint stencilReadMask; + GLuint stencilWriteMask; + struct StencilFace { + GLenum func; + GLenum failOp; + GLenum zfailOp; + GLenum zpassOp; + } stencil[2]; // front, back + bool polyOffsetFill; + float polyOffsetFactor; + float polyOffsetUnits; + float lineWidth; + int cpCount; + GLenum polygonMode; + void reset() { valid = false; } + struct { + // not part of QRhiGraphicsPipeline but used by setGraphicsPipeline() + GLint stencilRef = 0; + } dynamic; + } graphicsPassState; + + struct ComputePassState { + enum Access { + Read = 0x01, + Write = 0x02 + }; + QHash<QRhiResource *, QPair<int, bool> > writtenResources; + void reset() { + writtenResources.clear(); + } + } computePassState; + + struct TextureUnitState { + void *ps; + uint psGeneration; + uint texture; + } textureUnitState[16]; + + QVarLengthArray<QByteArray, 4> dataRetainPool; + QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool; + QVarLengthArray<QImage, 4> imageRetainPool; + + // relies heavily on implicit sharing (no copies of the actual data will be made) + const void *retainData(const QByteArray &data) { + dataRetainPool.append(data); + return dataRetainPool.last().constData(); + } + const uchar *retainBufferData(const QRhiBufferData &data) { + bufferDataRetainPool.append(data); + return reinterpret_cast<const uchar *>(bufferDataRetainPool.last().constData()); + } + const void *retainImage(const QImage &image) { + imageRetainPool.append(image); + return imageRetainPool.last().constBits(); + } + void resetCommands() { + commands.reset(); + dataRetainPool.clear(); + bufferDataRetainPool.clear(); + imageRetainPool.clear(); + + passResTrackers.clear(); + currentPassResTrackerIndex = -1; + } + void resetState() { + recordingPass = NoPass; + passNeedsResourceTracking = true; + // do not zero lastGpuTime + currentTarget = nullptr; + resetCommands(); + resetCachedState(); + } + void resetCachedState() { + currentGraphicsPipeline = nullptr; + currentComputePipeline = nullptr; + currentPipelineGeneration = 0; + currentGraphicsSrb = nullptr; + currentComputeSrb = nullptr; + currentSrbGeneration = 0; + graphicsPassState.reset(); + computePassState.reset(); + memset(textureUnitState, 0, sizeof(textureUnitState)); + } +}; + +inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a, + const QGles2CommandBuffer::GraphicsPassState::StencilFace &b) +{ + return a.func == b.func + && a.failOp == b.failOp + && a.zfailOp == b.zfailOp + && a.zpassOp == b.zpassOp; +} + +inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a, + const QGles2CommandBuffer::GraphicsPassState::StencilFace &b) +{ + return !(a == b); +} + +inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a, + const QGles2CommandBuffer::GraphicsPassState::ColorMask &b) +{ + return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a; +} + +inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a, + const QGles2CommandBuffer::GraphicsPassState::ColorMask &b) +{ + return !(a == b); +} + +inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::Blend &a, + const QGles2CommandBuffer::GraphicsPassState::Blend &b) +{ + return a.srcColor == b.srcColor + && a.dstColor == b.dstColor + && a.srcAlpha == b.srcAlpha + && a.dstAlpha == b.dstAlpha + && a.opColor == b.opColor + && a.opAlpha == b.opAlpha; +} + +inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::Blend &a, + const QGles2CommandBuffer::GraphicsPassState::Blend &b) +{ + return !(a == b); +} + +struct QGles2SwapChainTimestamps +{ + static const int TIMESTAMP_PAIRS = 2; + + bool active[TIMESTAMP_PAIRS] = {}; + GLuint query[TIMESTAMP_PAIRS * 2] = {}; + + void prepare(QRhiGles2 *rhiD); + void destroy(QRhiGles2 *rhiD); + bool tryQueryTimestamps(int pairIndex, QRhiGles2 *rhiD, double *elapsedSec); +}; + +struct QGles2SwapChain : public QRhiSwapChain +{ + QGles2SwapChain(QRhiImplementation *rhi); + ~QGles2SwapChain(); + void destroy() override; + + QRhiCommandBuffer *currentFrameCommandBuffer() override; + QRhiRenderTarget *currentFrameRenderTarget() override; + QRhiRenderTarget *currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override; + + QSize surfacePixelSize() override; + bool isFormatSupported(Format f) override; + + QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; + bool createOrResize() override; + + void initSwapChainRenderTarget(QGles2SwapChainRenderTarget *rt); + + QSurface *surface = nullptr; + QSize pixelSize; + QGles2SwapChainRenderTarget rt; + QGles2SwapChainRenderTarget rtLeft; + QGles2SwapChainRenderTarget rtRight; + QGles2CommandBuffer cb; + int frameCount = 0; + QGles2SwapChainTimestamps timestamps; + int currentTimestampPairIndex = 0; +}; + +class QRhiGles2 : public QRhiImplementation +{ +public: + QRhiGles2(QRhiGles2InitParams *params, QRhiGles2NativeHandles *importDevice = nullptr); + + bool create(QRhi::Flags flags) override; + void destroy() override; + + QRhiGraphicsPipeline *createGraphicsPipeline() override; + QRhiComputePipeline *createComputePipeline() override; + QRhiShaderResourceBindings *createShaderResourceBindings() override; + QRhiBuffer *createBuffer(QRhiBuffer::Type type, + QRhiBuffer::UsageFlags usage, + quint32 size) override; + QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type, + const QSize &pixelSize, + int sampleCount, + QRhiRenderBuffer::Flags flags, + QRhiTexture::Format backingFormatHint) override; + QRhiTexture *createTexture(QRhiTexture::Format format, + const QSize &pixelSize, + int depth, + int arraySize, + int sampleCount, + QRhiTexture::Flags flags) override; + QRhiSampler *createSampler(QRhiSampler::Filter magFilter, + QRhiSampler::Filter minFilter, + QRhiSampler::Filter mipmapMode, + QRhiSampler:: AddressMode u, + QRhiSampler::AddressMode v, + QRhiSampler::AddressMode w) override; + + QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, + QRhiTextureRenderTarget::Flags flags) override; + + QRhiSwapChain *createSwapChain() override; + QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override; + QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override; + QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override; + QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override; + QRhi::FrameOpResult finish() override; + + void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + + void beginPass(QRhiCommandBuffer *cb, + QRhiRenderTarget *rt, + const QColor &colorClearValue, + const QRhiDepthStencilClearValue &depthStencilClearValue, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; + void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + + void setGraphicsPipeline(QRhiCommandBuffer *cb, + QRhiGraphicsPipeline *ps) override; + + void setShaderResources(QRhiCommandBuffer *cb, + QRhiShaderResourceBindings *srb, + int dynamicOffsetCount, + const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override; + + void setVertexInput(QRhiCommandBuffer *cb, + int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings, + QRhiBuffer *indexBuf, quint32 indexOffset, + QRhiCommandBuffer::IndexFormat indexFormat) override; + + void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override; + void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override; + void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override; + void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override; + + void draw(QRhiCommandBuffer *cb, quint32 vertexCount, + quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override; + + void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, + quint32 instanceCount, quint32 firstIndex, + qint32 vertexOffset, quint32 firstInstance) override; + + void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override; + void debugMarkEnd(QRhiCommandBuffer *cb) override; + void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override; + + void beginComputePass(QRhiCommandBuffer *cb, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; + void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override; + void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override; + + const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override; + void beginExternal(QRhiCommandBuffer *cb) override; + void endExternal(QRhiCommandBuffer *cb) override; + double lastCompletedGpuTime(QRhiCommandBuffer *cb) override; + + QList<int> supportedSampleCounts() const override; + int ubufAlignment() const override; + bool isYUpInFramebuffer() const override; + bool isYUpInNDC() const override; + bool isClipDepthZeroToOne() const override; + QMatrix4x4 clipSpaceCorrMatrix() const override; + bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override; + bool isFeatureSupported(QRhi::Feature feature) const override; + int resourceLimit(QRhi::ResourceLimit limit) const override; + const QRhiNativeHandles *nativeHandles() override; + QRhiDriverInfo driverInfo() const override; + QRhiStats statistics() override; + bool makeThreadLocalNativeContextCurrent() override; + void releaseCachedResources() override; + bool isDeviceLost() const override; + + QByteArray pipelineCacheData() override; + void setPipelineCacheData(const QByteArray &data) override; + + bool ensureContext(QSurface *surface = nullptr) const; + QSurface *evaluateFallbackSurface() const; + void executeDeferredReleases(); + void trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *bufD, QGles2Buffer::Access access); + void trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Texture::Access access); + void enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cbD, + int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc); + void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates); + void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker, + QGles2Buffer *bufD, + QRhiPassResourceTracker::BufferAccess access, + QRhiPassResourceTracker::BufferStage stage); + void trackedRegisterTexture(QRhiPassResourceTracker *passResTracker, + QGles2Texture *texD, + QRhiPassResourceTracker::TextureAccess access, + QRhiPassResourceTracker::TextureStage stage); + void executeCommandBuffer(QRhiCommandBuffer *cb); + void executeBindGraphicsPipeline(QGles2CommandBuffer *cbD, QGles2GraphicsPipeline *psD); + void bindCombinedSampler(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Sampler *samplerD, + void *ps, uint psGeneration, int glslLocation, + int *texUnit, bool *activeTexUnitAltered); + void bindShaderResources(QGles2CommandBuffer *cbD, + QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs, + QRhiShaderResourceBindings *srb, + const uint *dynOfsPairs, int dynOfsCount); + QGles2RenderTargetData *enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2CommandBuffer *cbD, + bool *wantsColorClear = nullptr, bool *wantsDsClear = nullptr); + void enqueueBarriersForPass(QGles2CommandBuffer *cbD); + QByteArray shaderSource(const QRhiShaderStage &shaderStage, QShaderVersion *shaderVersion); + bool compileShader(GLuint program, const QRhiShaderStage &shaderStage, QShaderVersion *shaderVersion); + bool linkProgram(GLuint program); + void registerUniformIfActive(const QShaderDescription::BlockVariable &var, + const QByteArray &namePrefix, int binding, int baseOffset, + GLuint program, + QDuplicateTracker<int, 256> *activeUniformLocations, + QGles2UniformDescriptionVector *dst); + void gatherUniforms(GLuint program, const QShaderDescription::UniformBlock &ub, + QDuplicateTracker<int, 256> *activeUniformLocations, QGles2UniformDescriptionVector *dst); + void gatherSamplers(GLuint program, const QShaderDescription::InOutVariable &v, + QGles2SamplerDescriptionVector *dst); + void gatherGeneratedSamplers(GLuint program, + const QShader::SeparateToCombinedImageSamplerMapping &mapping, + QGles2SamplerDescriptionVector *dst); + void sanityCheckVertexFragmentInterface(const QShaderDescription &vsDesc, const QShaderDescription &fsDesc); + bool isProgramBinaryDiskCacheEnabled() const; + + enum ProgramCacheResult { + ProgramCacheHit, + ProgramCacheMiss, + ProgramCacheError + }; + ProgramCacheResult tryLoadFromDiskOrPipelineCache(const QRhiShaderStage *stages, + int stageCount, + GLuint program, + const QVector<QShaderDescription::InOutVariable> &inputVars, + QByteArray *cacheKey); + void trySaveToDiskCache(GLuint program, const QByteArray &cacheKey); + void trySaveToPipelineCache(GLuint program, const QByteArray &cacheKey, bool force = false); + + QRhi::Flags rhiFlags; + QOpenGLContext *ctx = nullptr; + bool importedContext = false; + QSurfaceFormat requestedFormat; + QSurface *fallbackSurface = nullptr; + QPointer<QWindow> maybeWindow = nullptr; + QOpenGLContext *maybeShareContext = nullptr; + mutable bool needsMakeCurrentDueToSwap = false; + QOpenGLExtensions *f = nullptr; + void (QOPENGLF_APIENTRYP glPolygonMode) (GLenum, GLenum) = nullptr; + void(QOPENGLF_APIENTRYP glTexImage1D)(GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, + const void *) = nullptr; + void(QOPENGLF_APIENTRYP glTexStorage1D)(GLenum, GLint, GLenum, GLsizei) = nullptr; + void(QOPENGLF_APIENTRYP glTexSubImage1D)(GLenum, GLint, GLint, GLsizei, GLenum, GLenum, + const GLvoid *) = nullptr; + void(QOPENGLF_APIENTRYP glCopyTexSubImage1D)(GLenum, GLint, GLint, GLint, GLint, + GLsizei) = nullptr; + void(QOPENGLF_APIENTRYP glCompressedTexImage1D)(GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, + const GLvoid *) = nullptr; + void(QOPENGLF_APIENTRYP glCompressedTexSubImage1D)(GLenum, GLint, GLint, GLsizei, GLenum, + GLsizei, const GLvoid *) = nullptr; + void(QOPENGLF_APIENTRYP glFramebufferTexture1D)(GLenum, GLenum, GLenum, GLuint, + GLint) = nullptr; + void(QOPENGLF_APIENTRYP glFramebufferTextureMultiviewOVR)(GLenum, GLenum, GLuint, GLint, + GLint, GLsizei) = nullptr; + void (QOPENGLF_APIENTRYP glQueryCounter)(GLuint, GLenum) = nullptr; + void (QOPENGLF_APIENTRYP glGetQueryObjectui64v)(GLuint, GLenum, quint64 *) = nullptr; + void (QOPENGLF_APIENTRYP glObjectLabel)(GLenum, GLuint, GLsizei, const GLchar *) = nullptr; + void (QOPENGLF_APIENTRYP glFramebufferTexture2DMultisampleEXT)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei) = nullptr; + void (QOPENGLF_APIENTRYP glFramebufferTextureMultisampleMultiviewOVR)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei) = nullptr; + uint vao = 0; + struct Caps { + Caps() + : ctxMajor(2), + ctxMinor(0), + maxTextureSize(2048), + maxDrawBuffers(4), + maxSamples(16), + maxTextureArraySize(0), + maxThreadGroupsPerDimension(0), + maxThreadsPerThreadGroup(0), + maxThreadGroupsX(0), + maxThreadGroupsY(0), + maxThreadGroupsZ(0), + maxUniformVectors(4096), + maxVertexInputs(8), + maxVertexOutputs(8), + msaaRenderBuffer(false), + multisampledTexture(false), + npotTextureFull(true), + gles(false), + fixedIndexPrimitiveRestart(false), + bgraExternalFormat(false), + bgraInternalFormat(false), + r8Format(false), + r16Format(false), + floatFormats(false), + rgb10Formats(false), + depthTexture(false), + packedDepthStencil(false), + needsDepthStencilCombinedAttach(false), + srgbWriteControl(false), + coreProfile(false), + uniformBuffers(false), + elementIndexUint(false), + depth24(false), + rgba8Format(false), + instancing(false), + baseVertex(false), + compute(false), + textureCompareMode(false), + properMapBuffer(false), + nonBaseLevelFramebufferTexture(false), + texelFetch(false), + intAttributes(true), + screenSpaceDerivatives(false), + programBinary(false), + texture3D(false), + tessellation(false), + geometryShader(false), + texture1D(false), + hasDrawBuffersFunc(false), + halfAttributes(false), + multiView(false), + timestamps(false), + objectLabel(false), + glesMultisampleRenderToTexture(false), + glesMultiviewMultisampleRenderToTexture(false), + unpackRowLength(false) + { } + int ctxMajor; + int ctxMinor; + int maxTextureSize; + int maxDrawBuffers; + int maxSamples; + int maxTextureArraySize; + int maxThreadGroupsPerDimension; + int maxThreadsPerThreadGroup; + int maxThreadGroupsX; + int maxThreadGroupsY; + int maxThreadGroupsZ; + int maxUniformVectors; + int maxVertexInputs; + int maxVertexOutputs; + // Multisample fb and blit are supported (GLES 3.0 or OpenGL 3.x). Not + // the same as multisample textures! + uint msaaRenderBuffer : 1; + uint multisampledTexture : 1; + uint npotTextureFull : 1; + uint gles : 1; + uint fixedIndexPrimitiveRestart : 1; + uint bgraExternalFormat : 1; + uint bgraInternalFormat : 1; + uint r8Format : 1; + uint r16Format : 1; + uint floatFormats : 1; + uint rgb10Formats : 1; + uint depthTexture : 1; + uint packedDepthStencil : 1; + uint needsDepthStencilCombinedAttach : 1; + uint srgbWriteControl : 1; + uint coreProfile : 1; + uint uniformBuffers : 1; + uint elementIndexUint : 1; + uint depth24 : 1; + uint rgba8Format : 1; + uint instancing : 1; + uint baseVertex : 1; + uint compute : 1; + uint textureCompareMode : 1; + uint properMapBuffer : 1; + uint nonBaseLevelFramebufferTexture : 1; + uint texelFetch : 1; + uint intAttributes : 1; + uint screenSpaceDerivatives : 1; + uint programBinary : 1; + uint texture3D : 1; + uint tessellation : 1; + uint geometryShader : 1; + uint texture1D : 1; + uint hasDrawBuffersFunc : 1; + uint halfAttributes : 1; + uint multiView : 1; + uint timestamps : 1; + uint objectLabel : 1; + uint glesMultisampleRenderToTexture : 1; + uint glesMultiviewMultisampleRenderToTexture : 1; + uint unpackRowLength : 1; + } caps; + QGles2SwapChain *currentSwapChain = nullptr; + QSet<GLint> supportedCompressedFormats; + mutable QList<int> supportedSampleCountList; + QRhiGles2NativeHandles nativeHandlesStruct; + QRhiDriverInfo driverInfoStruct; + mutable bool contextLost = false; + + struct DeferredReleaseEntry { + enum Type { + Buffer, + Pipeline, + Texture, + RenderBuffer, + TextureRenderTarget + }; + Type type; + union { + struct { + GLuint buffer; + } buffer; + struct { + GLuint program; + } pipeline; + struct { + GLuint texture; + } texture; + struct { + GLuint renderbuffer; + GLuint renderbuffer2; + } renderbuffer; + struct { + GLuint framebuffer; + GLuint nonMsaaThrowawayDepthTexture; + } textureRenderTarget; + }; + }; + QList<DeferredReleaseEntry> releaseQueue; + + struct OffscreenFrame { + OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { } + bool active = false; + QGles2CommandBuffer cbWrapper; + GLuint tsQueries[2] = {}; + } ofr; + + QHash<QRhiShaderStage, uint> m_shaderCache; + + struct PipelineCacheData { + quint32 format; + QByteArray data; + }; + QHash<QByteArray, PipelineCacheData> m_pipelineCache; +}; + +Q_DECLARE_TYPEINFO(QRhiGles2::DeferredReleaseEntry, Q_RELOCATABLE_TYPE); + QT_END_NAMESPACE #endif |