From 9486a8a4b60a678280db2c625064ca78b3aaf489 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 21 Sep 2018 07:53:11 +0200 Subject: Complete ES 3.1 and 3.2 helpers Which didn't handle indirect drawing, compute and tessellation Since ES 3.1/3.2 don't provide API for glShaderStorageBlockBinding, code was adjusted to use the default binding points and not require that API. Change-Id: Ie4dcd05f0a1d72e4a25f49b5fae138dc605ba5e3 Task-number: QTBUG-70660 Reviewed-by: Sean Harmer --- .../opengl/graphicshelpers/graphicshelperes3_1.cpp | 168 +++++++++++++++++++++ .../opengl/graphicshelpers/graphicshelperes3_1_p.h | 8 + .../opengl/graphicshelpers/graphicshelperes3_2.cpp | 20 +++ .../opengl/graphicshelpers/graphicshelperes3_2_p.h | 3 + .../opengl/graphicshelpers/submissioncontext.cpp | 10 +- 5 files changed, 206 insertions(+), 3 deletions(-) (limited to 'src/render/renderers/opengl/graphicshelpers') diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1.cpp index 135e83aec..a555b67ef 100644 --- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1.cpp +++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1.cpp @@ -53,10 +53,114 @@ QT_BEGIN_NAMESPACE #ifndef GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE #define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A #endif +#ifndef GL_ACTIVE_RESOURCES +#define GL_ACTIVE_RESOURCES 0x92F5 +#endif +#ifndef GL_BUFFER_BINDING +#define GL_BUFFER_BINDING 0x9302 +#endif +#ifndef GL_BUFFER_DATA_SIZE +#define GL_BUFFER_DATA_SIZE 0x9303 +#endif +#ifndef GL_NUM_ACTIVE_VARIABLES +#define GL_NUM_ACTIVE_VARIABLES 0x9304 +#endif +#ifndef GL_SHADER_STORAGE_BLOCK +#define GL_SHADER_STORAGE_BLOCK 0x92E6 +#endif +#ifndef GL_ALL_BARRIER_BITS +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001 +#endif +#ifndef GL_ELEMENT_ARRAY_BARRIER_BIT +#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002 +#endif +#ifndef GL_UNIFORM_BARRIER_BIT +#define GL_UNIFORM_BARRIER_BIT 0x00000004 +#endif +#ifndef GL_TEXTURE_FETCH_BARRIER_BIT +#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008 +#endif +#ifndef GL_SHADER_IMAGE_ACCESS_BARRIER_BIT +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#endif +#ifndef GL_COMMAND_BARRIER_BIT +#define GL_COMMAND_BARRIER_BIT 0x00000040 +#endif +#ifndef GL_PIXEL_BUFFER_BARRIER_BIT +#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080 +#endif +#ifndef GL_TEXTURE_UPDATE_BARRIER_BIT +#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100 +#endif +#ifndef GL_BUFFER_UPDATE_BARRIER_BIT +#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200 +#endif +#ifndef GL_FRAMEBUFFER_BARRIER_BIT +#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400 +#endif +#ifndef GL_TRANSFORM_FEEDBACK_BARRIER_BIT +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800 +#endif +#ifndef GL_ATOMIC_COUNTER_BARRIER_BIT +#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000 +#endif +#ifndef GL_SHADER_STORAGE_BARRIER_BIT +#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000 +#endif + namespace Qt3DRender { namespace Render { +namespace { + +GLbitfield memoryBarrierGLBitfield(QMemoryBarrier::Operations barriers) +{ + GLbitfield bits = 0; + + if (barriers.testFlag(QMemoryBarrier::All)) { + bits |= GL_ALL_BARRIER_BITS; + return bits; + } + + if (barriers.testFlag(QMemoryBarrier::VertexAttributeArray)) + bits |= GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT; + if (barriers.testFlag(QMemoryBarrier::ElementArray)) + bits |= GL_ELEMENT_ARRAY_BARRIER_BIT; + if (barriers.testFlag(QMemoryBarrier::Uniform)) + bits |= GL_UNIFORM_BARRIER_BIT; + if (barriers.testFlag(QMemoryBarrier::TextureFetch)) + bits |= GL_TEXTURE_FETCH_BARRIER_BIT; + if (barriers.testFlag(QMemoryBarrier::ShaderImageAccess)) + bits |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; + if (barriers.testFlag(QMemoryBarrier::Command)) + bits |= GL_COMMAND_BARRIER_BIT; + if (barriers.testFlag(QMemoryBarrier::PixelBuffer)) + bits |= GL_PIXEL_BUFFER_BARRIER_BIT; + if (barriers.testFlag(QMemoryBarrier::TextureUpdate)) + bits |= GL_TEXTURE_UPDATE_BARRIER_BIT; + if (barriers.testFlag(QMemoryBarrier::BufferUpdate)) + bits |= GL_BUFFER_UPDATE_BARRIER_BIT; + if (barriers.testFlag(QMemoryBarrier::FrameBuffer)) + bits |= GL_FRAMEBUFFER_BARRIER_BIT; + if (barriers.testFlag(QMemoryBarrier::TransformFeedback)) + bits |= GL_TRANSFORM_FEEDBACK_BARRIER_BIT; + if (barriers.testFlag(QMemoryBarrier::AtomicCounter)) + bits |= GL_ATOMIC_COUNTER_BARRIER_BIT; + if (barriers.testFlag(QMemoryBarrier::ShaderStorage)) + bits |= GL_SHADER_STORAGE_BARRIER_BIT; + if (barriers.testFlag(QMemoryBarrier::QueryBuffer)) + qWarning() << "QueryBuffer barrier not supported by ES 3.1"; + + return bits; +} + +} // anonymous + + GraphicsHelperES3_1::GraphicsHelperES3_1() { } @@ -65,6 +169,70 @@ GraphicsHelperES3_1::~GraphicsHelperES3_1() { } +bool GraphicsHelperES3_1::supportsFeature(GraphicsHelperInterface::Feature feature) const +{ + switch (feature) { + case GraphicsHelperInterface::Compute: + case GraphicsHelperInterface::ShaderStorageObject: + case GraphicsHelperInterface::IndirectDrawing: + return true; + default: + break; + } + return GraphicsHelperES3::supportsFeature(feature); +} + +void GraphicsHelperES3_1::dispatchCompute(GLuint wx, GLuint wy, GLuint wz) +{ + m_extraFuncs->glDispatchCompute(wx, wy, wz); +} + +void GraphicsHelperES3_1::memoryBarrier(QMemoryBarrier::Operations barriers) +{ + m_extraFuncs->glMemoryBarrier(memoryBarrierGLBitfield(barriers)); +} + +void GraphicsHelperES3_1::drawArraysIndirect(GLenum mode, void *indirect) +{ + m_extraFuncs->glDrawArraysIndirect(mode, indirect); +} + +void GraphicsHelperES3_1::drawElementsIndirect(GLenum mode, GLenum type, void *indirect) +{ + m_extraFuncs->glDrawElementsIndirect(mode, type, indirect); +} + +void GraphicsHelperES3_1::bindShaderStorageBlock(GLuint , GLuint , GLuint ) +{ + // ES 3.1 has no API for that, bindings have to be specified directly in the shader + // with layout(std430, binding = 3) + qWarning() << "ES 3.1 has no bindShaderStorageBlock API, it uses binding declaration from the shader storage block"; +} + +QVector GraphicsHelperES3_1::programShaderStorageBlocks(GLuint programId) +{ + QVector blocks; + GLint nbrActiveShaderStorageBlocks = 0; + m_extraFuncs->glGetProgramInterfaceiv(programId, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &nbrActiveShaderStorageBlocks); + blocks.reserve(nbrActiveShaderStorageBlocks); + for (GLint i = 0; i < nbrActiveShaderStorageBlocks; ++i) { + QByteArray storageBlockName(256, '\0'); + GLsizei length = 0; + ShaderStorageBlock storageBlock; + m_extraFuncs->glGetProgramResourceName(programId, GL_SHADER_STORAGE_BLOCK, i, 256, &length, storageBlockName.data()); + storageBlock.m_index = i; + storageBlock.m_name = QString::fromUtf8(storageBlockName.left(length)); + GLenum prop = GL_BUFFER_BINDING; + m_extraFuncs->glGetProgramResourceiv(programId, GL_SHADER_STORAGE_BLOCK, i, 1, &prop, 4, NULL, &storageBlock.m_binding); + prop = GL_BUFFER_DATA_SIZE; + m_extraFuncs->glGetProgramResourceiv(programId, GL_SHADER_STORAGE_BLOCK, i, 1, &prop, 4, NULL, &storageBlock.m_size); + prop = GL_NUM_ACTIVE_VARIABLES; + m_extraFuncs->glGetProgramResourceiv(programId, GL_SHADER_STORAGE_BLOCK, i, 1, &prop, 4, NULL, &storageBlock.m_activeVariablesCount); + blocks.push_back(storageBlock); + } + return blocks; +} + UniformType GraphicsHelperES3_1::uniformTypeFromGLType(GLenum glType) { switch (glType) { diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1_p.h index 70a584380..2c130fbf5 100644 --- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1_p.h +++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1_p.h @@ -64,6 +64,14 @@ public: GraphicsHelperES3_1(); ~GraphicsHelperES3_1(); + bool supportsFeature(Feature feature) const override; + void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) override; + void memoryBarrier(QMemoryBarrier::Operations barriers) override; + void drawArraysIndirect(GLenum mode,void *indirect) override; + void drawElementsIndirect(GLenum mode, GLenum type, void *indirect) override; + void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) override; + QVector programShaderStorageBlocks(GLuint programId) override; + // QGraphicHelperInterface interface UniformType uniformTypeFromGLType(GLenum glType) override; uint uniformByteSize(const ShaderUniform &description) override; diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp index 6290d091d..9dce08e4f 100644 --- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp +++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp @@ -52,6 +52,10 @@ QT_BEGIN_NAMESPACE #define GL_DEPTH_STENCIL_ATTACHMENT 0x821A #endif +#ifndef GL_PATCH_VERTICES +#define GL_PATCH_VERTICES 36466 +#endif + namespace Qt3DRender { namespace Render { @@ -63,6 +67,17 @@ GraphicsHelperES3_2::~GraphicsHelperES3_2() { } +bool GraphicsHelperES3_2::supportsFeature(GraphicsHelperInterface::Feature feature) const +{ + switch (feature) { + case GraphicsHelperInterface::Tessellation: + return true; + default: + break; + } + return GraphicsHelperES3_1::supportsFeature(feature); +} + bool GraphicsHelperES3_2::frameBufferNeedsRenderBuffer(const Attachment &attachment) { Q_UNUSED(attachment); @@ -97,6 +112,11 @@ void GraphicsHelperES3_2::bindFrameBufferAttachment(QOpenGLTexture *texture, con texture->release(); } +void GraphicsHelperES3_2::setVerticesPerPatch(GLint verticesPerPatch) +{ + m_extraFuncs->glPatchParameteri(GL_PATCH_VERTICES, verticesPerPatch); +} + } // namespace Render } // namespace Qt3DRender diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2_p.h index 787bba5f0..ed71b1e3e 100644 --- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2_p.h +++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2_p.h @@ -64,9 +64,12 @@ public: GraphicsHelperES3_2(); ~GraphicsHelperES3_2(); + bool supportsFeature(Feature feature) const override; + // QGraphicHelperInterface interface void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) override; bool frameBufferNeedsRenderBuffer(const Attachment &attachment) override; + void setVerticesPerPatch(GLint verticesPerPatch) override; }; } // namespace Render diff --git a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp index 7bb0713ee..26ee94305 100644 --- a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp +++ b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp @@ -1291,15 +1291,19 @@ bool SubmissionContext::setParameters(ShaderParameterPack ¶meterPack) // Bind Shader Storage block to SSBO and update SSBO const QVector blockToSSBOs = parameterPack.shaderStorageBuffers(); - int ssboIndex = 0; for (const BlockToSSBO b : blockToSSBOs) { Buffer *cpuBuffer = m_renderer->nodeManagers()->bufferManager()->lookupResource(b.m_bufferID); GLBuffer *ssbo = glBufferForRenderBuffer(cpuBuffer, GLBuffer::ShaderStorageBuffer); - bindShaderStorageBlock(shader->programId(), b.m_blockIndex, ssboIndex); + + // bindShaderStorageBlock + // This is currently not required as we are introspecting the bindingIndex + // value from the shaders and not replacing them, making such a call useless + // bindShaderStorageBlock(shader->programId(), b.m_blockIndex, b.m_bindingIndex); + // Needed to avoid conflict where the buffer would already // be bound as a VertexArray bindGLBuffer(ssbo, GLBuffer::ShaderStorageBuffer); - ssbo->bindBufferBase(this, ssboIndex++, GLBuffer::ShaderStorageBuffer); + ssbo->bindBufferBase(this, b.m_bindingIndex, GLBuffer::ShaderStorageBuffer); // TO DO: Make sure that there's enough binding points } -- cgit v1.2.3