From 644ef33730914c7c50e7dfbd5c3e93b89850b704 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 12 Apr 2018 17:58:05 +0200 Subject: [PATCH] First draft at batch generateTextureMipsWithPipeline --- .../gpu-gl-common/src/gpu/gl/GLBackend.cpp | 16 ++++- .../gpu-gl-common/src/gpu/gl/GLBackend.h | 9 ++- .../src/gpu/gl/GLBackendTexture.cpp | 62 ++++++++++++++++--- libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp | 7 +-- libraries/gpu-gl/src/gpu/gl41/GL41Backend.h | 4 +- libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp | 37 +++++------ libraries/gpu-gl/src/gpu/gl45/GL45Backend.h | 2 +- libraries/gpu/src/gpu/Batch.cpp | 9 +++ libraries/gpu/src/gpu/Batch.h | 7 ++- libraries/gpu/src/gpu/Context.cpp | 12 ++++ libraries/gpu/src/gpu/Context.h | 2 + libraries/render-utils/src/ssao.slh | 1 + 12 files changed, 124 insertions(+), 44 deletions(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index 9bb02d678d..0858e36f65 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -62,7 +62,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::gl::GLBackend::do_setFramebufferSwapChain), (&::gpu::gl::GLBackend::do_clearFramebuffer), (&::gpu::gl::GLBackend::do_blit), - (&::gpu::gl::GLBackend::do_generateTextureMips), + (&::gpu::gl::GLBackend::do_generateTextureMips), + (&::gpu::gl::GLBackend::do_generateTextureMipsWithPipeline), (&::gpu::gl::GLBackend::do_advance), @@ -133,10 +134,23 @@ GLBackend::GLBackend() { GLBackend::~GLBackend() { + if (_mipGenerationFramebufferId) { + glDeleteFramebuffers(1, &_mipGenerationFramebufferId); + _mipGenerationFramebufferId = 0; + } killInput(); killTransform(); } +void GLBackend::do_draw(const Batch& batch, size_t paramOffset) { + Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint; + GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType]; + uint32 numVertices = batch._params[paramOffset + 1]._uint; + uint32 startVertex = batch._params[paramOffset + 0]._uint; + + draw(mode, numVertices, startVertex); +} + void GLBackend::renderPassTransfer(const Batch& batch) { const size_t numCommands = batch.getCommands().size(); const Batch::Commands::value_type* command = batch.getCommands().data(); diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 6355137a19..0d62e7490f 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -108,7 +108,7 @@ public: // Draw Stage - virtual void do_draw(const Batch& batch, size_t paramOffset) = 0; + virtual void do_draw(const Batch& batch, size_t paramOffset); virtual void do_drawIndexed(const Batch& batch, size_t paramOffset) = 0; virtual void do_drawInstanced(const Batch& batch, size_t paramOffset) = 0; virtual void do_drawIndexedInstanced(const Batch& batch, size_t paramOffset) = 0; @@ -120,7 +120,8 @@ public: virtual void do_setInputBuffer(const Batch& batch, size_t paramOffset) final; virtual void do_setIndexBuffer(const Batch& batch, size_t paramOffset) final; virtual void do_setIndirectBuffer(const Batch& batch, size_t paramOffset) final; - virtual void do_generateTextureMips(const Batch& batch, size_t paramOffset) final; + virtual void do_generateTextureMips(const Batch& batch, size_t paramOffset) final; + virtual void do_generateTextureMipsWithPipeline(const Batch& batch, size_t paramOffset) final; // Transform Stage virtual void do_setModelTransform(const Batch& batch, size_t paramOffset) final; @@ -234,6 +235,8 @@ public: protected: + virtual void draw(GLenum mode, uint32 numVertices, uint32 startVertex) = 0; + void recycle() const override; // FIXME instead of a single flag, create a features struct similar to @@ -492,6 +495,8 @@ protected: } _textureManagement; virtual void initTextureManagementStage() {} + GLuint _mipGenerationFramebufferId{ 0 }; + typedef void (GLBackend::*CommandCall)(const Batch&, size_t); static CommandCall _commandCalls[Batch::NUM_COMMANDS]; friend class GLState; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp index ca4e328612..674fdacf0f 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp @@ -66,16 +66,58 @@ GLTexture* GLBackend::syncGPUObject(const TexturePointer& texturePointer) { } void GLBackend::do_generateTextureMips(const Batch& batch, size_t paramOffset) { - TexturePointer resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); - if (!resourceTexture) { - return; - } + TexturePointer resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); + if (!resourceTexture) { + return; + } - // DO not transfer the texture, this call is expected for rendering texture - GLTexture* object = syncGPUObject(resourceTexture); - if (!object) { - return; - } + // DO not transfer the texture, this call is expected for rendering texture + GLTexture* object = syncGPUObject(resourceTexture); + if (!object) { + return; + } - object->generateMips(); + object->generateMips(); +} + +void GLBackend::do_generateTextureMipsWithPipeline(const Batch& batch, size_t paramOffset) { + TexturePointer resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); + if (!resourceTexture) { + return; + } + + // Do not transfer the texture, this call is expected for rendering texture + GLTexture* object = syncGPUObject(resourceTexture); + if (!object) { + return; + } + + auto numMips = batch._params[paramOffset + 1]._int; + if (numMips < 0) { + numMips = resourceTexture->getNumMips(); + } else { + numMips = std::min(numMips, (int)resourceTexture->getNumMips()); + } + + if (_mipGenerationFramebufferId == 0) { + glGenFramebuffers(1, &_mipGenerationFramebufferId); + Q_ASSERT(_mipGenerationFramebufferId > 0); + } + + glBindFramebuffer(GL_FRAMEBUFFER, _mipGenerationFramebufferId); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0); + + for (int level = 1; level < numMips; level++) { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, object->_id, level); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level - 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level - 1); + + const auto mipDimensions = resourceTexture->evalMipDimensions(level); + glViewport(0, 0, mipDimensions.x, mipDimensions.y); + draw(GL_TRIANGLE_STRIP, 4, 0); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, numMips-1); + + resetOutputStage(); } diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp index 88cf89ad99..d4376632ca 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp @@ -20,12 +20,7 @@ using namespace gpu::gl41; const std::string GL41Backend::GL41_VERSION { "GL41" }; -void GL41Backend::do_draw(const Batch& batch, size_t paramOffset) { - Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint; - GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType]; - uint32 numVertices = batch._params[paramOffset + 1]._uint; - uint32 startVertex = batch._params[paramOffset + 0]._uint; - +void GL41Backend::draw(GLenum mode, uint32 numVertices, uint32 startVertex) { if (isStereo()) { #ifdef GPU_STEREO_DRAWCALL_INSTANCED glDrawArraysInstanced(mode, startVertex, numVertices, 2); diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h index 3c59781f78..408766f566 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h +++ b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h @@ -133,6 +133,9 @@ public: }; protected: + + void draw(GLenum mode, uint32 numVertices, uint32 startVertex) override; + GLuint getFramebufferID(const FramebufferPointer& framebuffer) override; GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override; @@ -146,7 +149,6 @@ protected: GLQuery* syncGPUObject(const Query& query) override; // Draw Stage - void do_draw(const Batch& batch, size_t paramOffset) override; void do_drawIndexed(const Batch& batch, size_t paramOffset) override; void do_drawInstanced(const Batch& batch, size_t paramOffset) override; void do_drawIndexedInstanced(const Batch& batch, size_t paramOffset) override; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp index c119e27d5b..9a08bbf173 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp @@ -24,33 +24,28 @@ void GL45Backend::recycle() const { Parent::recycle(); } -void GL45Backend::do_draw(const Batch& batch, size_t paramOffset) { - Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint; - GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType]; - uint32 numVertices = batch._params[paramOffset + 1]._uint; - uint32 startVertex = batch._params[paramOffset + 0]._uint; - - if (isStereo()) { +void GL45Backend::draw(GLenum mode, uint32 numVertices, uint32 startVertex) { + if (isStereo()) { #ifdef GPU_STEREO_DRAWCALL_INSTANCED - glDrawArraysInstanced(mode, startVertex, numVertices, 2); + glDrawArraysInstanced(mode, startVertex, numVertices, 2); #else - setupStereoSide(0); - glDrawArrays(mode, startVertex, numVertices); - setupStereoSide(1); - glDrawArrays(mode, startVertex, numVertices); + setupStereoSide(0); + glDrawArrays(mode, startVertex, numVertices); + setupStereoSide(1); + glDrawArrays(mode, startVertex, numVertices); #endif - _stats._DSNumTriangles += 2 * numVertices / 3; - _stats._DSNumDrawcalls += 2; + _stats._DSNumTriangles += 2 * numVertices / 3; + _stats._DSNumDrawcalls += 2; - } else { - glDrawArrays(mode, startVertex, numVertices); - _stats._DSNumTriangles += numVertices / 3; - _stats._DSNumDrawcalls++; - } - _stats._DSNumAPIDrawcalls++; + } else { + glDrawArrays(mode, startVertex, numVertices); + _stats._DSNumTriangles += numVertices / 3; + _stats._DSNumDrawcalls++; + } + _stats._DSNumAPIDrawcalls++; - (void) CHECK_GL_ERROR(); + (void)CHECK_GL_ERROR(); } void GL45Backend::do_drawIndexed(const Batch& batch, size_t paramOffset) { diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h index c23a83eaf9..1683861c89 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h @@ -231,6 +231,7 @@ public: protected: + void draw(GLenum mode, uint32 numVertices, uint32 startVertex) override; void recycle() const override; GLuint getFramebufferID(const FramebufferPointer& framebuffer) override; @@ -246,7 +247,6 @@ protected: // Draw Stage - void do_draw(const Batch& batch, size_t paramOffset) override; void do_drawIndexed(const Batch& batch, size_t paramOffset) override; void do_drawInstanced(const Batch& batch, size_t paramOffset) override; void do_drawIndexedInstanced(const Batch& batch, size_t paramOffset) override; diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index db4941c163..0c49901091 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -425,6 +425,15 @@ void Batch::generateTextureMips(const TexturePointer& texture) { _params.emplace_back(_textures.cache(texture)); } +void Batch::generateTextureMipsWithPipeline(const TexturePointer& texture, int numMips) { + setResourceTexture(0, texture); + + ADD_COMMAND(generateTextureMipsWithPipeline); + + _params.emplace_back(_textures.cache(texture)); + _params.emplace_back(numMips); +} + void Batch::beginQuery(const QueryPointer& query) { ADD_COMMAND(beginQuery); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 96b234295d..90a30f4e5e 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -211,7 +211,9 @@ public: void blit(const FramebufferPointer& src, const Vec4i& srcRect, const FramebufferPointer& dst, const Vec4i& dstRect); // Generate the mips for a texture - void generateTextureMips(const TexturePointer& texture); + void generateTextureMips(const TexturePointer& texture); + // Generate the mips for a texture using the current pipeline + void generateTextureMipsWithPipeline(const TexturePointer& texture, int numMips = -1); // Query Section void beginQuery(const QueryPointer& query); @@ -310,7 +312,8 @@ public: COMMAND_setFramebufferSwapChain, COMMAND_clearFramebuffer, COMMAND_blit, - COMMAND_generateTextureMips, + COMMAND_generateTextureMips, + COMMAND_generateTextureMipsWithPipeline, COMMAND_advance, diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index e1b68c88ca..657829214f 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -14,6 +14,7 @@ #include "Frame.h" #include "GPULogging.h" +#include "StandardShaderLib.h" using namespace gpu; @@ -317,3 +318,14 @@ Size Context::getTexturePendingGPUTransferMemSize() { Size Context::getTextureResourcePopulatedGPUMemSize() { return Backend::textureResourcePopulatedGPUMemSize.getValue(); } + +PipelinePointer Context::createMipGenerationPipeline(const ShaderPointer& ps, const gpu::Shader::BindingSet& slotBindings) { + auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); + static gpu::StatePointer state(new gpu::State()); + + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + gpu::Shader::makeProgram(*program, slotBindings); + + // Good to go add the brand new pipeline + return gpu::Pipeline::create(program, state); +} diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 2df7de2331..63713832e7 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -220,6 +220,8 @@ public: // Same as above but grabbed at every end of a frame void getFrameStats(ContextStats& stats) const; + static PipelinePointer createMipGenerationPipeline(const ShaderPointer& pixelShader, const gpu::Shader::BindingSet& slotBindings = gpu::Shader::BindingSet()); + double getFrameTimerGPUAverage() const; double getFrameTimerBatchAverage() const; diff --git a/libraries/render-utils/src/ssao.slh b/libraries/render-utils/src/ssao.slh index c9b27bc2c8..c0039265fa 100644 --- a/libraries/render-utils/src/ssao.slh +++ b/libraries/render-utils/src/ssao.slh @@ -313,6 +313,7 @@ float evalAO(in vec3 C, in vec3 n_C, in vec3 Q) { // the source occlusion texture uniform sampler2D occlusionMap; + vec2 fetchOcclusionDepthRaw(ivec2 coords, out vec3 raw) { raw = texelFetch(occlusionMap, coords, 0).xyz; return unpackOcclusionDepth(raw);