Beispiel #1
0
BufferGLImpl::BufferGLImpl(IReferenceCounters *pRefCounters, 
                           FixedBlockMemoryAllocator &BuffViewObjMemAllocator, 
                           RenderDeviceGLImpl *pDeviceGL, 
                           const BufferDesc& BuffDesc, 
                           const BufferData &BuffData /*= BufferData()*/,
                           bool bIsDeviceInternal) : 
    TBufferBase( pRefCounters, BuffViewObjMemAllocator, pDeviceGL, BuffDesc, bIsDeviceInternal),
    m_GlBuffer(true), // Create buffer immediately
    m_uiMapTarget(0),
    m_GLUsageHint(UsageToGLUsage(BuffDesc.Usage)),
    m_bUseMapWriteDiscardBugWA(GetUseMapWriteDiscardBugWA(pDeviceGL))
{
    if( BuffDesc.Usage == USAGE_STATIC && BuffData.pData == nullptr )
        LOG_ERROR_AND_THROW("Static buffer must be initialized with data at creation time");

    auto Target = GetBufferBindTarget(BuffDesc);
    // TODO: find out if it affects performance if the buffer is originally bound to one target
    // and then bound to another (such as first to GL_ARRAY_BUFFER and then to GL_UNIFORM_BUFFER)
    glBindBuffer(Target, m_GlBuffer);
    VERIFY(BuffData.pData == nullptr || BuffData.DataSize >= BuffDesc.uiSizeInBytes, "Data pointer is null or data size is not consistent with buffer size" );
    GLsizeiptr DataSize = BuffDesc.uiSizeInBytes;
 	const GLvoid *pData = nullptr;
    if( BuffData.pData && BuffData.DataSize >= BuffDesc.uiSizeInBytes )
    {
        pData = BuffData.pData;
        DataSize = BuffData.DataSize;
    }
    // Create and initialize a buffer object's data store

    // Target must be one of GL_ARRAY_BUFFER, GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 
    // GL_ELEMENT_ARRAY_BUFFER, GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER, GL_TEXTURE_BUFFER, 
    // GL_TRANSFORM_FEEDBACK_BUFFER, or GL_UNIFORM_BUFFER.

    // Usage must be one of GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY, GL_STATIC_DRAW, 
    // GL_STATIC_READ, GL_STATIC_COPY, GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, or GL_DYNAMIC_COPY.

    //The frequency of access may be one of these:
    //
    //STREAM
    //  The data store contents will be modified once and used at most a few times.
    //
    //STATIC
    //  The data store contents will be modified once and used many times.
    //
    //DYNAMIC
    //  The data store contents will be modified repeatedly and used many times.
    //
    
    //The nature of access may be one of these:
    //
    //DRAW
    //  The data store contents are modified by the application, and used as the source for GL 
    //  drawing and image specification commands.
    //
    //READ
    //  The data store contents are modified by reading data from the GL, and used to return that 
    //  data when queried by the application.
    //
    //COPY
    //  The data store contents are modified by reading data from the GL, and used as the source 
    //  for GL drawing and image specification commands.

    // See also http://www.informit.com/articles/article.aspx?p=2033340&seqNum=2

    // All buffer bind targets (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER etc.) relate to the same 
    // kind of objects. As a result they are all equivalent from a transfer point of view.
    glBufferData(Target, DataSize, pData, m_GLUsageHint);
    CHECK_GL_ERROR_AND_THROW("glBufferData() failed");
    glBindBuffer(Target, 0);
}
void TextureBaseGL::CreateViewInternal( const struct TextureViewDesc &OrigViewDesc, class ITextureView **ppView, bool bIsDefaultView )
{
    VERIFY( ppView != nullptr, "Null pointer provided" );
    if( !ppView )return;
    VERIFY( *ppView == nullptr, "Overwriting reference to existing object may cause memory leaks" );

    *ppView = nullptr;

    try
    {
        auto ViewDesc = OrigViewDesc;
        CorrectTextureViewDesc(ViewDesc);

        auto *pDeviceGLImpl = ValidatedCast<RenderDeviceGLImpl>(GetDevice());
        auto &TexViewAllocator = pDeviceGLImpl->GetTexViewObjAllocator();
        VERIFY( &TexViewAllocator == &m_dbgTexViewObjAllocator, "Texture view allocator does not match allocator provided during texture initialization" );

        // http://www.opengl.org/wiki/Texture_Storage#Texture_views

        GLenum GLViewFormat = TexFormatToGLInternalTexFormat( ViewDesc.Format, m_Desc.BindFlags );
        VERIFY( GLViewFormat != 0, "Unsupported texture format" );
        
        TextureViewGLImpl *pViewOGL = nullptr;
        if( ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE )
        {
            bool bIsFullTextureView =
                ViewDesc.TextureDim     == m_Desc.Type       &&
                ViewDesc.Format          == GetDefaultTextureViewFormat( m_Desc.Format, ViewDesc.ViewType, m_Desc.BindFlags ) &&
                ViewDesc.MostDetailedMip == 0                &&
                ViewDesc.NumMipLevels    == m_Desc.MipLevels &&
                ViewDesc.FirstArraySlice == 0                &&
                ViewDesc.NumArraySlices  == m_Desc.ArraySize;

            pViewOGL = NEW_RC_OBJ(TexViewAllocator, "TextureViewGLImpl instance", TextureViewGLImpl, bIsDefaultView ? this : nullptr)(
                                               pDeviceGLImpl, ViewDesc, this, 
                                               !bIsFullTextureView, // Create OpenGL texture view object if view
                                                                    // does not address the whole texture
                                               bIsDefaultView
                                               );
            if( !bIsFullTextureView )
            {
                GLenum GLViewTarget = 0;
                switch(ViewDesc.TextureDim)
                {
                    case RESOURCE_DIM_TEX_1D:
                        GLViewTarget = GL_TEXTURE_1D;
                        ViewDesc.NumArraySlices = 1;
                        break;
        
                    case RESOURCE_DIM_TEX_1D_ARRAY:
                        GLViewTarget = GL_TEXTURE_1D_ARRAY;
                        break;

                    case RESOURCE_DIM_TEX_2D:
                        GLViewTarget = m_Desc.SampleCount > 1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
                        ViewDesc.NumArraySlices = 1;
                        break;
        
                    case RESOURCE_DIM_TEX_2D_ARRAY:
                        GLViewTarget = m_Desc.SampleCount > 1 ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY;
                        break;

                    case RESOURCE_DIM_TEX_3D:
                        GLViewTarget = GL_TEXTURE_3D;
                        break;

                    case RESOURCE_DIM_TEX_CUBE:
                        GLViewTarget = GL_TEXTURE_CUBE_MAP;
                        break;

                    case RESOURCE_DIM_TEX_CUBE_ARRAY:
                        GLViewTarget = GL_TEXTURE_CUBE_MAP_ARRAY;
                        break;

                    default: UNEXPECTED("Unsupported texture view type");
                }

                glTextureView( pViewOGL->GetHandle(), GLViewTarget, m_GlTexture, GLViewFormat, ViewDesc.MostDetailedMip, ViewDesc.NumMipLevels, ViewDesc.FirstArraySlice, ViewDesc.NumArraySlices );
                CHECK_GL_ERROR_AND_THROW( "Failed to create texture view" );
                pViewOGL->SetBindTarget(GLViewTarget);
            }
        }
        else if( ViewDesc.ViewType == TEXTURE_VIEW_UNORDERED_ACCESS )
        {
            VERIFY( ViewDesc.NumArraySlices == 1 || ViewDesc.NumArraySlices == m_Desc.ArraySize,
                    "Only single array/depth slice or the whole texture can be bound as UAV in OpenGL");
            VERIFY( ViewDesc.AccessFlags != 0, "At least one access flag must be specified" );
            pViewOGL = NEW_RC_OBJ(TexViewAllocator, "TextureViewGLImpl instance", TextureViewGLImpl, bIsDefaultView ? this : nullptr)(
                                               pDeviceGLImpl, ViewDesc, this, 
                                               false, // Do NOT create texture view OpenGL object
                                               bIsDefaultView
                                               );
        }
        else if( ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET )
        {
            VERIFY( ViewDesc.NumMipLevels == 1, "Only single mip level can be bound as RTV" );
            pViewOGL = NEW_RC_OBJ(TexViewAllocator, "TextureViewGLImpl instance", TextureViewGLImpl, bIsDefaultView ? this : nullptr)(
                                               pDeviceGLImpl, ViewDesc, this, 
                                               false, // Do NOT create texture view OpenGL object
                                               bIsDefaultView
                                              );
        }
        else if( ViewDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL )
        {
            VERIFY( ViewDesc.NumMipLevels == 1, "Only single mip level can be bound as DSV" );
            pViewOGL = NEW_RC_OBJ(TexViewAllocator, "TextureViewGLImpl instance", TextureViewGLImpl, bIsDefaultView ? this : nullptr)(
                                               pDeviceGLImpl, ViewDesc, this, 
                                               false, // Do NOT create texture view OpenGL object
                                               bIsDefaultView
                                              );
        }

        if( bIsDefaultView )
            *ppView = pViewOGL;
        else
        {
            if( pViewOGL )
            {
                pViewOGL->QueryInterface( IID_TextureView, reinterpret_cast<IObject**>(ppView) );
            }
        }
    }
    catch( const std::runtime_error& )
    {
        const auto *ViewTypeName = GetTexViewTypeLiteralName(OrigViewDesc.ViewType);
        LOG_ERROR("Failed to create view \"", OrigViewDesc.Name ? OrigViewDesc.Name : "", "\" (", ViewTypeName, ") for texture \"", m_Desc.Name ? m_Desc.Name : "", "\"" )
    }
}