// -------------------------------------------------------------------------------------------------------------------- bool UntexturedObjectsGLDrawLoop::Init(const std::vector<UntexturedObjectsProblem::Vertex>& _vertices, const std::vector<UntexturedObjectsProblem::Index>& _indices, size_t _objectCount) { if (!UntexturedObjectsSolution::Init(_vertices, _indices, _objectCount)) { return false; } // Program const char* kUniformNames[] = { "ViewProjection", nullptr }; m_prog = CreateProgramT("cubes_gl_multi_draw_vs.glsl", "cubes_gl_multi_draw_fs.glsl", kUniformNames, &mUniformLocation); if (m_prog == 0) { console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str()); return false; } glGenVertexArrays(1, &m_varray); glBindVertexArray(m_varray); // Buffers glGenBuffers(1, &m_vb); glBindBuffer(GL_ARRAY_BUFFER, m_vb); glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(UntexturedObjectsProblem::Vertex), &*_vertices.begin(), GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(UntexturedObjectsProblem::Vertex), (void*) offsetof(UntexturedObjectsProblem::Vertex, pos)); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(UntexturedObjectsProblem::Vertex), (void*) offsetof(UntexturedObjectsProblem::Vertex, color)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); std::vector<uint32_t> drawids(_objectCount); for (uint32_t i = 0; i < _objectCount; ++i) { drawids[i] = i; } glGenBuffers(1, &m_drawid); glBindBuffer(GL_ARRAY_BUFFER, m_drawid); glBufferData(GL_ARRAY_BUFFER, drawids.size() * sizeof(uint32_t), drawids.data(), GL_STATIC_DRAW); glVertexAttribIPointer(2, 1, GL_UNSIGNED_INT, sizeof(uint32_t), 0); glVertexAttribDivisor(2, 1); glEnableVertexAttribArray(2); glGenBuffers(1, &m_ib); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ib); glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(UntexturedObjectsProblem::Index), &*_indices.begin(), GL_STATIC_DRAW); glGenBuffers(1, &m_transform_buffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_transform_buffer); return glGetError() == GL_NO_ERROR; }
// -------------------------------------------------------------------------------------------------------------------- bool UntexturedObjectsGLBufferStorage::Init(const std::vector<UntexturedObjectsProblem::Vertex>& _vertices, const std::vector<UntexturedObjectsProblem::Index>& _indices, size_t _objectCount) { if (glBufferStorage == nullptr) { console::warn("Unable to initialize solution '%s', glBufferStorage() unavailable.", GetName().c_str()); return false; } if (!UntexturedObjectsSolution::Init(_vertices, _indices, _objectCount)) { return false; } if (mUseShaderDrawParameters && !HasExtension("GL_ARB_shader_draw_parameters")) { console::warn("Unable to initialize solution, ARB_shader_draw_parameters is required but not available."); return false; } // Program const char* kUniformNames[] = { "ViewProjection", nullptr }; m_prog = CreateProgramT("cubes_gl_buffer_storage_vs.glsl", "cubes_gl_buffer_storage_fs.glsl", mUseShaderDrawParameters ? std::string("#define USE_SHADER_DRAW_PARAMETERS 1\n") : std::string(""), kUniformNames, &mUniformLocation); if (m_prog == 0) { console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str()); return false; } glGenVertexArrays(1, &m_varray); glBindVertexArray(m_varray); // Buffers glGenBuffers(1, &m_vb); glBindBuffer(GL_ARRAY_BUFFER, m_vb); glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(UntexturedObjectsProblem::Vertex), &*_vertices.begin(), GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(UntexturedObjectsProblem::Vertex), (void*) offsetof(UntexturedObjectsProblem::Vertex, pos)); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(UntexturedObjectsProblem::Vertex), (void*) offsetof(UntexturedObjectsProblem::Vertex, color)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); // If we aren't using shader draw parameters, use the workaround instead. if (!mUseShaderDrawParameters) { std::vector<uint32_t> drawids(_objectCount); for (uint32_t i = 0; i < _objectCount; ++i) { drawids[i] = i; } glGenBuffers(1, &m_drawid); glBindBuffer(GL_ARRAY_BUFFER, m_drawid); glBufferData(GL_ARRAY_BUFFER, drawids.size() * sizeof(uint32_t), drawids.data(), GL_STATIC_DRAW); glVertexAttribIPointer(2, 1, GL_UNSIGNED_INT, sizeof(uint32_t), 0); glVertexAttribDivisor(2, 1); glEnableVertexAttribArray(2); } glGenBuffers(1, &m_ib); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ib); glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(UntexturedObjectsProblem::Index), &*_indices.begin(), GL_STATIC_DRAW); glGenBuffers(1, &m_transform_buffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_transform_buffer); glBufferStorage(GL_SHADER_STORAGE_BUFFER, _objectCount * 64, nullptr, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT); m_transform_ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, _objectCount * 64, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); glGenBuffers(1, &m_cmd_buffer); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_cmd_buffer); glBufferStorage(GL_DRAW_INDIRECT_BUFFER, _objectCount * sizeof(DrawElementsIndirectCommand), nullptr, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT); m_cmd_ptr = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, _objectCount * sizeof(DrawElementsIndirectCommand), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); // Set the command buffer size. m_commands.resize(_objectCount); return glGetError() == GL_NO_ERROR; }
// -------------------------------------------------------------------------------------------------------------------- bool TexturedQuadsGLSparseBindlessTextureArrayMultiDraw::Init(const std::vector<TexturedQuadsProblem::Vertex>& _vertices, const std::vector<TexturedQuadsProblem::Index>& _indices, const std::vector<TextureDetails*>& _textures, size_t _objectCount) { if (!TexturedQuadsSolution::Init(_vertices, _indices, _textures, _objectCount)) { return false; } // Prerequisites if (!mTexManager.Init()) { return false; } if (glGetTextureHandleARB == nullptr) { console::warn("Unable to initialize solution '%s', requires support for bindless textures (not present).", GetName().c_str()); return false; } if (mUseShaderDrawParameters && !HasExtension(ARB_shader_draw_parameters)) { console::warn("Unable to initialize solution, ARB_shader_draw_parameters is required but not available."); return false; } // Program mProgram = CreateProgram("textures_gl_sparse_bindless_texture_array_multidraw_vs.glsl", "textures_gl_sparse_bindless_texture_array_multidraw_fs.glsl", mUseShaderDrawParameters ? std::string("#define USE_SHADER_DRAW_PARAMETERS 1\n") : std::string("") ); if (mProgram == 0) { console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str()); return false; } // Textures for (auto it = _textures.begin(); it != _textures.end(); ++it) { mTextures.push_back(mTexManager.newTexture2DFromDetails(*it)); } // Buffers mVertexBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, _vertices, GL_STATIC_DRAW); mIndexBuffer = NewBufferFromVector(GL_ELEMENT_ARRAY_BUFFER, _indices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TexturedQuadsProblem::Vertex), (void*)offsetof(TexturedQuadsProblem::Vertex, pos)); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedQuadsProblem::Vertex), (void*)offsetof(TexturedQuadsProblem::Vertex, tex)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); // If we aren't using shader draw parameters, use the workaround instead. if (!mUseShaderDrawParameters) { std::vector<uint32_t> drawids(_objectCount); for (uint32_t i = 0; i < _objectCount; ++i) { drawids[i] = i; } mDrawIDBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, drawids, GL_STATIC_DRAW); glVertexAttribIPointer(2, 1, GL_UNSIGNED_INT, sizeof(uint32_t), 0); glVertexAttribDivisor(2, 1); glEnableVertexAttribArray(2); } glGenBuffers(1, &mTransformBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mTransformBuffer); auto srcIt = mTextures.cbegin(); std::vector<TexAddress> texAddressContents(_objectCount); for (auto dstIt = texAddressContents.begin(); dstIt != texAddressContents.end(); ++dstIt) { if (srcIt == mTextures.cend()) { srcIt = mTextures.cbegin(); } (*dstIt) = (*srcIt)->GetAddress(); ++srcIt; } mTexAddressBuffer = NewBufferFromVector(GL_SHADER_STORAGE_BUFFER, texAddressContents, GL_DYNAMIC_DRAW); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mTexAddressBuffer); mCommands.resize(_objectCount); return glGetError() == GL_NO_ERROR; }
// -------------------------------------------------------------------------------------------------------------------- bool TexturedQuadsGLTextureArray::Init(const std::vector<TexturedQuadsProblem::Vertex>& _vertices, const std::vector<TexturedQuadsProblem::Index>& _indices, const std::vector<TextureDetails*>& _textures, size_t _objectCount) { if (!TexturedQuadsSolution::Init(_vertices, _indices, _textures, _objectCount)) { return false; } // Prerequisites auto numTextures = _textures.size(); if (!mTexManager.Init(false, numTextures)) { return false; } // Program const char* kUniformNames[] = { "ViewProjection", "TexContainer", nullptr }; mProgram = CreateProgramT("textures_gl_texture_array_vs.glsl", "textures_gl_texture_array_fs.glsl", kUniformNames, &mUniformLocation); if (mProgram == 0) { console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str()); return false; } // Textures for (auto it = _textures.begin(); it != _textures.end(); ++it) { mTextures.push_back(mTexManager.newTexture2DFromDetails(*it)); } GLint lastTexId = -1; GLint lastTexUnit = -1; std::vector<DenseTexAddress> texAddress(numTextures); for (size_t i = 0; i < numTextures; ++i) { auto texture = mTextures[i]; auto texId = texture->GetTexId(); if (lastTexId != texId) { lastTexId = texId; lastTexUnit = (GLint) mTexUnits.size(); glActiveTexture(GL_TEXTURE0 + lastTexUnit); glBindTexture(GL_TEXTURE_2D_ARRAY, texId); mTexUnits.push_back(lastTexUnit); } texAddress[i].m_container_index = lastTexUnit; texAddress[i].m_layer = ((float) texture->getSliceNum() + 0.5f) / numTextures; } std::vector<DenseTexAddress> texAddressContents(_objectCount); for (uint32_t i = 0; i < _objectCount; ++i) { texAddressContents[i] = texAddress[i % numTextures]; } mTexAddressBuffer = NewBufferFromVector(GL_SHADER_STORAGE_BUFFER, texAddressContents, GL_DYNAMIC_DRAW); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mTexAddressBuffer); // Buffers glGenVertexArrays(1, &mVertexArray); glBindVertexArray(mVertexArray); mVertexBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, _vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TexturedQuadsProblem::Vertex), (void*)offsetof(TexturedQuadsProblem::Vertex, pos)); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedQuadsProblem::Vertex), (void*)offsetof(TexturedQuadsProblem::Vertex, tex)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); std::vector<uint32_t> drawids(_objectCount); for (uint32_t i = 0; i < _objectCount; ++i) { drawids[i] = i; } mDrawIDBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, drawids, GL_STATIC_DRAW); glVertexAttribIPointer(2, 1, GL_UNSIGNED_INT, sizeof(uint32_t), 0); glVertexAttribDivisor(2, 1); glEnableVertexAttribArray(2); mIndexBuffer = NewBufferFromVector(GL_ELEMENT_ARRAY_BUFFER, _indices, GL_STATIC_DRAW); glGenBuffers(1, &mTransformBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mTransformBuffer); return GLRenderer::GetApiError() == GL_NO_ERROR; }