Beispiel #1
0
void GLFramebufferObject::setDrawBuffers(
    Array1DReadView< GLenum > attachments )
{
    assert( attachments.packed() );
    glNamedFramebufferDrawBuffers( m_id,
        static_cast< GLsizei >( attachments.size() ), attachments.pointer() );
}
Beispiel #2
0
			void colorBuffersOutputActivate(T ... vals) noexcept
				{
				std::array<unsigned int,sizeof...(vals)> val_array{vals...};
				auto ptr=val_array.begin();
				while(ptr!=val_array.end())
					{
					*ptr+=GL_COLOR_ATTACHMENT0;
					++ptr;
					}
				glNamedFramebufferDrawBuffers(m_handle,val_array.size(),val_array.begin());
				}
Beispiel #3
0
kit::PixelBuffer::Ptr kit::PixelBuffer::create(glm::uvec2 resolution, kit::PixelBuffer::AttachmentList colorattachments)
{
  
  kit::PixelBuffer::Ptr returner = std::make_shared<kit::PixelBuffer>();
  
  returner->m_resolution = resolution;
  
  if(colorattachments.size() == 0)
  {
    KIT_GL(glNamedFramebufferDrawBuffer(returner->m_glHandle, GL_NONE));
  }
  else
  {
    // Keep track of attachments and create a drawbuffers
    std::vector<GLenum> drawBuffers(colorattachments.size());
    uint32_t currAttachment = 0;
    
    // Add/create color attachments
    for(auto & info : colorattachments)
    {
      // Fill the drawbuffer
      GLenum currEnum = GL_COLOR_ATTACHMENT0+ currAttachment;
      drawBuffers[currAttachment] = currEnum;
      currAttachment++;

      // Add texture if exists, otherwise create it 
      if(info.texture != nullptr)
      {
        // Assert resolution
        if(info.texture->getResolution().x != resolution.x || info.texture->getResolution().y != resolution.y)
        {
          KIT_THROW("Pixelbuffer attachments must be of the same size");
        }
        
        returner->m_colorAttachments.push_back(info.texture);
        KIT_GL(glNamedFramebufferTexture(returner->m_glHandle, currEnum, info.texture->getHandle(), 0));
      }
      else
      {
        kit::Texture::Ptr adder = kit::Texture::create2D(resolution, info.format, info.edgeSamplingMode, info.minFilteringMode, info.magFilteringMode);
        returner->m_colorAttachments.push_back(adder);
        KIT_GL(glNamedFramebufferTexture(returner->m_glHandle, currEnum, adder->getHandle(), 0));
      }
    }

    
    // Set drawbuffers
    KIT_GL(glNamedFramebufferDrawBuffers(returner->m_glHandle, (GLsizei)drawBuffers.size(), &drawBuffers[0]));
  }
  
  return returner;
}
void RaycastingPass::draw(const Camera & cam, const gl::FBO & fbo, const std::vector<std::shared_ptr<Light>> lights) {

	fbo.bind();

	glViewport(0, 0, static_cast<GLsizei>(cam.getWidth()), static_cast<GLsizei>(cam.getHeight()));

	GLenum db[3] {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
	glNamedFramebufferDrawBuffers(fbo, 3, db);

	glEnable(GL_DEPTH_TEST);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor(0.f, 0.f, 0.f, 1.f);

	m_program.use();

	m_lightBuffer.bindTo(0);

	size_t size = lights.size();
	std::vector<LightData> data;
	for (const auto & light : lights) {
		data.emplace_back(light->getData());
	}	
	m_lightBuffer.addData(data, static_cast<unsigned int>(size));

	m_program["camPos"] = cam.getPos();
	m_program["viewDir"] = cam.getDir();
	m_program["lightDataSize"] = size;

	for (auto id : m_objects) {

		m_program["MVP"] = cam.getProjMat() * cam.getViewMat() * ObjectInterface::getModelMatrix(id);
		m_program["M_IT"] = glm::inverse(glm::transpose(ObjectInterface::getModelMatrix(id)));
		m_program["M"] = ObjectInterface::getModelMatrix(id);

		m_program["material.emission"] = ObjectID::getID(id)->getEmission();
		m_program["material.ambient"] = ObjectID::getID(id)->getAmbient();
		m_program["material.diffuse"] = ObjectID::getID(id)->getDiffuse();
		m_program["material.specular"] = ObjectID::getID(id)->getSpecular();
		m_program["material.shininess"] = ObjectID::getID(id)->getShininess();

		ObjectInterface::draw(id);

	}
		
	fbo.unbind();

}
Beispiel #5
0
void
piglit_init(int argc, char **argv)
{
	bool pass = true;
	GLuint framebuffer;
	GLuint default_framebuffer = 0;
	GLenum bufs[2] = {GL_BACK_LEFT, GL_BACK};
	GLenum one_buf;
	bool subtest_pass;
	int i;

	glCreateFramebuffers(1, &framebuffer);
	piglit_check_gl_error(GL_NO_ERROR);

	/*
	 * "An INVALID_OPERATION error is generated by
	 *  NamedFramebufferDrawBuffers if framebuffer is not zero or
	 *  the name of an existing framebuffer"
	 */
	glNamedFramebufferDrawBuffers(5, 2, bufs);
	PIGLIT_SUBTEST_ERROR(GL_INVALID_OPERATION, pass, "INVALID_OPERATION if "
			     "framebuffer is not zero or the name of an existing "
			     "framebuffer");

	/*
	 * "An INVALID_VALUE error is generated if n is negative, or greater than the
	 *  value of MAX_DRAW_BUFFERS."
	 */
	int max_draw_buffers;
	glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers);

	subtest_pass = true;
	glNamedFramebufferDrawBuffers(0, -1, bufs);
	subtest_pass = subtest_pass & piglit_check_gl_error(GL_INVALID_VALUE);

	glNamedFramebufferDrawBuffers(0, max_draw_buffers + 1, bufs);
	subtest_pass = subtest_pass & piglit_check_gl_error(GL_INVALID_VALUE);

	PIGLIT_SUBTEST_CONDITION(subtest_pass, pass, "INVALID_VALUE error is "
				 "generated if n is negative, or greater than "
				 "the value of MAX_DRAW_BUFFERS.");

	/*
	 * From OpenGL 4.5 spec
	 *   "An INVALID_ENUM error is generated if any value in bufs
	 *    is not one of the values in tables 17.5 or 17.6."
	 */
	subtest_pass = true;
	one_buf = GL_RED;
	glNamedFramebufferDrawBuffers(default_framebuffer, 1, &one_buf);
	subtest_pass = subtest_pass && piglit_check_gl_error(GL_INVALID_ENUM);
	glNamedFramebufferDrawBuffers(framebuffer, 1, &one_buf);
	subtest_pass = subtest_pass && piglit_check_gl_error(GL_INVALID_ENUM);

	PIGLIT_SUBTEST_CONDITION(subtest_pass, pass, "INVALID_ENUM error is "
				 "generated if any value in bufs is not one of "
				 "the values in tables 17.5 or 17.6.");
	/*
	* (cont on error out of 17.5 or 17.6) Specifically for the default
	 * framebuffer:
	 * From OpenGL 4.5 spec, page 492 (515 PDF)
	 * "If the default framebuffer is affected, then each of the
	 *  constants must be one of the values listed in table 17.6
	 *  or the special value BACK .""
	 *
	 * And:
	 *"An INVALID_OPERATION error is generated if the default
	 *  framebuffer is affected and any value in bufs is a
	 *  constant (other than NONE or BACK) that does not indicate
	 *  one of the color buffers allocated to the default
	 *  framebuffer."
	 *
	 * So for the default framebuffer, and that table, we expect
	 * GL_NO_ERROR or GL_INVALID_OPERATION.
	 */
	subtest_pass = true;
	for (i = 0; i < ARRAY_SIZE(table_17_6_and_back); i++) {
		GLenum err = 0;

		glNamedFramebufferDrawBuffers(default_framebuffer, 1,
					      &table_17_6_and_back[i]);

		/* We manually check glGetError instead of relying on
		 * piglit_check_gl_error like in other subtests
		 * because for subtests that checks several enums, we
		 * are interested on getting which one failed. That
		 * makes debugging easier.
		 */
		err = glGetError();
		if (err != GL_NO_ERROR && err != GL_INVALID_OPERATION) {
			printf("Expected GL_NO_ERROR or GL_INVALID_OPERATION "
			       "with %s but received: %s\n",
			       piglit_get_gl_enum_name(table_17_6_and_back[i]),
			       piglit_get_gl_error_name(err));
			subtest_pass = false;
		}
	}

	/* For that spec paragraph, we also test enums from table
	 * 17.5. They should return INVALID_OPERATION, as after all,
	 * they are not allocated to the default framebuffer. */
	one_buf = GL_COLOR_ATTACHMENT0;
	glNamedFramebufferDrawBuffers(default_framebuffer, 1, &one_buf);
	subtest_pass = subtest_pass &&
	  piglit_check_gl_error(GL_INVALID_OPERATION);

	PIGLIT_SUBTEST_CONDITION(subtest_pass, pass, "If the default framebuffer"
				 " is affected, then each of the constants must "
				 "be one of the values listed in table 17.6 or "
				 "the special value BACK. INVALID_OPERATION error"
				 " is generated if the default framebuffer is "
				 "affected and any value in bufs is a constant "
				 "(other than NONE or BACK ) that does not indicate "
				 "one of the color buffers allocated to the default"
				 " framebuffer.");

	/* (cont default framebuffer)
	 * From OpenGL 4.5 spec:
	 * "When BACK is used, n must be 1 and color values are
	 *  written into the left buffer for single-buffered
	 *  contexts, or into the back left buffer for
	 *  double-buffered contexts"
	 *
	 * From the error table:
	 * "An INVALID_OPERATION error is generated if any value in
	 *   bufs is BACK , and n is not one."
	 *
	 */
	glNamedFramebufferDrawBuffers(default_framebuffer, 2, bufs);
	PIGLIT_SUBTEST_ERROR(GL_INVALID_OPERATION, pass, "(default framebuffer)"
			     " An INVALID_OPERATION error is generated if any "
			     "value in bufs is BACK, and n is not one.");

	/*
	 * Now, specifically for a framebuffer object:
	 * "If a framebuffer object is affected, then each of the
	 *  constants must be one of the values listed in table 17.5."
	 *
	 * 17.5 is GL_NONE, and COLOR_ATTACHMENTi, where i <
	 * MAX_COLOR_ATTACHMENTS - 1
	 */
	int max_attachments;
	glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_attachments);

	subtest_pass = true;
	for (i = 0; i < max_attachments; i++) {
		 one_buf = GL_COLOR_ATTACHMENT0 + i;
		 glNamedFramebufferDrawBuffers(framebuffer, 1, &one_buf);
		 subtest_pass = subtest_pass &&
		   piglit_check_gl_error(GL_NO_ERROR);
	}
	PIGLIT_SUBTEST_CONDITION(subtest_pass, pass, "If a framebuffer object is "
			 "affected, then each of constants must be one of the "
			 "values listed in table 17.5.");

	/*
	 * "An INVALID_OPERATION error is generated if a framebuffer
	 *  object is affected and any value in bufs is a constant
	 *  from table 17.6, or COLOR_ATTACHMENTm where m is greater
	 *  than or equal to the value of MAX_COLOR_ATTACHMENTS."
	 */
	subtest_pass = true;
	/* Starting at 1, as GL_NONE is valid */
	for (i = 1; i < ARRAY_SIZE(table_17_6); i++) {
		GLenum err = 0;

		glNamedFramebufferDrawBuffers(framebuffer, 1, &table_17_6[i]);
		err = glGetError();
		if (err != GL_INVALID_OPERATION) {
			printf("Expected GL_INVALID_OPERATION with"
			       " %s but received: %s\n",
			       piglit_get_gl_enum_name(table_17_6[i]),
			       piglit_get_gl_error_name(err));
			subtest_pass = false;
		}
	}

	one_buf = GL_COLOR_ATTACHMENT0 + max_attachments;
	glNamedFramebufferDrawBuffers(framebuffer, 1, &one_buf);
	subtest_pass = subtest_pass &&
	  piglit_check_gl_error(GL_INVALID_OPERATION);
	PIGLIT_SUBTEST_CONDITION(subtest_pass, pass, "INVALID_OPERATION error is "
			 "generated if a framebuffer object is affected and any "
			 "value in bufs is a constant from table 17.6, or "
			 "COLOR_ATTACHMENTm where m is greater than or equal "
			 "to the value of MAX_COLOR_ATTACHMENTS.");

	/*
	 * "An INVALID_OPERATION error is generated if a buffer other
	 *  than NONE is specified more than once in the array pointed
	 *  to by bufs"
	 */
	bufs[0] = bufs[1] = GL_FRONT_LEFT;
	glNamedFramebufferDrawBuffers(framebuffer, 2, bufs);
	PIGLIT_SUBTEST_ERROR(GL_INVALID_OPERATION, pass, "INVALID_OPERATION error "
			     "is generated if a buffer other than NONE is specified "
			     "more than once in the array pointed to by bufs.");

	/*
	 * From OpenGL 4.5 spec:
	 * "An INVALID_ENUM error is generated if any value in bufs is
	 *  FRONT, LEFT, RIGHT, or FRONT_AND_BACK . This restriction
	 *  applies to both the default framebuffer and framebuffer
	 *  objects, and exists because these constants may themselves
	 *  refer to multiple buffers, as shown in table 17.4."
	 */
	subtest_pass = true;
	for (i = 0; i < ARRAY_SIZE(multiple_buffers); i++) {
		GLenum err = 0;
		bool local_pass = true;

		glNamedFramebufferDrawBuffers(default_framebuffer, 1,
					      &multiple_buffers[i]);
		err = glGetError();
		local_pass = local_pass && (err == GL_INVALID_ENUM);

		glNamedFramebufferDrawBuffers(framebuffer, 1,
					      &multiple_buffers[i]);
		err = glGetError();
		local_pass = local_pass && (err == GL_INVALID_ENUM);

		if (!local_pass)
			printf("Expected GL_INVALID_ENUM with"
			       " %s but received: %s\n",
			       piglit_get_gl_enum_name(table_17_6_and_back[i]),
			       piglit_get_gl_error_name(err));

		subtest_pass = subtest_pass && local_pass;

	}
	PIGLIT_SUBTEST_CONDITION(subtest_pass, pass, "INVALID_ENUM error is "
				 "generated if any value in bufs is FRONT, LEFT,"
				 " RIGHT, or FRONT_AND_BACK ");

	/* clean up */
	glDeleteFramebuffers(1, &framebuffer);

	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
}
void AbstractFramebuffer::drawBuffersImplementationDSA(const GLsizei count, const GLenum* const buffers) {
    glNamedFramebufferDrawBuffers(_id, count, buffers);
}
 void drawBuffer1() const{
     constexpr const static GLenum draws_[]{GL_COLOR_ATTACHMENT1 };
     glNamedFramebufferDrawBuffers(fbo_,1,draws_);
 }
Beispiel #8
0
void kit::PixelBuffer::setDrawBuffers(std::vector< uint32_t > drawBuffers)
{
  
  KIT_GL(glNamedFramebufferDrawBuffers(this->m_glHandle, (GLsizei)drawBuffers.size(), &drawBuffers[0]));
}
Beispiel #9
0
bool
OGLCoreFramebuffer::setup(const GraphicsFramebufferDesc& framebufferDesc) noexcept
{
	assert(GL_NONE == _fbo);
	assert(framebufferDesc.getGraphicsFramebufferLayout());
	assert(framebufferDesc.getGraphicsFramebufferLayout()->isInstanceOf<OGLFramebufferLayout>());
	assert(framebufferDesc.getWidth() > 0 && framebufferDesc.getHeight() > 0);

	glCreateFramebuffers(1, &_fbo);
	if (_fbo == GL_NONE)
	{
		this->getDevice()->downcast<OGLDevice>()->message("glCreateFramebuffers() fail");
		return false;
	}

	GLenum drawCount = 0;
	GLenum drawBuffers[GL_COLOR_ATTACHMENT15 - GL_COLOR_ATTACHMENT0];

	const auto& textureComponents = framebufferDesc.getGraphicsFramebufferLayout()->getGraphicsFramebufferLayoutDesc().getComponents();
	const auto& colorAttachments = framebufferDesc.getColorAttachments();
	if (colorAttachments.size() > (sizeof(drawBuffers) / sizeof(drawBuffers[0])))
	{
		this->getDevice()->downcast<OGLDevice>()->message("The color attachment in framebuffer is out of range.");
		return false;
	}

	for (std::size_t i = 0; i < textureComponents.size(); i++)
	{
		auto type = textureComponents[i].getAttachType();
		switch (type)
		{
		case GraphicsImageLayout::GraphicsImageLayoutGeneral:
			break;
		case GraphicsImageLayout::GraphicsImageLayoutColorAttachmentOptimal:
		{
			GLint slot = GL_COLOR_ATTACHMENT0 + textureComponents[i].getAttachSlot();
			GLint mipLevel = colorAttachments[drawCount].getBindingLevel();
			GLint layer = colorAttachments[drawCount].getBindingLayer();

			if (!this->bindRenderTexture(colorAttachments[drawCount].getBindingTexture(), slot, mipLevel, layer))
				return false;

			drawBuffers[drawCount++] = slot;
		}
		break;
		case GraphicsImageLayout::GraphicsImageLayoutDepthStencilAttachmentOptimal:
		case GraphicsImageLayout::GraphicsImageLayoutDepthStencilReadOnlyOptimal:
		{
			const auto& depthStencilAttachment = framebufferDesc.getDepthStencilAttachment();
			if (!depthStencilAttachment.getBindingTexture())
			{
				this->getDevice()->downcast<OGLDevice>()->message("Need depth or stencil texture.");
				return false;
			}

			auto texture = depthStencilAttachment.getBindingTexture();
			auto format = texture->getGraphicsTextureDesc().getTexFormat();
			auto level = depthStencilAttachment.getBindingLevel();
			auto layer = depthStencilAttachment.getBindingLayer();

			if (OGLTypes::isDepthStencilFormat(format))
			{
				if (!this->bindRenderTexture(texture, GL_DEPTH_STENCIL_ATTACHMENT, level, layer))
					return false;
			}
			else if (OGLTypes::isDepthFormat(format))
			{
				if (!this->bindRenderTexture(texture, GL_DEPTH_ATTACHMENT, level, layer))
					return false;
			}
			else if (OGLTypes::isStencilFormat(format))
			{
				if (!this->bindRenderTexture(texture, GL_STENCIL_ATTACHMENT, level, layer))
					return false;
			}
			else
			{
				this->getDevice()->downcast<OGLDevice>()->message("Invalid texture format");
				return false;
			}
		}
		case GraphicsImageLayout::GraphicsImageLayoutShaderReadOnlyOptimal:
			break;
		case GraphicsImageLayout::GraphicsImageLayoutTransferSrcOptimal:
			break;
		case GraphicsImageLayout::GraphicsImageLayoutTransferDstOptimal:
			break;
		case GraphicsImageLayout::GraphicsImageLayoutPreinitialized:
			break;
		case GraphicsImageLayout::GraphicsImageLayoutPresentSrcKhr:
			break;
		default:
			break;
		}
	}

	glNamedFramebufferDrawBuffers(_fbo, drawCount, drawBuffers);

	_framebufferDesc = framebufferDesc;
	return OGLCheck::checkError();
}
Beispiel #10
0
    void update() override {
        gl::GLTexture* gltexture = nullptr;
        TexturePointer surface;
        if (_gpuObject.getColorStamps() != _colorStamps) {
            if (_gpuObject.hasColor()) {
                _colorBuffers.clear();
                static const GLenum colorAttachments[] = {
                    GL_COLOR_ATTACHMENT0,
                    GL_COLOR_ATTACHMENT1,
                    GL_COLOR_ATTACHMENT2,
                    GL_COLOR_ATTACHMENT3,
                    GL_COLOR_ATTACHMENT4,
                    GL_COLOR_ATTACHMENT5,
                    GL_COLOR_ATTACHMENT6,
                    GL_COLOR_ATTACHMENT7,
                    GL_COLOR_ATTACHMENT8,
                    GL_COLOR_ATTACHMENT9,
                    GL_COLOR_ATTACHMENT10,
                    GL_COLOR_ATTACHMENT11,
                    GL_COLOR_ATTACHMENT12,
                    GL_COLOR_ATTACHMENT13,
                    GL_COLOR_ATTACHMENT14,
                    GL_COLOR_ATTACHMENT15 };

                int unit = 0;
                for (auto& b : _gpuObject.getRenderBuffers()) {
                    surface = b._texture;
                    if (surface) {
                        gltexture = gl::GLTexture::sync<GL45Backend::GL45Texture>(*_backend.lock().get(), surface, false); // Grab the gltexture and don't transfer
                    } else {
                        gltexture = nullptr;
                    }

                    if (gltexture) {
                        glNamedFramebufferTexture(_id, colorAttachments[unit], gltexture->_texture, 0);
                        _colorBuffers.push_back(colorAttachments[unit]);
                    } else {
                        glNamedFramebufferTexture(_id, colorAttachments[unit], 0, 0);
                    }
                    unit++;
                }
            }
            _colorStamps = _gpuObject.getColorStamps();
        }

        GLenum attachement = GL_DEPTH_STENCIL_ATTACHMENT;
        if (!_gpuObject.hasStencil()) {
            attachement = GL_DEPTH_ATTACHMENT;
        } else if (!_gpuObject.hasDepth()) {
            attachement = GL_STENCIL_ATTACHMENT;
        }

        if (_gpuObject.getDepthStamp() != _depthStamp) {
            auto surface = _gpuObject.getDepthStencilBuffer();
            if (_gpuObject.hasDepthStencil() && surface) {
                gltexture = gl::GLTexture::sync<GL45Backend::GL45Texture>(*_backend.lock().get(), surface, false); // Grab the gltexture and don't transfer
            }

            if (gltexture) {
                glNamedFramebufferTexture(_id, attachement, gltexture->_texture, 0);
            } else {
                glNamedFramebufferTexture(_id, attachement, 0, 0);
            }
            _depthStamp = _gpuObject.getDepthStamp();
        }


        // Last but not least, define where we draw
        if (!_colorBuffers.empty()) {
            glNamedFramebufferDrawBuffers(_id, (GLsizei)_colorBuffers.size(), _colorBuffers.data());
        } else {
            glNamedFramebufferDrawBuffer(_id, GL_NONE);
        }

        // Now check for completness
        _status = glCheckNamedFramebufferStatus(_id, GL_DRAW_FRAMEBUFFER);

        // restore the current framebuffer
        checkStatus(GL_DRAW_FRAMEBUFFER);
    }
Beispiel #11
0
		void Framebuffer::drawBuffers(const Attachment* attachments, u32 count) const
		{
			glNamedFramebufferDrawBuffers(m_id, count, (const u32*)attachments);
		}
    void update() override {
        gl::GLTexture* gltexture = nullptr;
        TexturePointer surface;
        if (_gpuObject.getColorStamps() != _colorStamps) {
            if (_gpuObject.hasColor()) {
                _colorBuffers.clear();
                static const GLenum colorAttachments[] = {
                    GL_COLOR_ATTACHMENT0,
                    GL_COLOR_ATTACHMENT1,
                    GL_COLOR_ATTACHMENT2,
                    GL_COLOR_ATTACHMENT3,
                    GL_COLOR_ATTACHMENT4,
                    GL_COLOR_ATTACHMENT5,
                    GL_COLOR_ATTACHMENT6,
                    GL_COLOR_ATTACHMENT7,
                    GL_COLOR_ATTACHMENT8,
                    GL_COLOR_ATTACHMENT9,
                    GL_COLOR_ATTACHMENT10,
                    GL_COLOR_ATTACHMENT11,
                    GL_COLOR_ATTACHMENT12,
                    GL_COLOR_ATTACHMENT13,
                    GL_COLOR_ATTACHMENT14,
                    GL_COLOR_ATTACHMENT15 };

                int unit = 0;
                auto backend = _backend.lock();
                for (auto& b : _gpuObject.getRenderBuffers()) {
                    surface = b._texture;
                    if (surface) {
                        Q_ASSERT(TextureUsageType::RENDERBUFFER == surface->getUsageType());
                        gltexture = backend->syncGPUObject(surface);
                    } else {
                        gltexture = nullptr;
                    }

                    if (gltexture) {
                        if (gltexture->_target == GL_TEXTURE_2D) {
                            glNamedFramebufferTexture(_id, colorAttachments[unit], gltexture->_texture, 0);
                        } else if (gltexture->_target == GL_TEXTURE_2D_MULTISAMPLE) {
                            glNamedFramebufferTexture(_id, colorAttachments[unit], gltexture->_texture, 0);
                        } else {
                            glNamedFramebufferTextureLayer(_id, colorAttachments[unit], gltexture->_texture, 0, b._subresource);
                        }
                        _colorBuffers.push_back(colorAttachments[unit]);
                    } else {
                        glNamedFramebufferTexture(_id, colorAttachments[unit], 0, 0);
                    }
                    unit++;
                }
            }
            _colorStamps = _gpuObject.getColorStamps();
        }

        GLenum attachement = GL_DEPTH_STENCIL_ATTACHMENT;
        if (!_gpuObject.hasStencil()) {
            attachement = GL_DEPTH_ATTACHMENT;
        } else if (!_gpuObject.hasDepth()) {
            attachement = GL_STENCIL_ATTACHMENT;
        }

        if (_gpuObject.getDepthStamp() != _depthStamp) {
            auto surface = _gpuObject.getDepthStencilBuffer();
            auto backend = _backend.lock();
            if (_gpuObject.hasDepthStencil() && surface) {
                Q_ASSERT(TextureUsageType::RENDERBUFFER == surface->getUsageType());
                gltexture = backend->syncGPUObject(surface);
            }

            if (gltexture) {
                if (gltexture->_target == GL_TEXTURE_2D) {
                    glNamedFramebufferTexture(_id, attachement, gltexture->_texture, 0);
                }
                else if (gltexture->_target == GL_TEXTURE_2D_MULTISAMPLE) {
                    glNamedFramebufferTexture(_id, attachement, gltexture->_texture, 0);
                } else {
                    glNamedFramebufferTextureLayer(_id, attachement, gltexture->_texture, 0,
                                                   _gpuObject.getDepthStencilBufferSubresource());
                }
            } else {
                glNamedFramebufferTexture(_id, attachement, 0, 0);
            }
            _depthStamp = _gpuObject.getDepthStamp();
        }

        // Last but not least, define where we draw
        if (!_colorBuffers.empty()) {
            glNamedFramebufferDrawBuffers(_id, (GLsizei)_colorBuffers.size(), _colorBuffers.data());
        } else {
            glNamedFramebufferDrawBuffer(_id, GL_NONE);
        }

        // Now check for completness
        _status = glCheckNamedFramebufferStatus(_id, GL_DRAW_FRAMEBUFFER);

        // restore the current framebuffer
        checkStatus();
    }