void drawIndirectFirstPass(Uniforms...uniforms) const { T::InstancedFirstPassShader::getInstance()->use(); T::InstancedFirstPassShader::getInstance()->setUniforms(uniforms...); glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, T::Instance)); for (unsigned i = 0; i < m_meshes[T::MaterialType].size(); i++) { GLMesh *mesh = m_meshes[T::MaterialType][i]; #ifdef DEBUG if (mesh->VAOType != T::VertexType) { Log::error("CommandBuffer", "Wrong instanced vertex format (hint : %s)", mesh->textures[0]->getName().getPath().c_str()); continue; } #endif TexExpander<typename T::InstancedFirstPassShader>::template expandTex(*mesh, T::FirstPassTextures); if (!mesh->mb->getMaterial().BackfaceCulling) glDisable(GL_CULL_FACE); glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((m_offset[T::MaterialType] + i) * sizeof(DrawElementsIndirectCommand))); if (!mesh->mb->getMaterial().BackfaceCulling) glEnable(GL_CULL_FACE); } } //drawIndirectFirstPass
static bool check_draw_no_buffer_bound(void) { /* In the core profile, an INVALID_OPERATION error is generated * if zero is bound to DRAW_INDIRECT_BUFFER and DrawArraysIndirect * or DrawElementsIndirect is called. */ /* Bind a buffer of indices; ensure we're hitting the correct * error path with DrawElementsIndirect. */ GLuint ib; glGenBuffers(1, &ib); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib); glBufferData(GL_ELEMENT_ARRAY_BUFFER, 32, NULL, GL_DYNAMIC_DRAW); /* no indirect buffer */ glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); glDrawArraysIndirect(GL_TRIANGLES, (GLvoid const *)0); if (!piglit_check_gl_error(GL_INVALID_OPERATION)) return false; glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (GLvoid const *)0); if (!piglit_check_gl_error(GL_INVALID_OPERATION)) return false; return true; }
static bool check_draw_beyond_end(void) { /* An INVALID_OPERATION error is generated if the commands source * data beyond the end of the buffer object .. */ GLuint buf; glGenBuffers(1, &buf); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buf); glBufferData(GL_DRAW_INDIRECT_BUFFER, 5 * sizeof(GLuint), NULL, GL_DYNAMIC_DRAW); /* command is 4 * sizeof(GLuint); would read one GLuint beyond the end of the BO. */ glDrawArraysIndirect(GL_TRIANGLES, (GLvoid const *)(2 * sizeof(GLuint))); if (!piglit_check_gl_error(GL_INVALID_OPERATION)) return false; /* DrawElementsIndirect requires index buffer; bind the indirect buffer there too * since it's handy; just to make sure we hit the right case. */ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); /* command is 5 * sizeof(GLuint); would read one GLuint beyond the end. */ glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (GLvoid const *)(1 * sizeof(GLuint))); if (!piglit_check_gl_error(GL_INVALID_OPERATION)) return false; return true; }
/** Draw glowing meshes. * Require OpenGL 4.0 (or higher) * or GL_ARB_base_instance and GL_ARB_draw_indirect extensions) */ void drawIndirect() const { InstancedColorizeShader::getInstance()->use(); glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(irr::video::EVT_STANDARD, InstanceTypeGlow)); for (unsigned i = 0; i < m_meshes[0].size(); i++) { glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((m_offset[0] + i) * sizeof(DrawElementsIndirectCommand))); } } //drawIndirect
void drawIndirectNormals() const { NormalVisualizer::getInstance()->use(); NormalVisualizer::getInstance()->setUniforms(video::SColor(255, 0, 255, 0)); glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, T::Instance)); for (unsigned i = 0; i < m_meshes[T::MaterialType].size(); i++) { glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((m_offset[T::MaterialType] + i) * sizeof(DrawElementsIndirectCommand))); } } // drawIndirectNormals
void drawIndirect(Uniforms ...uniforms) const { T::InstancedRSMShader::getInstance()->use(); T::InstancedRSMShader::getInstance()->setUniforms(uniforms...); glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, InstanceTypeRSM)); for (unsigned i = 0; i < m_meshes[T::MaterialType].size(); i++) { GLMesh *mesh = m_meshes[T::MaterialType][i]; TexExpander<typename T::InstancedRSMShader>::template expandTex(*mesh, T::RSMTextures); glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((m_offset[T::MaterialType] + i) * sizeof(DrawElementsIndirectCommand))); } } //drawIndirect
void drawIndirectSecondPass(const std::vector<GLuint> &prefilled_tex, Uniforms...uniforms ) const { T::InstancedSecondPassShader::getInstance()->use(); T::InstancedSecondPassShader::getInstance()->setUniforms(uniforms...); glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, T::Instance)); for (unsigned i = 0; i < m_meshes[T::MaterialType].size(); i++) { GLMesh *mesh = m_meshes[T::MaterialType][i]; expandTexSecondPass<T>(*mesh, prefilled_tex); if (!mesh->mb->getMaterial().BackfaceCulling) glDisable(GL_CULL_FACE); glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((m_offset[T::MaterialType] + i) * sizeof(DrawElementsIndirectCommand))); if (!mesh->mb->getMaterial().BackfaceCulling) glEnable(GL_CULL_FACE); } } //drawIndirectSecondPass
static bool check_draw_elements_no_indices(void) { /* If no element array buffer is bound, an INVALID_OPERATION * error is generated. */ GLuint buf; glGenBuffers(1, &buf); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buf); glBufferData(GL_DRAW_INDIRECT_BUFFER, 5 * sizeof(GLuint), NULL, GL_DYNAMIC_DRAW); /* unbind indices */ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (GLvoid const *)0); if (!piglit_check_gl_error(GL_INVALID_OPERATION)) return false; return true; }
void drawIndirect(unsigned cascade, Uniforms ...uniforms) const { T::InstancedShadowPassShader::getInstance()->use(); T::InstancedShadowPassShader::getInstance()->setUniforms(cascade, uniforms...); glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, InstanceTypeShadow)); int material_id = T::MaterialType + cascade * Material::SHADERTYPE_COUNT; for (unsigned i = 0; i < m_meshes[material_id].size(); i++) { GLMesh *mesh = m_meshes[material_id][i]; TexExpander<typename T::InstancedShadowPassShader>::template expandTex(*mesh, T::ShadowTextures); glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((m_offset[material_id] + i) * sizeof(DrawElementsIndirectCommand))); } // for i } // drawIndirect
enum piglit_result piglit_display(void) { bool pass = true; glViewport(0, 0, 128, 128); glClearColor(0,0,1,1); glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(vao); glUseProgram(prog); glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (GLvoid const *)0); glUseProgram(0); piglit_present_results(); pass = piglit_probe_pixel_rgb(32, 32, green) && pass; pass = piglit_probe_pixel_rgb(96, 96, blue) && pass; return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
void IrrDriver::renderGlow(std::vector<GlowData>& glows) { m_scene_manager->setCurrentRendertime(scene::ESNRP_SOLID); m_rtts->getFBO(FBO_TMP1_WITH_DS).Bind(); glClearStencil(0); glClearColor(0, 0, 0, 0); glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); const u32 glowcount = (int)glows.size(); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc(GL_ALWAYS, 1, ~0); glEnable(GL_STENCIL_TEST); glEnable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glDisable(GL_BLEND); if (CVS->isARBBaseInstanceUsable()) glBindVertexArray(VAOManager::getInstance()->getVAO(EVT_STANDARD)); for (u32 i = 0; i < glowcount; i++) { const GlowData &dat = glows[i]; scene::ISceneNode * cur = dat.node; STKMeshSceneNode *node = static_cast<STKMeshSceneNode *>(cur); node->setGlowColors(SColor(0, (unsigned) (dat.b * 255.f), (unsigned)(dat.g * 255.f), (unsigned)(dat.r * 255.f))); if (!CVS->supportsIndirectInstancingRendering()) node->render(); } if (CVS->supportsIndirectInstancingRendering()) { glBindBuffer(GL_DRAW_INDIRECT_BUFFER, GlowPassCmd::getInstance()->drawindirectcmd); glUseProgram(MeshShader::InstancedColorizeShader::getInstance()->Program); glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeGlow)); if (CVS->isAZDOEnabled()) { if (GlowPassCmd::getInstance()->Size) { glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)(GlowPassCmd::getInstance()->Offset * sizeof(DrawElementsIndirectCommand)), (int)GlowPassCmd::getInstance()->Size, sizeof(DrawElementsIndirectCommand)); } } else { for (unsigned i = 0; i < ListInstancedGlow::getInstance()->size(); i++) glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((GlowPassCmd::getInstance()->Offset + i) * sizeof(DrawElementsIndirectCommand))); } } glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); // To half FrameBuffer::Blit(irr_driver->getFBO(FBO_TMP1_WITH_DS), irr_driver->getFBO(FBO_HALF1), GL_COLOR_BUFFER_BIT, GL_LINEAR); // To quarter FrameBuffer::Blit(irr_driver->getFBO(FBO_HALF1), irr_driver->getFBO(FBO_QUARTER1), GL_COLOR_BUFFER_BIT, GL_LINEAR); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glStencilFunc(GL_EQUAL, 0, ~0); glEnable(GL_STENCIL_TEST); m_rtts->getFBO(FBO_COLORS).Bind(); m_post_processing->renderGlow(m_rtts->getRenderTarget(RTT_QUARTER1)); glDisable(GL_STENCIL_TEST); }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL40_nglDrawElementsIndirect(JNIEnv *__env, jclass clazz, jint mode, jint type, jlong indirectAddress, jlong __functionAddress) { const GLvoid *indirect = (const GLvoid *)(intptr_t)indirectAddress; glDrawElementsIndirectPROC glDrawElementsIndirect = (glDrawElementsIndirectPROC)(intptr_t)__functionAddress; UNUSED_PARAMS(__env, clazz) glDrawElementsIndirect(mode, type, indirect); }
void OpenGLUnitsDrawer::draw_units(const std::vector<Unit> &units) { // ToDo: Don't need to update data if no changes. Don't need to re-_indirect_buffer data if no // changes. bool re_buffer{false}; static bool init{false}; if (units.size() != indirect_draw_.size()) { indirect_draw_.resize(units.size()); transformations_.resize(units.size()); } if (std::any_of(std::begin(units), std::end(units), [](const Unit &u) { return u.draw_strategy()->is_modified(); })) { unit_vertices_.clear(); unit_indices_.clear(); RenderInfo render_info; for (size_t i = 0; i < units.size(); ++i) { render_info = units.at(i).draw_strategy()->fill_draw_structures(); indirect_draw_[i].count = static_cast<GLuint>(render_info.indecies.size()); indirect_draw_[i].primCount = 1; indirect_draw_[i].firstIndex = static_cast<GLuint>(unit_indices_.size()); indirect_draw_[i].baseVertex = static_cast<GLuint>(unit_vertices_.size()) / kPointsPerPixel; indirect_draw_[i].baseInstance = 0; unit_vertices_.insert(std::end(unit_vertices_), std::begin(render_info.vertices), std::end(render_info.vertices)); unit_indices_.insert(std::end(unit_indices_), std::begin(render_info.indecies), std::end(render_info.indecies)); transformations_[i] = render_info.transformation; } re_buffer = true; } shader_.use(); // Pass them to the shaders glUniformMatrix4fv(shader_.get_location(Location::projection), 1, GL_FALSE, glm::value_ptr(projection_)); glUniformMatrix4fv(shader_.get_location(Location::view), 1, GL_FALSE, glm::value_ptr(view_)); glUniformMatrix4fv(shader_.get_location(Location::model), 1, GL_FALSE, glm::value_ptr(model_)); if (re_buffer) { glBindVertexArray(gl_field_vao_); { glBindBuffer(GL_ARRAY_BUFFER, gl_field_vbo_); glBufferData(GL_ARRAY_BUFFER, unit_vertices_.size() * sizeof(GLfloat), unit_vertices_.data(), GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_field_ebo_); glBufferData(GL_ELEMENT_ARRAY_BUFFER, unit_indices_.size() * sizeof(GLuint), unit_indices_.data(), GL_STATIC_DRAW); if (!init) { glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirect_buffer_); glBufferData(GL_DRAW_INDIRECT_BUFFER, indirect_draw_.size() * sizeof(DrawElementsIndirectCommand), indirect_draw_.data(), GL_STATIC_DRAW); init = true; } } glBindVertexArray(0); } glBindVertexArray(gl_field_vao_); { for (size_t i = 0; i < units.size(); ++i) { glUniformMatrix4fv(shader_.get_location(Location::rotation), 1, GL_FALSE, glm::value_ptr(transformations_[i])); glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, (void *)(i * sizeof(DrawElementsIndirectCommand))); GLenum err = glGetError(); if (err != GL_NO_ERROR) { Logger::warning("OpenGL: glDrawElementsIndirect error: %d", err); } } } }
inline void draw_elements_indirect(Primitive primitive, IndexType index_type, uint32 byte_offset) { ARC_GL_CLEAR_ERRORS(); glDrawElementsIndirect((GLenum)primitive, (GLenum)index_type, (void*)byte_offset); ARC_GL_CHECK_FOR_ERRORS(); }