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 );
      }
Example #3
0
      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;
        }

      }