#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h" #include "XCEngine/RHI/OpenGL/OpenGLTexture.h" #include "XCEngine/RHI/OpenGL/OpenGLBuffer.h" #include "XCEngine/RHI/OpenGL/OpenGLFramebuffer.h" #include "XCEngine/RHI/OpenGL/OpenGLTextureUnitAllocator.h" #include "XCEngine/RHI/OpenGL/OpenGLUniformBufferManager.h" #include namespace XCEngine { namespace RHI { namespace { GLenum ResolveFramebufferTextureTarget(OpenGLTextureType textureType, const ResourceViewDesc& desc) { switch (textureType) { case OpenGLTextureType::Texture1D: return GL_TEXTURE_1D; case OpenGLTextureType::Texture2D: return GL_TEXTURE_2D; case OpenGLTextureType::TextureCube: { const uint32_t face = desc.firstArraySlice < 6 ? desc.firstArraySlice : 0; return GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; } case OpenGLTextureType::Texture2DArray: case OpenGLTextureType::Texture3D: case OpenGLTextureType::TextureCubeArray: return 0; default: return GL_TEXTURE_2D; } } int ResolveFramebufferAttachmentLayer(OpenGLTextureType textureType, const ResourceViewDesc& desc) { switch (textureType) { case OpenGLTextureType::Texture2DArray: case OpenGLTextureType::Texture3D: case OpenGLTextureType::TextureCubeArray: return static_cast(desc.firstArraySlice); default: return -1; } } Format ResolveViewFormat(OpenGLTexture* texture, const ResourceViewDesc& desc) { if (desc.format != 0) { return static_cast(desc.format); } return texture ? texture->GetFormat() : Format::Unknown; } FramebufferAttachmentType ResolveDepthAttachmentType(Format format) { return format == Format::D24_UNorm_S8_UInt ? FramebufferAttachmentType::DepthStencil : FramebufferAttachmentType::Depth; } } // namespace OpenGLResourceView::OpenGLResourceView() : m_viewType(ResourceViewType::RenderTarget) , m_format(Format::Unknown) , m_dimension(ResourceViewDimension::Unknown) , m_framebufferID(0) , m_textureUnit(-1) , m_bindingPoint(-1) , m_texture(nullptr) , m_buffer(nullptr) , m_framebuffer(nullptr) , m_textureUnitAllocator(nullptr) , m_uniformBufferManager(nullptr) , m_bufferOffset(0) , m_bufferSize(0) , m_bufferStride(0) { } OpenGLResourceView::~OpenGLResourceView() { Shutdown(); } void OpenGLResourceView::Shutdown() { if (m_textureUnit >= 0 && m_textureUnitAllocator) { m_textureUnitAllocator->UnbindTexture(m_textureUnit); m_textureUnitAllocator->Free(m_textureUnit); m_textureUnit = -1; } if (m_bindingPoint >= 0 && m_uniformBufferManager) { m_uniformBufferManager->UnbindBuffer(m_bindingPoint); m_uniformBufferManager->Free(m_bindingPoint); m_bindingPoint = -1; } m_framebuffer = nullptr; m_textureUnitAllocator = nullptr; m_uniformBufferManager = nullptr; m_framebufferAttachment = {}; m_framebufferID = 0; m_texture = nullptr; m_buffer = nullptr; m_bufferOffset = 0; m_bufferSize = 0; m_bufferStride = 0; } void* OpenGLResourceView::GetNativeHandle() { switch (m_viewType) { case ResourceViewType::VertexBuffer: case ResourceViewType::IndexBuffer: return reinterpret_cast(static_cast(m_buffer ? m_buffer->GetID() : 0)); case ResourceViewType::RenderTarget: case ResourceViewType::DepthStencil: return reinterpret_cast(static_cast(m_framebufferID)); case ResourceViewType::ShaderResource: case ResourceViewType::UnorderedAccess: return reinterpret_cast(static_cast(m_texture ? m_texture->GetID() : 0)); case ResourceViewType::ConstantBuffer: return reinterpret_cast(static_cast(m_buffer ? m_buffer->GetID() : 0)); default: return nullptr; } } bool OpenGLResourceView::IsValid() const { switch (m_viewType) { case ResourceViewType::VertexBuffer: case ResourceViewType::IndexBuffer: return m_buffer != nullptr && m_buffer->GetID() != 0; case ResourceViewType::RenderTarget: case ResourceViewType::DepthStencil: return m_framebufferID != 0; case ResourceViewType::ShaderResource: return m_texture != nullptr && m_texture->GetID() != 0; case ResourceViewType::UnorderedAccess: return m_texture != nullptr && m_textureUnit >= 0; case ResourceViewType::ConstantBuffer: return m_buffer != nullptr && m_bindingPoint >= 0; default: return false; } } bool OpenGLResourceView::InitializeAsRenderTarget( OpenGLTexture* texture, const ResourceViewDesc& desc, OpenGLFramebuffer* framebuffer) { if (!texture || !framebuffer) { return false; } m_viewType = ResourceViewType::RenderTarget; m_format = ResolveViewFormat(texture, desc); m_dimension = desc.dimension; m_texture = texture; m_framebuffer = framebuffer; m_framebufferID = framebuffer->GetFramebuffer(); m_framebufferAttachment.texture = texture->GetID(); m_framebufferAttachment.target = ResolveFramebufferTextureTarget(texture->GetOpenGLType(), desc); m_framebufferAttachment.mipLevel = static_cast(desc.mipLevel); m_framebufferAttachment.layer = ResolveFramebufferAttachmentLayer(texture->GetOpenGLType(), desc); m_framebufferAttachment.type = FramebufferAttachmentType::Color; m_framebufferAttachment.format = static_cast(m_format); return true; } bool OpenGLResourceView::InitializeAsDepthStencil( OpenGLTexture* texture, const ResourceViewDesc& desc, OpenGLFramebuffer* framebuffer) { if (!texture || !framebuffer) { return false; } m_viewType = ResourceViewType::DepthStencil; m_format = ResolveViewFormat(texture, desc); m_dimension = desc.dimension; m_texture = texture; m_framebuffer = framebuffer; m_framebufferID = framebuffer->GetFramebuffer(); m_framebufferAttachment.texture = texture->GetID(); m_framebufferAttachment.target = ResolveFramebufferTextureTarget(texture->GetOpenGLType(), desc); m_framebufferAttachment.mipLevel = static_cast(desc.mipLevel); m_framebufferAttachment.layer = ResolveFramebufferAttachmentLayer(texture->GetOpenGLType(), desc); m_framebufferAttachment.type = ResolveDepthAttachmentType(m_format); m_framebufferAttachment.format = static_cast(m_format); return true; } bool OpenGLResourceView::InitializeAsShaderResource( OpenGLTexture* texture, const ResourceViewDesc& desc, OpenGLTextureUnitAllocator* allocator) { if (!texture) { return false; } m_viewType = ResourceViewType::ShaderResource; m_format = ResolveViewFormat(texture, desc); m_dimension = desc.dimension; m_texture = texture; m_textureUnit = -1; m_textureUnitAllocator = allocator; return true; } bool OpenGLResourceView::InitializeAsUnorderedAccess( OpenGLTexture* texture, const ResourceViewDesc& desc, OpenGLTextureUnitAllocator* allocator) { if (!texture || !allocator) { return false; } int32_t unit = allocator->Allocate(); if (unit < 0) { return false; } m_viewType = ResourceViewType::UnorderedAccess; m_format = ResolveViewFormat(texture, desc); m_dimension = desc.dimension; m_texture = texture; m_textureUnit = unit; m_textureUnitAllocator = allocator; glActiveTexture(GL_TEXTURE0 + unit); glBindTexture(static_cast(texture->GetOpenGLType()), texture->GetID()); glBindImageTexture(unit, texture->GetID(), 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); return true; } bool OpenGLResourceView::InitializeAsConstantBuffer( OpenGLBuffer* buffer, const ResourceViewDesc& desc, OpenGLUniformBufferManager* manager) { if (!buffer || !manager) { return false; } int32_t bindingPoint = manager->Allocate(); if (bindingPoint < 0) { return false; } m_viewType = ResourceViewType::ConstantBuffer; m_format = Format::Unknown; m_dimension = ResourceViewDimension::Buffer; m_buffer = buffer; m_bindingPoint = bindingPoint; m_uniformBufferManager = manager; manager->BindBuffer(bindingPoint, buffer, 0, static_cast(desc.bufferLocation)); return true; } bool OpenGLResourceView::InitializeAsVertexBuffer( OpenGLBuffer* buffer, const ResourceViewDesc& desc) { if (!buffer) { return false; } m_viewType = ResourceViewType::VertexBuffer; m_format = Format::Unknown; m_dimension = ResourceViewDimension::Buffer; m_buffer = buffer; m_bufferOffset = desc.bufferLocation; m_bufferSize = static_cast(buffer->GetSize()); m_bufferStride = desc.structureByteStride > 0 ? desc.structureByteStride : buffer->GetStride(); return true; } bool OpenGLResourceView::InitializeAsIndexBuffer( OpenGLBuffer* buffer, const ResourceViewDesc& desc) { if (!buffer) { return false; } m_viewType = ResourceViewType::IndexBuffer; m_format = desc.format != 0 ? static_cast(desc.format) : Format::R32_UInt; m_dimension = ResourceViewDimension::Buffer; m_buffer = buffer; m_bufferOffset = desc.bufferLocation; m_bufferSize = static_cast(buffer->GetSize()); m_bufferStride = buffer->GetStride(); return true; } unsigned int OpenGLResourceView::GetFramebuffer() const { return m_framebuffer ? m_framebuffer->GetFramebuffer() : 0; } unsigned int OpenGLResourceView::GetTexture() const { return m_texture ? m_texture->GetID() : 0; } unsigned int OpenGLResourceView::GetBuffer() const { return m_buffer ? m_buffer->GetID() : 0; } } // namespace RHI } // namespace XCEngine