From: Mikko Rasa Date: Sun, 12 Sep 2021 22:01:51 +0000 (+0300) Subject: Remove RenderBuffer and always use textures as framebuffer attachments X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=cd5f37b066352119cf92d53d0001af7ff99be437 Remove RenderBuffer and always use textures as framebuffer attachments Originally textures could not have multiple samples, but now they can. Vulkan only has images which are used for both purposes. --- diff --git a/extensions/arb_texture_multisample.glext b/extensions/arb_texture_multisample.glext new file mode 100644 index 00000000..15414ae1 --- /dev/null +++ b/extensions/arb_texture_multisample.glext @@ -0,0 +1 @@ +extension ARB_texture_multisample diff --git a/extensions/arb_texture_storage_multisample.glext b/extensions/arb_texture_storage_multisample.glext new file mode 100644 index 00000000..e596e8eb --- /dev/null +++ b/extensions/arb_texture_storage_multisample.glext @@ -0,0 +1 @@ +extension ARB_texture_storage_multisample diff --git a/source/builders/sequencebuilder.cpp b/source/builders/sequencebuilder.cpp index 12e7bdf3..337df476 100644 --- a/source/builders/sequencebuilder.cpp +++ b/source/builders/sequencebuilder.cpp @@ -3,7 +3,6 @@ #include #include "deviceinfo.h" #include "error.h" -#include "renderbuffer.h" #include "sequence.h" #include "sequencebuilder.h" #include "sequencetemplate.h" diff --git a/source/core/framebuffer.cpp b/source/core/framebuffer.cpp index 4dbb3092..93a72686 100644 --- a/source/core/framebuffer.cpp +++ b/source/core/framebuffer.cpp @@ -8,8 +8,8 @@ #include "error.h" #include "framebuffer.h" #include "misc.h" -#include "renderbuffer.h" #include "texture2d.h" +#include "texture2dmultisample.h" #include "texture3d.h" #include "windowview.h" @@ -106,37 +106,31 @@ void Framebuffer::update() const const Attachment &attch = attachments[i]; if(dirty&(1<get_id()); - else - glFramebufferRenderbuffer(GL_FRAMEBUFFER, attch.attachment, GL_RENDERBUFFER, attch.rbuf->get_id()); - } - else if(attch.type) + if(attch.tex) { + GLenum type = attch.tex->get_target(); if(ARB_direct_state_access) { - if(attch.type==GL_TEXTURE_2D || attch.layer<0) + if(type==GL_TEXTURE_2D || type==GL_TEXTURE_2D_MULTISAMPLE || attch.layer<0) glNamedFramebufferTexture(id, attch.attachment, attch.tex->get_id(), attch.level); else glNamedFramebufferTextureLayer(id, attch.attachment, attch.tex->get_id(), attch.level, attch.layer); } - else if(attch.type==GL_TEXTURE_2D) - glFramebufferTexture2D(GL_FRAMEBUFFER, attch.attachment, attch.type, attch.tex->get_id(), attch.level); + else if(type==GL_TEXTURE_2D || type==GL_TEXTURE_2D_MULTISAMPLE) + glFramebufferTexture2D(GL_FRAMEBUFFER, attch.attachment, type, attch.tex->get_id(), attch.level); else if(attch.layer<0) glFramebufferTexture(GL_FRAMEBUFFER, attch.attachment, attch.tex->get_id(), attch.level); - else if(attch.type==GL_TEXTURE_2D_ARRAY) + else if(type==GL_TEXTURE_2D_ARRAY) glFramebufferTextureLayer(GL_FRAMEBUFFER, attch.attachment, attch.tex->get_id(), attch.level, attch.layer); - else if(attch.type==GL_TEXTURE_3D) - glFramebufferTexture3D(GL_FRAMEBUFFER, attch.attachment, attch.type, attch.tex->get_id(), attch.level, attch.layer); - else if(attch.type==GL_TEXTURE_CUBE_MAP) + else if(type==GL_TEXTURE_3D) + glFramebufferTexture3D(GL_FRAMEBUFFER, attch.attachment, type, attch.tex->get_id(), attch.level, attch.layer); + else if(type==GL_TEXTURE_CUBE_MAP) glFramebufferTexture2D(GL_FRAMEBUFFER, attch.attachment, TextureCube::enumerate_faces(attch.layer), attch.tex->get_id(), attch.level); } else if(ARB_direct_state_access) - glNamedFramebufferRenderbuffer(id, attch.attachment, 0, 0); + glNamedFramebufferTexture(id, attch.attachment, 0, 0); else - glFramebufferRenderbuffer(GL_FRAMEBUFFER, attch.attachment, 0, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, attch.attachment, GL_TEXTURE_2D, 0, 0); } if(attch.attachment>=COLOR_ATTACHMENT0 && attch.attachment<=COLOR_ATTACHMENT3) @@ -176,26 +170,28 @@ void Framebuffer::update() const void Framebuffer::check_size() { for(vector::iterator i=attachments.begin(); i!=attachments.end(); ++i) - if(i->type) + if(i->tex) { - if(i->type==GL_RENDERBUFFER) - { - width = i->rbuf->get_width(); - height = i->rbuf->get_height(); - } - else if(i->type==GL_TEXTURE_2D) + GLenum type = i->tex->get_target(); + if(type==GL_TEXTURE_2D) { Texture2D *tex = static_cast(i->tex); width = max(tex->get_width()>>i->level, 1U); height = max(tex->get_height()>>i->level, 1U); } - else if(i->type==GL_TEXTURE_3D || i->type==GL_TEXTURE_2D_ARRAY) + else if(type==GL_TEXTURE_2D_MULTISAMPLE) + { + Texture2DMultisample *tex = static_cast(i->tex); + width = tex->get_width(); + height = tex->get_height(); + } + else if(type==GL_TEXTURE_3D || type==GL_TEXTURE_2D_ARRAY) { Texture3D *tex = static_cast(i->tex); width = max(tex->get_width()>>i->level, 1U); height = max(tex->get_height()>>i->level, 1U); } - else if(i->type==GL_TEXTURE_CUBE_MAP) + else if(type==GL_TEXTURE_CUBE_MAP) { width = max(static_cast(i->tex)->get_size()>>i->level, 1U); height = width; @@ -213,7 +209,7 @@ unsigned Framebuffer::get_attachment_index(FramebufferAttachment attch) return attachments.size()-1; } -void Framebuffer::set_texture_attachment(FramebufferAttachment attch, Texture &tex, unsigned level, int layer) +void Framebuffer::set_attachment(FrameAttachment attch, Texture &tex, unsigned level, int layer) { if(!id) throw invalid_operation("Framebuffer::attach"); @@ -224,47 +220,41 @@ void Framebuffer::set_texture_attachment(FramebufferAttachment attch, Texture &t check_size(); } -void Framebuffer::attach(FramebufferAttachment attch, Renderbuffer &rbuf) +void Framebuffer::attach(FramebufferAttachment attch, Texture2D &tex, unsigned level) { - if(!id) - throw invalid_operation("Framebuffer::attach"); - - unsigned i = get_attachment_index(attch); - attachments[i].set(rbuf); - dirty |= 1< -#include -#include -#include -#include "deviceinfo.h" -#include "renderbuffer.h" - -using namespace std; - -namespace Msp { -namespace GL { - -Renderbuffer::Renderbuffer() -{ - static Require _req(EXT_framebuffer_object); - - if(ARB_direct_state_access) - glCreateRenderbuffers(1, &id); - else - glGenRenderbuffers(1, &id); -} - -Renderbuffer::~Renderbuffer() -{ - glDeleteRenderbuffers(1, &id); -} - -void Renderbuffer::storage(PixelFormat fmt, unsigned wd, unsigned ht) -{ - require_pixelformat(fmt); - width = wd; - height = ht; - GLenum gl_fmt = get_gl_pixelformat(fmt); - if(ARB_direct_state_access) - glNamedRenderbufferStorage(id, gl_fmt, width, height); - else - { - glBindRenderbuffer(GL_RENDERBUFFER, id); - glRenderbufferStorage(GL_RENDERBUFFER, gl_fmt, width, height); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - } -} - -unsigned Renderbuffer::get_max_samples() -{ - return Limits::get_global().max_samples; -} - -void Renderbuffer::storage_multisample(unsigned samples, PixelFormat fmt, unsigned wd, unsigned ht) -{ - if(!samples) - return storage(fmt, wd, ht); - - static Require _req(EXT_framebuffer_multisample); - if(samples>Limits::get_global().max_samples) - throw out_of_range("Renderbuffer::storage_multisample"); - - require_pixelformat(fmt); - - width = wd; - height = ht; - GLenum gl_fmt = get_gl_pixelformat(fmt); - if(ARB_direct_state_access) - glNamedRenderbufferStorageMultisample(id, samples, gl_fmt, width, height); - else - { - glBindRenderbuffer(GL_RENDERBUFFER, id); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, gl_fmt, width, height); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - } -} - -void Renderbuffer::set_debug_name(const string &name) -{ -#ifdef DEBUG - if(KHR_debug) - glObjectLabel(GL_RENDERBUFFER, id, name.size(), name.c_str()); -#else - (void)name; -#endif -} - -} // namespace GL -} // namespace Msp diff --git a/source/core/renderbuffer.h b/source/core/renderbuffer.h deleted file mode 100644 index 84ed3f28..00000000 --- a/source/core/renderbuffer.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MSP_GL_RENDERBUFFER_H_ -#define MSP_GL_RENDERBUFFER_H_ - -#include "pixelformat.h" - -namespace Msp { -namespace GL { - -/** -A Renderbuffer contains a single renderable image. It can be attached to a -Framebuffer to provide a logical buffer that is required to render the scene -correctly but that is not needed as a texture later. Renderbuffers also -provide a capability for multisampling, which is not available in textures. - -Requires the GL_EXT_framebuffer_object extension. Multisample renderbuffers -additionally require the GL_EXT_framebuffer_multisample extension. -*/ -class Renderbuffer -{ -private: - unsigned id; - unsigned width; - unsigned height; - -public: - Renderbuffer(); - ~Renderbuffer(); - - unsigned get_id() const { return id; } - unsigned get_width() const { return width; } - unsigned get_height() const { return height; } - - /** Allocates storage for the renderbuffer. */ - void storage(PixelFormat fmt, unsigned wd, unsigned ht); - - /** Returns the maximum supported sample count for multisampling. If - multisampling is not supported, returns 0. */ - DEPRECATED static unsigned get_max_samples(); - - /** Allocates multisample storage for the renderbuffer. All attachments in - a framebuffer must have the same number of samples. To transfer the - contents to a texture for furter processing, use the framebuffer blit - functions.*/ - void storage_multisample(unsigned samples, PixelFormat fmt, unsigned wd, unsigned ht); - - void set_debug_name(const std::string &); -}; - -} // namespace GL -} // namespace Msp - -#endif diff --git a/source/core/texture2dmultisample.cpp b/source/core/texture2dmultisample.cpp new file mode 100644 index 00000000..18e21b76 --- /dev/null +++ b/source/core/texture2dmultisample.cpp @@ -0,0 +1,73 @@ +#include +#include +#include +#include "deviceinfo.h" +#include "error.h" +#include "texture2dmultisample.h" + +using namespace std; + +namespace Msp { +namespace GL { + +Texture2DMultisample::Texture2DMultisample(): + Texture(GL_TEXTURE_2D_MULTISAMPLE), + width(0), + height(0) +{ + static Require _req(ARB_texture_multisample); +} + +void Texture2DMultisample::storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned sm) +{ + if(width>0) + { + if(fmt!=format || wd!=width || ht!=height || sm!=samples) + throw incompatible_data("Texture2DMultisample::storage"); + return; + } + if(wd==0 || ht==0) + throw invalid_argument("Texture2DMultisample::storage"); + if(!sm || sm>Limits::get_global().max_samples) + throw invalid_argument("Texture2DMultisample::storage"); + + set_format(fmt); + width = wd; + height = ht; + samples = sm; + + bool direct = ARB_texture_storage_multisample && ARB_direct_state_access; + if(!direct) + { + glActiveTexture(GL_TEXTURE0); + glBindTexture(target, id); + } + + GLenum gl_fmt = get_gl_pixelformat(storage_fmt); + if(ARB_texture_storage_multisample) + { + if(ARB_direct_state_access) + glTextureStorage2DMultisample(id, samples, gl_fmt, width, height, false); + else + glTexStorage2DMultisample(target, samples, gl_fmt, width, height, false); + } + else + glTexImage2DMultisample(target, samples, gl_fmt, width, height, false); + apply_swizzle(); + + if(!direct) + glBindTexture(target, 0); +} + +void Texture2DMultisample::image(const Graphics::Image &, unsigned) +{ + throw invalid_operation("Texture2DMultisample::image"); +} + +UInt64 Texture2DMultisample::get_data_size() const +{ + return id ? width*height*get_pixel_size(format)*samples : 0; +} + +} // namespace GL +} // namespace Msp diff --git a/source/core/texture2dmultisample.h b/source/core/texture2dmultisample.h new file mode 100644 index 00000000..cb086f0d --- /dev/null +++ b/source/core/texture2dmultisample.h @@ -0,0 +1,34 @@ +#ifndef MSP_GL_TEXTURE2DMULTISAMPLE_H_ +#define MSP_GL_TEXTURE2DMULTISAMPLE_H_ + +#include "texture.h" + +namespace Msp { +namespace GL { + +class Texture2DMultisample: public Texture +{ +private: + unsigned width; + unsigned height; + unsigned samples; + +public: + Texture2DMultisample(); + + void storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned sm); + + virtual void image(const Graphics::Image &, unsigned = 0); + + unsigned get_width() const { return width; } + unsigned get_height() const { return height; } + + virtual AsyncLoader *load(IO::Seekable &, const Resources * = 0) { return 0; } + virtual UInt64 get_data_size() const; + virtual void unload() { } +}; + +} // namespace GL +} // namespace Msp + +#endif diff --git a/source/effects/environmentmap.cpp b/source/effects/environmentmap.cpp index 1cefde1b..5002e0f8 100644 --- a/source/effects/environmentmap.cpp +++ b/source/effects/environmentmap.cpp @@ -57,7 +57,7 @@ void EnvironmentMap::init(unsigned s, PixelFormat f, unsigned l) update_delay = 0; env_tex.storage(f, size, l); - depth_buf.storage(DEPTH_COMPONENT32F, size, size); + depth_buf.storage(DEPTH_COMPONENT32F, size, size, 1); for(unsigned i=0; i<6; ++i) { TextureCubeFace face = TextureCube::enumerate_faces(i); diff --git a/source/effects/environmentmap.h b/source/effects/environmentmap.h index 4936d162..e02687b7 100644 --- a/source/effects/environmentmap.h +++ b/source/effects/environmentmap.h @@ -6,7 +6,7 @@ #include "framebuffer.h" #include "matrix.h" #include "programdata.h" -#include "renderbuffer.h" +#include "texture2d.h" #include "texturecube.h" #include "vector.h" @@ -36,7 +36,7 @@ private: unsigned size; Renderable &environment; TextureCube env_tex; - Renderbuffer depth_buf; + Texture2D depth_buf; Face faces[6]; TextureCube irradiance; diff --git a/source/effects/sky.cpp b/source/effects/sky.cpp index a210efc9..23819db3 100644 --- a/source/effects/sky.cpp +++ b/source/effects/sky.cpp @@ -4,6 +4,7 @@ #include "mesh.h" #include "renderer.h" #include "resources.h" +#include "texture2d.h" #include "sky.h" using namespace std; diff --git a/source/render/rendertarget.cpp b/source/render/rendertarget.cpp index f2f12d50..426b2d52 100644 --- a/source/render/rendertarget.cpp +++ b/source/render/rendertarget.cpp @@ -1,8 +1,9 @@ #include #include #include "error.h" -#include "renderbuffer.h" #include "rendertarget.h" +#include "texture2d.h" +#include "texture2dmultisample.h" using namespace std; @@ -137,42 +138,37 @@ void RenderTarget::init(unsigned w, unsigned h, unsigned s, const RenderTargetFo PixelFormat pf = get_output_pixelformat(*i); - TargetBuffer tgt; if(samples) { - tgt.buffer = new Renderbuffer; - tgt.buffer->storage_multisample(samples, pf, width, height); - fbo.attach(att, *tgt.buffer); + Texture2DMultisample *tex2d_ms = new Texture2DMultisample; + tex2d_ms->storage(pf, width, height, samples); + fbo.attach(att, *tex2d_ms); + textures.push_back(tex2d_ms); } else { - tgt.texture = new Texture2D; - tgt.texture->storage(pf, width, height, 1); - fbo.attach(att, *tgt.texture); + Texture2D *tex2d = new Texture2D; + tex2d->storage(pf, width, height, 1); + fbo.attach(att, *tex2d); + textures.push_back(tex2d); } - buffers.push_back(tgt); } } RenderTarget::~RenderTarget() { - for(vector::iterator i=buffers.begin(); i!=buffers.end(); ++i) - { - if(samples) - delete i->buffer; - else - delete i->texture; - } + for(vector::iterator i=textures.begin(); i!=textures.end(); ++i) + delete *i; } const Texture2D &RenderTarget::get_target_texture(unsigned i) const { - if(i>=buffers.size()) + if(i>=textures.size()) throw out_of_range("RenderTarget::get_target_texture"); if(samples) throw invalid_operation("RenderTarget::get_target_texture"); - return *buffers[i].texture; + return *static_cast(textures[i]); } const Texture2D &RenderTarget::get_target_texture(RenderOutput o) const @@ -193,16 +189,13 @@ void RenderTarget::set_debug_name(const string &name) { unsigned type = get_output_type(*j); - string buf_name; + string tex_name; if(type>=get_output_type(RENDER_DEPTH)) - buf_name = name+"/depth"; + tex_name = name+"/depth"; else - buf_name = Msp::format("%s/color%d", name, type); + tex_name = Msp::format("%s/color%d", name, type); - if(samples) - buffers[i].buffer->set_debug_name(buf_name+".rbuf"); - else - buffers[i].texture->set_debug_name(buf_name+".tex2d"); + textures[i]->set_debug_name(tex_name+".tex2d"); } #else (void)name; diff --git a/source/render/rendertarget.h b/source/render/rendertarget.h index 030e4577..f13d23d9 100644 --- a/source/render/rendertarget.h +++ b/source/render/rendertarget.h @@ -2,11 +2,13 @@ #define RENDERTARGET_H_ #include "framebuffer.h" -#include "texture2d.h" namespace Msp { namespace GL { +class Texture; +class Texture2D; + enum RenderOutput { RENDER_COLOR = 0|3, @@ -49,17 +51,11 @@ PixelFormat get_output_pixelformat(unsigned char); class RenderTarget { private: - union TargetBuffer - { - Texture2D *texture; - Renderbuffer *buffer; - }; - unsigned width; unsigned height; unsigned samples; RenderTargetFormat format; - std::vector buffers; + std::vector textures; Framebuffer fbo; public: diff --git a/source/render/sequence.cpp b/source/render/sequence.cpp index 472b572f..aaa1ef12 100644 --- a/source/render/sequence.cpp +++ b/source/render/sequence.cpp @@ -4,7 +4,6 @@ #include "framebuffer.h" #include "lighting.h" #include "postprocessor.h" -#include "renderbuffer.h" #include "renderer.h" #include "sequence.h" #include "texture2d.h" diff --git a/source/render/sequence.h b/source/render/sequence.h index be8ed306..8e6c45af 100644 --- a/source/render/sequence.h +++ b/source/render/sequence.h @@ -7,7 +7,6 @@ #include "depthtest.h" #include "framebuffer.h" #include "renderable.h" -#include "renderbuffer.h" #include "rendertarget.h" #include "stenciltest.h" #include "texture2d.h"