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 : "", "\"" ) } }