diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 9eb9648478..4b145b55a0 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -25,7 +25,8 @@ Batch::Batch() : _textures(), _streamFormats(), _transforms(), - _pipelines() + _pipelines(), + _framebuffers() { } @@ -41,7 +42,8 @@ void Batch::clear() { _textures.clear(); _streamFormats.clear(); _transforms.clear(); - _pipelines.clear(); + _pipelines.clear(); + _framebuffers.clear(); } uint32 Batch::cacheData(uint32 size, const void* data) { @@ -186,3 +188,10 @@ void Batch::setUniformTexture(uint32 slot, const TextureView& view) { setUniformTexture(slot, view._texture); } +void Batch::setFramebuffer(const FramebufferPointer& framebuffer) { + ADD_COMMAND(setUniformTexture); + + _params.push_back(_framebuffers.cache(framebuffer)); + +} + diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 6e8a2d1da6..b6bc05ab40 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -23,6 +23,8 @@ #include "Pipeline.h" +#include "Framebuffer.h" + #if defined(NSIGHT_FOUND) #include "nvToolsExt.h" class ProfileRange { @@ -112,6 +114,8 @@ public: void setUniformTexture(uint32 slot, const TexturePointer& view); void setUniformTexture(uint32 slot, const TextureView& view); // not a command, just a shortcut from a TextureView + // Framebuffer Stage + void setFramebuffer(const FramebufferPointer& framebuffer); // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long @@ -170,6 +174,8 @@ public: COMMAND_setUniformBuffer, COMMAND_setUniformTexture, + COMMAND_setFramebuffer, + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -266,6 +272,7 @@ public: typedef Cache::Vector StreamFormatCaches; typedef Cache::Vector TransformCaches; typedef Cache::Vector PipelineCaches; + typedef Cache::Vector FramebufferCaches; // Cache Data in a byte array if too big to fit in Param // FOr example Mat4s are going there @@ -289,6 +296,7 @@ public: StreamFormatCaches _streamFormats; TransformCaches _transforms; PipelineCaches _pipelines; + FramebufferCaches _framebuffers; protected: }; diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 8276ff5f95..022ca02d6d 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -15,8 +15,8 @@ #include "Resource.h" #include "Texture.h" -#include "Shader.h" #include "Pipeline.h" +#include "Framebuffer.h" namespace gpu { @@ -47,8 +47,8 @@ public: }; template< typename T > - static void setGPUObject(const Buffer& buffer, T* bo) { - buffer.setGPUObject(bo); + static void setGPUObject(const Buffer& buffer, T* object) { + buffer.setGPUObject(object); } template< typename T > static T* getGPUObject(const Buffer& buffer) { @@ -56,8 +56,8 @@ public: } template< typename T > - static void setGPUObject(const Texture& texture, T* to) { - texture.setGPUObject(to); + static void setGPUObject(const Texture& texture, T* object) { + texture.setGPUObject(object); } template< typename T > static T* getGPUObject(const Texture& texture) { @@ -65,8 +65,8 @@ public: } template< typename T > - static void setGPUObject(const Shader& shader, T* so) { - shader.setGPUObject(so); + static void setGPUObject(const Shader& shader, T* object) { + shader.setGPUObject(object); } template< typename T > static T* getGPUObject(const Shader& shader) { @@ -74,8 +74,8 @@ public: } template< typename T > - static void setGPUObject(const Pipeline& pipeline, T* po) { - pipeline.setGPUObject(po); + static void setGPUObject(const Pipeline& pipeline, T* object) { + pipeline.setGPUObject(object); } template< typename T > static T* getGPUObject(const Pipeline& pipeline) { @@ -83,14 +83,23 @@ public: } template< typename T > - static void setGPUObject(const State& state, T* so) { - state.setGPUObject(so); + static void setGPUObject(const State& state, T* object) { + state.setGPUObject(object); } template< typename T > static T* getGPUObject(const State& state) { return reinterpret_cast(state.getGPUObject()); } + template< typename T > + static void setGPUObject(const Framebuffer& framebuffer, T* object) { + framebuffer.setGPUObject(object); + } + template< typename T > + static T* getGPUObject(const Framebuffer& framebuffer) { + return reinterpret_cast(framebuffer.getGPUObject()); + } + protected: }; diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp index 597a31788e..de8961886b 100755 --- a/libraries/gpu/src/gpu/Framebuffer.cpp +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -26,7 +26,6 @@ Framebuffer::~Framebuffer() Framebuffer* Framebuffer::create() { auto framebuffer = new Framebuffer(); framebuffer->_renderBuffers.resize(MAX_NUM_RENDER_BUFFERS); - framebuffer->_renderBuffersSubresource.resize(MAX_NUM_RENDER_BUFFERS, 0); return framebuffer; } @@ -96,14 +95,14 @@ void Framebuffer::resize(uint16 width, uint16 height, uint16 numSamples) { if ((width != _width) || (height != _height) || (numSamples != _numSamples)) { for (uint32 i = 0; i < _renderBuffers.size(); ++i) { if (_renderBuffers[i]) { - _renderBuffers[i]->resize2D(width, height, numSamples); - _numSamples = _renderBuffers[i]->getNumSamples(); + _renderBuffers[i]._texture->resize2D(width, height, numSamples); + _numSamples = _renderBuffers[i]._texture->getNumSamples(); } } if (_depthStencilBuffer) { - _depthStencilBuffer->resize2D(width, height, numSamples); - _numSamples = _depthStencilBuffer->getNumSamples(); + _depthStencilBuffer._texture->resize2D(width, height, numSamples); + _numSamples = _depthStencilBuffer._texture->getNumSamples(); } _width = width; @@ -155,20 +154,10 @@ int Framebuffer::setRenderBuffer(uint32 slot, const TexturePointer& texture, uin } } - // everything works, assign - // dereference the previously used buffer if exists - if (_renderBuffers[slot]) { - _renderBuffers[slot].reset(); - _renderBuffersSubresource[slot] = 0; - } - updateSize(texture); // assign the new one - _renderBuffers[slot] = texture; - - // Assign the subresource - _renderBuffersSubresource[slot] = subresource; + _renderBuffers[slot] = TextureView(texture, subresource); // update the mask int mask = (1< _renderBuffersSubresource; - - TexturePointer _depthStencilBuffer; - uint32 _depthStencilBufferSubresource; + TextureViews _renderBuffers; + TextureView _depthStencilBuffer; + bool _isDefined = false; void updateSize(const TexturePointer& texture); @@ -189,6 +185,7 @@ protected: GPUObject* getGPUObject() const { return _gpuObject; } friend class Backend; }; +typedef std::shared_ptr FramebufferPointer; } diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 8fcc2362c1..c9de132b73 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -32,6 +32,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_setUniformBuffer), (&::gpu::GLBackend::do_setUniformTexture), + (&::gpu::GLBackend::do_setFramebuffer), + + (&::gpu::GLBackend::do_glEnable), (&::gpu::GLBackend::do_glDisable), @@ -67,7 +70,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = GLBackend::GLBackend() : _input(), _transform(), - _pipeline() + _pipeline(), + _output() { initTransform(); } diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index ea97fd8908..e3069f5205 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -133,14 +133,25 @@ public: class GLPipeline : public GPUObject { public: - GLShader* _program; - GLState* _state; + GLShader* _program = 0; + GLState* _state = 0; GLPipeline(); ~GLPipeline(); }; static GLPipeline* syncGPUObject(const Pipeline& pipeline); + + class GLFramebuffer : public GPUObject { + public: + GLuint _fbo = 0; + + GLFramebuffer(); + ~GLFramebuffer(); + }; + static GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer); + static GLuint getFramebufferID(const FramebufferPointer& framebuffer); + static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS; static const int MAX_NUM_INPUT_BUFFERS = 16; @@ -276,8 +287,8 @@ protected: State::Signature _stateSignatureCache; GLState* _state; - bool _invalidState; - bool _needStateSync; + bool _invalidState = false; + bool _needStateSync = true; PipelineStageState() : _pipeline(), @@ -291,6 +302,16 @@ protected: {} } _pipeline; + // Output stage + void do_setFramebuffer(Batch& batch, uint32 paramOffset); + + struct OutputStageState { + + FramebufferPointer _framebuffer = nullptr; + + OutputStageState() {} + } _output; + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp new file mode 100755 index 0000000000..8865008e49 --- /dev/null +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -0,0 +1,72 @@ +// +// GLBackendTexture.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 1/19/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "GPULogging.h" +#include "GLBackendShared.h" + + +GLBackend::GLFramebuffer::GLFramebuffer() +{} + +GLBackend::GLFramebuffer::~GLFramebuffer() { + if (_fbo != 0) { + glDeleteFramebuffers(1, &_fbo); + } +} + +GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffer) { + GLFramebuffer* object = Backend::getGPUObject(framebuffer); + + // If GPU object already created and in sync + bool needUpdate = false; + if (object) { + return object; + } else if (!framebuffer.isDefined()) { + // NO framebuffer definition yet so let's avoid thinking + return nullptr; + } + + // need to have a gpu object? + if (!object) { + object = new GLFramebuffer(); + glGenFramebuffers(1, &object->_fbo); + CHECK_GL_ERROR(); + Backend::setGPUObject(framebuffer, object); + } + + + CHECK_GL_ERROR(); + + return object; +} + + + +GLuint GLBackend::getFramebufferID(const FramebufferPointer& framebuffer) { + if (!framebuffer) { + return 0; + } + GLFramebuffer* object = GLBackend::syncGPUObject(*framebuffer); + if (object) { + return object->_fbo; + } else { + return 0; + } +} + +void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) { + auto framebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint); + + if (_output._framebuffer != framebuffer) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(framebuffer)); + _output._framebuffer = framebuffer; + } +} + diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 3eed52c686..cb124b7b08 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -240,15 +240,25 @@ public: _subresource(0), _element(element) {}; - TextureView(const TexturePointer& texture, const Element& element) : + TextureView(const TexturePointer& texture, uint16 subresource, const Element& element) : _texture(texture), - _subresource(0), + _subresource(subresource), _element(element) {}; + + TextureView(const TexturePointer& texture, uint16 subresource) : + _texture(texture), + _subresource(subresource) + {}; + ~TextureView() {} TextureView(const TextureView& view) = default; TextureView& operator=(const TextureView& view) = default; + + explicit operator bool() const { return (_texture); } + bool operator !() const { return (!_texture); } }; +typedef std::vector TextureViews; };