void VertexAttributeCache<VertexCacheVBO>::updateGeometryInstanceCacheEntry( GeometryInstanceGLHandle gi, GeometryInstanceCacheEntry& geometryInstanceCacheEntry, AttributeCacheEntry* attributeCacheEntry ) { VertexAttributesGLSharedHandle const& vertexAttributes = gi->getGeometry()->getVertexAttributes(); VertexDataGLHandle vertexData = vertexAttributes->getVertexDataGLHandle(); geometryInstanceCacheEntry.m_formatId = registerVertexFormat( vertexAttributes.get(), gi->m_programPipeline->m_activeAttributeMask ); const VertexFormat &vertexFormat = m_vertexFormats[geometryInstanceCacheEntry.m_formatId]; for ( unsigned int index = 0; index < vertexFormat.m_numStreams; ++index ) { unsigned int streamId = vertexFormat.m_streamIds[index]; AttributeCacheEntry& cacheEntry = attributeCacheEntry[index]; BufferGL *buffer = vertexData->m_data[streamId].m_buffer; if ( buffer ) { DP_ASSERT( buffer->getBuffer() ); cacheEntry.vbo = buffer->getBuffer()->getGLId(); cacheEntry.offset = reinterpret_cast<GLvoid *>(vertexData->m_data[streamId].m_offset); } else { cacheEntry.vbo = 0; cacheEntry.offset = 0; } } // update indices data IndicesGLSharedHandle const& indices = gi->getGeometry()->getIndices(); if ( indices && indices->getBufferHandle() ) { DP_ASSERT( indices->getBufferHandle()->getBuffer() ); geometryInstanceCacheEntry.m_attributeCacheIndices.vbo = indices->getBufferHandle()->getBuffer()->getGLId(); geometryInstanceCacheEntry.m_attributeCacheIndices.offset = 0; } else { geometryInstanceCacheEntry.m_attributeCacheIndices.vbo = 0; geometryInstanceCacheEntry.m_attributeCacheIndices.offset = 0; } geometryInstanceCacheEntry.m_drawCall.updateDrawCall( gi ); geometryInstanceCacheEntry.m_attributeCacheEntry = attributeCacheEntry; geometryInstanceCacheEntry.m_vertexAttributesHandle = vertexAttributes.get(); geometryInstanceCacheEntry.m_indicesHandle = indices.get(); }
void addArrayIndirectCommand( GeometryInstanceGLHandle gi, RenderEngineGLIndirect::RenderGroupGLCache::DrawArrayListEntry &drawListEntry ) { drawListEntry.m_indirectEntries.push_back( generateIndirectEntry(gi) ); VertexAttributesGLSharedHandle const& vertexAttributes = gi->getGeometry()->getVertexAttributes().get(); VertexDataGLHandle data = vertexAttributes->getVertexDataGLHandle(); RenderEngineGLIndirect::RenderGroupGLCache::DrawArraysIndirectCommand command; command.count = static_cast<GLuint>(data->m_numberOfVertices); command.primCount = 1; command.first = 0; command.baseInstance = static_cast<GLuint>(drawListEntry.m_indirectCommands.size()); drawListEntry.m_indirectCommands.push_back( command ); }
void RenderEngineGLImpl<VertexCache>::render( GeometryInstanceGLHandle gi ) { if ( gi->isVisible() ) { assert( gi->m_pipelineGroupCache ); RenderGroupCache* pipelineCache = static_cast<RenderGroupCache*>(gi->m_pipelineGroupCache); changeProgramPipelineCache( pipelineCache ); //m_currentProgramPipelineCache->renderParameters( m_currentProgramPipelineCache->getContainerCacheEntries() + gi->m_pipelineGroupCacheIndex * m_numVariableParameterStates); m_currentProgramPipelineCache->renderParameters( gi->m_pipelineGroupCacheIndex ); GeometryInstanceCache* giCache = static_cast<GeometryInstanceCache*>(pipelineCache->m_geometryInstanceCache.get()); GeometryInstanceCacheEntry* giCacheEntry = giCache->m_geometryInstanceCacheEntries; renderGeometryInstance(*(giCacheEntry + gi->m_pipelineGroupCacheIndex)); } }
RenderEngineGLIndirect::RenderGroupGLCache::IndirectEntry generateIndirectEntry( GeometryInstanceGLHandle gi ) { RenderEngineGLIndirect::RenderGroupGLCache::IndirectEntry entry; VertexAttributesGLSharedHandle const& vertexAttributes = gi->getGeometry()->getVertexAttributes().get(); VertexDataGLHandle data = vertexAttributes->getVertexDataGLHandle(); DP_ASSERT( data->m_data[0].m_buffer->getBuffer() ); entry.position = data->m_data[0].m_buffer->getBuffer()->getAddress(); if ( data->m_data[2].m_buffer ) { DP_ASSERT( data->m_data[2].m_buffer->getBuffer() ); entry.normal = data->m_data[2].m_buffer->getBuffer()->getAddress(); } else { // HACK, some geometry does not have normals entry.normal = entry.position; } entry.transform = *((GLuint64EXT*)gi->m_containers[2].container->m_data); entry.material = *((GLuint64EXT*)gi->m_containers[3].container->m_data); return entry; }
void RenderEngineGLIndirect::render( RenderGroupGLHandle groupHandle, const dp::rix::core::RenderOptions& /*renderOptions*/ ) { // if dirty, update sorted list RenderGroupGL::ProgramPipelineCaches::iterator glIt; RenderGroupGL::ProgramPipelineCaches::iterator glIt_end = groupHandle->m_programPipelineCaches.end(); for ( glIt = groupHandle->m_programPipelineCaches.begin(); glIt != glIt_end; ++glIt ) { ProgramPipelineGLHandle programPipeline = glIt->first; RenderGroupGLCache* cache = glIt->second.get<RenderGroupGLCache>(); #if RIX_GL_SEPARATE_SHADER_OBJECTS_SUPPORT == 1 glBindProgramPipeline( programPipeline->m_pipelineId ); #else glUseProgram( programPipeline->m_programs[0]->getProgram()->getGLId() ); #endif //if ( giList->m_indirectEntries.size() != giList->m_geometryInstances.size()) if ( !cache->m_initialized ) // TODO support changes { cache->m_initialized = true; RenderGroupGLCache::DrawArrayListEntry triangles; RenderGroupGLCache::DrawArrayListEntry lines; RenderGroupGLCache::DrawArrayListEntry linesStrips; //cache->m_indirectEntries.clear(); //cache->m_indirectCommands.clear(); for (size_t index = 0; index < cache->getGeometryInstances().size(); ++index ) { GeometryInstanceGLHandle gi = cache->getGeometryInstances()[index]; if ( !gi->getGeometry()->getIndices() ) { switch ( gi->getGeometry()->getGeometryDescription()->getPrimitiveType() ) { case GeometryPrimitiveType::TRIANGLES: //drawEntry = &triangles; addArrayIndirectCommand(gi, triangles); break; case GeometryPrimitiveType::LINES: addArrayIndirectCommand(gi, lines); break; case GeometryPrimitiveType::LINE_STRIP: addArrayIndirectCommand(gi, linesStrips); break; default: assert( 0 && "unsupported primitve types"); } } else { //addElementIndirectCommand(cache, gi ); } } addDrawArrayList( cache, triangles, GL_TRIANGLES); addDrawArrayList( cache, lines, GL_LINES ); addDrawArrayList( cache, linesStrips, GL_LINE_STRIP ); for ( size_t idx = 0;idx < cache->m_drawElementsList.size(); ++idx ) { prepareDrawElementsEntry( &cache->m_drawElementsList[idx] ); } } // prepare fixed containers #if 0 GeometryInstanceGLHandle gi = cache->getGeometryInstances()[0]; for ( size_t containerIdx = 0; containerIdx < gi->m_containers.size(); ++containerIdx ) { // debug info auto infos = gi->m_containers[containerIdx].container->m_descriptor->m_parameterInfos; for ( size_t infoIdx = 0; infoIdx < infos.size(); ++infoIdx ) { std::cout << "c: " << containerIdx << ", infoIdX:" << infoIdx << ", name: " << infos[infoIdx].m_name << std::endl; } } #endif assert( !"No implementation available atm"); // TODO update to new interface //gi->m_containers[0].parameters[0]->update( gi->m_containers[0].container->m_data ); // sys_View //gi->m_containers[1].parameters[0]->update( gi->m_containers[1].container->m_data ); // lights for ( size_t idx = 0;idx < cache->m_drawArrayList.size(); ++idx ) { RenderGroupGLCache::DrawArrayListEntry &entry = cache->m_drawArrayList[idx]; glEnableVertexAttribArray( 12 ); dp::gl::bind( GL_ARRAY_BUFFER, entry.m_indirectPointersBuffer->getBuffer() ); glVertexAttribLPointerEXT( 12, 1, GL_UNSIGNED_INT64_NV, 0, 0 ); glVertexAttribDivisor( 12, 1); // TODO update vertex attrib pointer to 64-bit values #define USE_DRAW_INDIRECT_BUFFER #if 0 #if defined(USE_DRAW_INDIRECT_BUFFER) dp::gl::bind( GL_DRAW_INDIRECT_BUFFER, entry.m_indirectCommandsBuffer->getBuffer() ); size_t offset = 0; for (size_t index = 0; index < entry.m_indirectCommands.size(); ++index ) { glDrawArraysIndirect( entry.m_primitiveType, (const void*)(offset) ); offset += sizeof( RenderGroupGLCache::DrawArraysIndirectCommand ); } #else RenderGroupGLCache::DrawArraysIndirectCommand *command = &entry.m_indirectCommands[0]; for (size_t index = 0; index < entry.m_indirectCommands.size(); ++index ) { //glDrawArraysIndirect( entry.m_primitiveType, command ); glDrawArraysInstancedBaseInstance( entry.m_primitiveType, command->first, command->count, command->primCount, command->baseInstance ); //glDrawementsBaseVertex( entry.m_primitiveType, command->count, GL_UN) ++command; } #endif #else #if defined(USE_DRAW_INDIRECT_BUFFER) dp::gl::bind( GL_DRAW_INDIRECT_BUFFER, entry.m_indirectCommandsBuffer->getBuffer() ); glMultiDrawArraysIndirectAMD( entry.m_primitiveType, 0, static_cast<GLsizei>(entry.m_indirectCommands.size()), sizeof( RenderGroupGLCache::DrawArraysIndirectCommand ) ); #else RenderGroupGLCache::DrawArraysIndirectCommand *commands = &entry.m_indirectCommands[0]; glMultiDrawArraysIndirectAMD( entry.m_primitiveType, commands, static_cast<GLuint>(entry.m_indirectCommands.size()), 0 ); #endif #endif } #if 0 unsigned int indirectCommands = 0; glEnable( GL_PRIMITIVE_RESTART ); //glDisable( GL_PRIMITIVE_RESTART ); glPrimitiveRestartIndex( ~0 ); glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV ); glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV); glEnableVertexAttribArray( 12 ); glVertexAttribDivisor( 12, 1); glVertexAttribLFormatNV( 12, 1, GL_UNSIGNED_INT64_NV, 0 ); for ( size_t idx = 0;idx < cache->m_drawElementsList.size(); ++idx ) { const RenderGroupGLCache::DrawElementsListEntry& entry = cache->m_drawElementsList[idx]; //dp::gl::bind( GL_ARRAY_BUFFER, entry.m_indirectPointersBuffer ); //glVertexAttribLPointerEXT( 12, 1, GL_UNSIGNED_INT64_NV, 0, 0 ); glBufferAddressRangeNV( GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 12, entry.m_indirectPointersBufferAddress, entry.m_indirectPointersBufferRange ); //dp::gl::bind( GL_ELEMENT_ARRAY_BUFFER, entry.m_indexBuffer ); glBufferAddressRangeNV( GL_ELEMENT_ARRAY_ADDRESS_NV, 0, entry.m_indexBufferAddress, entry.m_indexBufferRange ); //glMultiDrawElementsIndirectAMD( entry.m_primitiveType, GL_UNSIGNED_INT, &entry.m_indirectCommands[0], static_cast<GLuint>(entry.m_indirectCommands.size()), 0); //glDrawElementsIndirect( entry.m_primitiveType, GL_UNSIGNED_INT, &entry.m_indirectCommands[0] ); glDrawElementsInstancedBaseVertexBaseInstance( entry.m_primitiveType, entry.m_indirectCommands[0].count, GL_UNSIGNED_INT, 0, 1, entry.m_indirectCommands[0].baseVertex, entry.m_indirectCommands[0].baseInstance ); indirectCommands += static_cast<unsigned int>(entry.m_indirectCommands.size()); } glDisableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV ); glDisableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV); #endif //std::cout << "indirect commands " << indirectCommands << ", " << cache->m_drawElementsList.size() << std::endl; } }
void addElementIndirectCommand( RenderEngineGLIndirect::RenderGroupGLCache* /*cache*/, RenderEngineGLIndirect::RenderGroupGLCache::DrawElementsListEntry& entry, GeometryInstanceGLHandle gi ) { #if 1 entry.m_indirectEntries.push_back( generateIndirectEntry( gi ) ); RenderEngineGLIndirect::RenderGroupGLCache::DrawElementsIndirectCommand command; command.count = static_cast<GLuint>(gi->getGeometry()->getIndices()->getCount()); command.primCount = 1; command.firstIndex = 0; command.baseInstance = 0; command.baseVertex = 0; command.baseInstance = static_cast<GLuint>(entry.m_indirectCommands.size()); entry.m_indirectCommands.push_back(command); RenderEngineGLIndirect::RenderGroupGLCache::BindlessPointer pointer; DP_ASSERT( gi->getGeometry()->getIndices()->getBufferHandle()->getBuffer() ); dp::gl::BufferSharedPtr const& buffer = gi->getGeometry()->getIndices()->getBufferHandle()->getBuffer(); pointer.m_address = buffer->getAddress(); pointer.m_range = buffer->getSize(); entry.m_indexPointers.push_back( pointer ); #else dp::gl::MappedBuffer<unsigned int> indices( entry.m_indexBuffer, GL_MAP_READ_BIT ); unsigned int first = 0; unsigned int current = 0; while ( current < gi->getGeometry()->getIndices()->getCount() ) { if (indices[current] == ~0) { if ( current - first > 0 ) { RenderEngineGLIndirect::RenderGroupGLCache::DrawElementsIndirectCommand command; command.primCount = 1; command.firstIndex = first; command.count = current - first; command.baseInstance = 0; command.baseVertex = 0; command.baseInstance = static_cast<GLuint>(drawListEntry.m_indirectCommands.size()); drawListEntry.m_indirectCommands.push_back(command); drawListEntry.m_indirectEntries.push_back( generateIndirectEntry( gi ) ); } first = current + 1; } ++current; } if ( current - first > 0 ) { RenderEngineGLIndirect::RenderGroupGLCache::DrawElementsIndirectCommand command; command.primCount = 1; command.firstIndex = first; command.count = current - first; command.baseInstance = 0; command.baseVertex = 0; command.baseInstance = static_cast<GLuint>(drawListEntry.m_indirectCommands.size()); drawListEntry.m_indirectCommands.push_back(command); drawListEntry.m_indirectEntries.push_back( generateIndirectEntry( gi ) ); } #endif //if ( drawListEntry.m_indirectCommands.size() > 1 ) { //std::cout << "#strips " << drawListEntry.m_indirectCommands.size() << std::endl; } }