From cd5f37b066352119cf92d53d0001af7ff99be437 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 13 Sep 2021 01:01:51 +0300 Subject: [PATCH] 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. --- extensions/arb_texture_multisample.glext | 1 + .../arb_texture_storage_multisample.glext | 1 + source/builders/sequencebuilder.cpp | 1 - source/core/framebuffer.cpp | 89 ++++++++----------- source/core/framebuffer.h | 18 ++-- source/core/renderbuffer.cpp | 84 ----------------- source/core/renderbuffer.h | 52 ----------- source/core/texture2dmultisample.cpp | 73 +++++++++++++++ source/core/texture2dmultisample.h | 34 +++++++ source/effects/environmentmap.cpp | 2 +- source/effects/environmentmap.h | 4 +- source/effects/sky.cpp | 1 + source/render/rendertarget.cpp | 43 ++++----- source/render/rendertarget.h | 12 +-- source/render/sequence.cpp | 1 - source/render/sequence.h | 1 - 16 files changed, 176 insertions(+), 241 deletions(-) create mode 100644 extensions/arb_texture_multisample.glext create mode 100644 extensions/arb_texture_storage_multisample.glext delete mode 100644 source/core/renderbuffer.cpp delete mode 100644 source/core/renderbuffer.h create mode 100644 source/core/texture2dmultisample.cpp create mode 100644 source/core/texture2dmultisample.h 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" -- 2.43.0