void GLFramebufferObject::setDrawBuffers( Array1DReadView< GLenum > attachments ) { assert( attachments.packed() ); glNamedFramebufferDrawBuffers( m_id, static_cast< GLsizei >( attachments.size() ), attachments.pointer() ); }
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()); }
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(); }
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_); }
void kit::PixelBuffer::setDrawBuffers(std::vector< uint32_t > drawBuffers) { KIT_GL(glNamedFramebufferDrawBuffers(this->m_glHandle, (GLsizei)drawBuffers.size(), &drawBuffers[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(); }
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); }
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(); }