mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 11:33:44 +02:00
Bringin the Framebuffer to GLBackend and refining the interface
This commit is contained in:
parent
69484ad00b
commit
05689c0413
9 changed files with 169 additions and 55 deletions
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Stream::FormatPointer>::Vector StreamFormatCaches;
|
||||
typedef Cache<Transform>::Vector TransformCaches;
|
||||
typedef Cache<PipelinePointer>::Vector PipelineCaches;
|
||||
typedef Cache<FramebufferPointer>::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:
|
||||
};
|
||||
|
|
|
@ -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<T*>(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<T*>(framebuffer.getGPUObject());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
|
|
@ -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<<slot);
|
||||
|
@ -188,7 +177,7 @@ void Framebuffer::removeRenderBuffers() {
|
|||
_buffersMask = _buffersMask & BUFFER_DEPTHSTENCIL;
|
||||
|
||||
for (auto renderBuffer : _renderBuffers) {
|
||||
renderBuffer.reset();
|
||||
renderBuffer._texture.reset();
|
||||
}
|
||||
|
||||
updateSize(TexturePointer(nullptr));
|
||||
|
@ -205,7 +194,7 @@ uint32 Framebuffer::getNumRenderBuffers() const {
|
|||
|
||||
TexturePointer Framebuffer::getRenderBuffer(uint32 slot) const {
|
||||
if (!isSwapchain() && (slot < getMaxNumRenderBuffers())) {
|
||||
return _renderBuffers[slot];
|
||||
return _renderBuffers[slot]._texture;
|
||||
} else {
|
||||
return TexturePointer();
|
||||
}
|
||||
|
@ -214,7 +203,7 @@ TexturePointer Framebuffer::getRenderBuffer(uint32 slot) const {
|
|||
|
||||
uint32 Framebuffer::getRenderBufferSubresource(uint32 slot) const {
|
||||
if (!isSwapchain() && (slot < getMaxNumRenderBuffers())) {
|
||||
return _renderBuffersSubresource[slot];
|
||||
return _renderBuffers[slot]._subresource;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -232,15 +221,10 @@ bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, uint32 su
|
|||
}
|
||||
}
|
||||
|
||||
// Checks ok, assign
|
||||
_depthStencilBuffer.reset();
|
||||
_depthStencilBufferSubresource = 0;
|
||||
|
||||
updateSize(texture);
|
||||
|
||||
// assign the new one
|
||||
_depthStencilBuffer = texture;
|
||||
_depthStencilBufferSubresource = subresource;
|
||||
_depthStencilBuffer = TextureView(texture, subresource);
|
||||
|
||||
_buffersMask = ( _buffersMask & ~BUFFER_DEPTHSTENCIL);
|
||||
if (texture) {
|
||||
|
@ -254,7 +238,7 @@ TexturePointer Framebuffer::getDepthStencilBuffer() const {
|
|||
if (isSwapchain()) {
|
||||
return TexturePointer();
|
||||
} else {
|
||||
return _depthStencilBuffer;
|
||||
return _depthStencilBuffer._texture;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,6 +246,6 @@ uint32 Framebuffer::getDepthStencilBufferSubresource() const {
|
|||
if (isSwapchain()) {
|
||||
return 0;
|
||||
} else {
|
||||
return _depthStencilBufferSubresource;
|
||||
return _depthStencilBuffer._subresource;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,11 +155,9 @@ public:
|
|||
// Get viewport covering the ful Canvas
|
||||
Viewport getViewport() const { return Viewport(getWidth(), getHeight(), 0, 0); }
|
||||
|
||||
bool isDefined() const { return _isDefined; }
|
||||
|
||||
protected:
|
||||
|
||||
Viewport _viewport;
|
||||
|
||||
uint16 _width;
|
||||
uint16 _height;
|
||||
uint16 _numSamples;
|
||||
|
@ -170,12 +168,10 @@ protected:
|
|||
|
||||
SwapchainPointer _swapchain;
|
||||
|
||||
Textures _renderBuffers;
|
||||
std::vector<uint32> _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<Framebuffer> FramebufferPointer;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
72
libraries/gpu/src/gpu/GLBackendOutput.cpp
Executable file
72
libraries/gpu/src/gpu/GLBackendOutput.cpp
Executable file
|
@ -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<GLBackend::GLFramebuffer>(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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<TextureView> TextureViews;
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue