From 9cd963af95f2dc9110c916c5b927d3cb564f92fa Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 27 Sep 2018 10:26:51 +0200 Subject: [PATCH 1/3] Added generateTextureMipsWithPipeline function in batch --- .../gpu-gl-common/src/gpu/gl/GLBackend.cpp | 5 ++ .../gpu-gl-common/src/gpu/gl/GLBackend.h | 5 ++ .../src/gpu/gl/GLBackendTexture.cpp | 47 +++++++++++++++++++ libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp | 23 +++++++++ libraries/gpu-gl/src/gpu/gl41/GL41Backend.h | 3 ++ libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp | 24 ++++++++++ libraries/gpu-gl/src/gpu/gl45/GL45Backend.h | 1 + libraries/gpu/src/gpu/Batch.cpp | 9 ++++ libraries/gpu/src/gpu/Batch.h | 3 ++ libraries/gpu/src/gpu/ShaderConstants.h | 6 ++- 10 files changed, 125 insertions(+), 1 deletion(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index 4fea4f2dc5..2842c682e7 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -64,6 +64,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::gl::GLBackend::do_clearFramebuffer), (&::gpu::gl::GLBackend::do_blit), (&::gpu::gl::GLBackend::do_generateTextureMips), + (&::gpu::gl::GLBackend::do_generateTextureMipsWithPipeline), (&::gpu::gl::GLBackend::do_advance), @@ -163,6 +164,10 @@ GLBackend::GLBackend() { GLBackend::~GLBackend() {} void GLBackend::shutdown() { + if (_mipGenerationFramebufferId) { + glDeleteFramebuffers(1, &_mipGenerationFramebufferId); + _mipGenerationFramebufferId = 0; + } killInput(); killTransform(); killTextureManagementStage(); diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 0b76ef17de..267c2a97ad 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -288,6 +288,7 @@ public: 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_generateTextureMipsWithPipeline(const Batch& batch, size_t paramOffset) final; // Transform Stage virtual void do_setModelTransform(const Batch& batch, size_t paramOffset) final; @@ -407,6 +408,8 @@ public: protected: virtual GLint getRealUniformLocation(GLint location) const; + 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 @@ -696,6 +699,8 @@ protected: virtual void initTextureManagementStage(); virtual void killTextureManagementStage(); + 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 f4fb3fcf2c..f4f2da3ee5 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp @@ -79,3 +79,50 @@ void GLBackend::do_generateTextureMips(const Batch& batch, size_t paramOffset) { 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, 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); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + resetOutputStage(); + // Restore viewport + ivec4& vp = _transform._viewport; + glViewport(vp.x, vp.y, vp.z, vp.w); +} diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp index 88cf89ad99..43ae4691b9 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp @@ -20,6 +20,29 @@ using namespace gpu::gl41; const std::string GL41Backend::GL41_VERSION { "GL41" }; +void GL41Backend::draw(GLenum mode, uint32 numVertices, uint32 startVertex) { + if (isStereo()) { +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawArraysInstanced(mode, startVertex, numVertices, 2); +#else + setupStereoSide(0); + glDrawArrays(mode, startVertex, numVertices); + setupStereoSide(1); + glDrawArrays(mode, startVertex, numVertices); +#endif + _stats._DSNumTriangles += 2 * numVertices / 3; + _stats._DSNumDrawcalls += 2; + + } else { + glDrawArrays(mode, startVertex, numVertices); + _stats._DSNumTriangles += numVertices / 3; + _stats._DSNumDrawcalls++; + } + _stats._DSNumAPIDrawcalls++; + + (void)CHECK_GL_ERROR(); +} + 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]; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h index e5f7415107..5d691d032a 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h +++ b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h @@ -130,6 +130,9 @@ public: }; protected: + + void draw(GLenum mode, uint32 numVertices, uint32 startVertex) override; + GLuint getFramebufferID(const FramebufferPointer& framebuffer) override; GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp index bbe011d237..e86eae2c2d 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp @@ -42,6 +42,30 @@ void GL45Backend::recycle() const { Parent::recycle(); } +void GL45Backend::draw(GLenum mode, uint32 numVertices, uint32 startVertex) { + if (isStereo()) { +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawArraysInstanced(mode, startVertex, numVertices, 2); +#else + setupStereoSide(0); + glDrawArrays(mode, startVertex, numVertices); + setupStereoSide(1); + glDrawArrays(mode, startVertex, numVertices); +#endif + + _stats._DSNumTriangles += 2 * numVertices / 3; + _stats._DSNumDrawcalls += 2; + + } else { + glDrawArrays(mode, startVertex, numVertices); + _stats._DSNumTriangles += numVertices / 3; + _stats._DSNumDrawcalls++; + } + _stats._DSNumAPIDrawcalls++; + + (void)CHECK_GL_ERROR(); +} + 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]; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h index 30656b47c7..77095375af 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h @@ -229,6 +229,7 @@ public: protected: + void draw(GLenum mode, uint32 numVertices, uint32 startVertex) override; void recycle() const override; GLuint getFramebufferID(const FramebufferPointer& framebuffer) override; diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 745f1d1845..4cf678f26e 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -417,6 +417,15 @@ void Batch::generateTextureMips(const TexturePointer& texture) { _params.emplace_back(_textures.cache(texture)); } +void Batch::generateTextureMipsWithPipeline(const TexturePointer& texture, int numMips) { + setResourceTexture(gpu::slot::texture::MipCreationInput, 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 8e607a189e..5a4089d2b6 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -216,6 +216,8 @@ public: // Generate the mips for a texture void generateTextureMips(const TexturePointer& texture); + // Generate the mips for a texture using the current pipeline + void generateTextureMipsWithPipeline(const TexturePointer& destTexture, int numMips = -1); // Query Section void beginQuery(const QueryPointer& query); @@ -316,6 +318,7 @@ public: COMMAND_clearFramebuffer, COMMAND_blit, COMMAND_generateTextureMips, + COMMAND_generateTextureMipsWithPipeline, COMMAND_advance, diff --git a/libraries/gpu/src/gpu/ShaderConstants.h b/libraries/gpu/src/gpu/ShaderConstants.h index 13dfd1be9c..426c64e913 100644 --- a/libraries/gpu/src/gpu/ShaderConstants.h +++ b/libraries/gpu/src/gpu/ShaderConstants.h @@ -21,6 +21,9 @@ #define GPU_TEXTURE_TRANSFORM_OBJECT 31 +// Mip creation +#define GPU_TEXTURE_MIP_CREATION_INPUT 0 + #define GPU_STORAGE_TRANSFORM_OBJECT 7 #define GPU_ATTR_POSITION 0 @@ -67,7 +70,8 @@ enum Buffer { namespace texture { enum Texture { ObjectTransforms = GPU_TEXTURE_TRANSFORM_OBJECT, -}; + MipCreationInput = GPU_TEXTURE_MIP_CREATION_INPUT, +}; } // namespace texture namespace storage { From 9bc85b3e5dbca4c4766cb2113ae0ee6c22eae658 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 27 Sep 2018 15:43:37 +0200 Subject: [PATCH 2/3] Fixed android build --- .../gpu-gles/src/gpu/gles/GLESBackend.cpp | 23 +++++++++++++++++++ libraries/gpu-gles/src/gpu/gles/GLESBackend.h | 3 +++ 2 files changed, 26 insertions(+) diff --git a/libraries/gpu-gles/src/gpu/gles/GLESBackend.cpp b/libraries/gpu-gles/src/gpu/gles/GLESBackend.cpp index b277889771..cb40b4fc9b 100644 --- a/libraries/gpu-gles/src/gpu/gles/GLESBackend.cpp +++ b/libraries/gpu-gles/src/gpu/gles/GLESBackend.cpp @@ -20,6 +20,29 @@ using namespace gpu::gles; const std::string GLESBackend::GLES_VERSION { "GLES" }; +void GLESBackend::draw(GLenum mode, uint32 numVertices, uint32 startVertex) { + if (isStereo()) { +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawArraysInstanced(mode, startVertex, numVertices, 2); +#else + setupStereoSide(0); + glDrawArrays(mode, startVertex, numVertices); + setupStereoSide(1); + glDrawArrays(mode, startVertex, numVertices); +#endif + _stats._DSNumTriangles += 2 * numVertices / 3; + _stats._DSNumDrawcalls += 2; + + } else { + glDrawArrays(mode, startVertex, numVertices); + _stats._DSNumTriangles += numVertices / 3; + _stats._DSNumDrawcalls++; + } + _stats._DSNumAPIDrawcalls++; + + (void)CHECK_GL_ERROR(); +} + void GLESBackend::do_draw(const Batch& batch, size_t paramOffset) { Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint; GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType]; diff --git a/libraries/gpu-gles/src/gpu/gles/GLESBackend.h b/libraries/gpu-gles/src/gpu/gles/GLESBackend.h index 56ae41da31..7f6765c129 100644 --- a/libraries/gpu-gles/src/gpu/gles/GLESBackend.h +++ b/libraries/gpu-gles/src/gpu/gles/GLESBackend.h @@ -126,6 +126,9 @@ public: }; protected: + + void draw(GLenum mode, uint32 numVertices, uint32 startVertex) override; + GLuint getFramebufferID(const FramebufferPointer& framebuffer) override; GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override; From 6abffceb43f3a701697503cdd20a82dcea1e7b10 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 16 Oct 2018 09:39:32 +0200 Subject: [PATCH 3/3] Mip generation texture slot is higher and doesn't interfere anymore --- .../src/gpu/gl/GLBackendTexture.cpp | 9 +++++++-- libraries/gpu/src/gpu/Batch.cpp | 2 -- libraries/gpu/src/gpu/MipGeneration.slh | 20 +++++++++++++++++++ libraries/gpu/src/gpu/ShaderConstants.h | 2 +- 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 libraries/gpu/src/gpu/MipGeneration.slh diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp index f4f2da3ee5..b74ff079d7 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp @@ -86,9 +86,14 @@ void GLBackend::do_generateTextureMipsWithPipeline(const Batch& batch, size_t pa return; } - // Do not transfer the texture, this call is expected for rendering texture + // Always make sure the GLObject is in sync GLTexture* object = syncGPUObject(resourceTexture); - if (!object) { + if (object) { + GLuint to = object->_texture; + glActiveTexture(GL_TEXTURE0 + gpu::slot::texture::MipCreationInput); + glBindTexture(object->_target, to); + (void)CHECK_GL_ERROR(); + } else { return; } diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 4cf678f26e..0e5fc1404f 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -418,8 +418,6 @@ void Batch::generateTextureMips(const TexturePointer& texture) { } void Batch::generateTextureMipsWithPipeline(const TexturePointer& texture, int numMips) { - setResourceTexture(gpu::slot::texture::MipCreationInput, texture); - ADD_COMMAND(generateTextureMipsWithPipeline); _params.emplace_back(_textures.cache(texture)); diff --git a/libraries/gpu/src/gpu/MipGeneration.slh b/libraries/gpu/src/gpu/MipGeneration.slh new file mode 100644 index 0000000000..bc8dd39042 --- /dev/null +++ b/libraries/gpu/src/gpu/MipGeneration.slh @@ -0,0 +1,20 @@ + +<@if not MIP_GENERATION_SLH@> +<@def MIP_GENERATION_SLH@> + +<@include gpu/ShaderConstants.h@> + +layout(binding=GPU_TEXTURE_MIP_CREATION_INPUT) uniform sampler2D texMap; + +in vec2 varTexCoord0; + +<@endif@> \ No newline at end of file diff --git a/libraries/gpu/src/gpu/ShaderConstants.h b/libraries/gpu/src/gpu/ShaderConstants.h index 426c64e913..0724b4eb40 100644 --- a/libraries/gpu/src/gpu/ShaderConstants.h +++ b/libraries/gpu/src/gpu/ShaderConstants.h @@ -22,7 +22,7 @@ #define GPU_TEXTURE_TRANSFORM_OBJECT 31 // Mip creation -#define GPU_TEXTURE_MIP_CREATION_INPUT 0 +#define GPU_TEXTURE_MIP_CREATION_INPUT 30 #define GPU_STORAGE_TRANSFORM_OBJECT 7