#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 { 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) { } 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_framebufferID = 0; m_texture = nullptr; m_buffer = nullptr; } void* OpenGLResourceView::GetNativeHandle() { switch (m_viewType) { 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::RenderTarget: case ResourceViewType::DepthStencil: return m_framebufferID != 0; case ResourceViewType::ShaderResource: 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 = static_cast(desc.format); m_dimension = desc.dimension; m_texture = texture; m_framebuffer = framebuffer; m_framebufferID = framebuffer->GetFramebuffer(); return true; } bool OpenGLResourceView::InitializeAsDepthStencil( OpenGLTexture* texture, const ResourceViewDesc& desc, OpenGLFramebuffer* framebuffer) { if (!texture || !framebuffer) { return false; } m_viewType = ResourceViewType::DepthStencil; m_format = static_cast(desc.format); m_dimension = desc.dimension; m_texture = texture; m_framebuffer = framebuffer; m_framebufferID = framebuffer->GetFramebuffer(); return true; } bool OpenGLResourceView::InitializeAsShaderResource( 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::ShaderResource; m_format = static_cast(desc.format); m_dimension = desc.dimension; m_texture = texture; m_textureUnit = unit; m_textureUnitAllocator = allocator; allocator->BindTexture(unit, texture); 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 = static_cast(desc.format); 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; } 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