2026-03-20 19:05:50 +08:00
# define WIN32_LEAN_AND_MEAN
# define NOMINMAX
# include <glad/glad.h>
# include <windows.h>
2026-03-16 17:22:45 +08:00
# include "XCEngine/RHI/OpenGL/OpenGLDevice.h"
2026-03-18 02:29:12 +08:00
# include "XCEngine/RHI/OpenGL/OpenGLBuffer.h"
# include "XCEngine/RHI/OpenGL/OpenGLTexture.h"
# include "XCEngine/RHI/OpenGL/OpenGLShader.h"
# include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h"
# include "XCEngine/RHI/OpenGL/OpenGLFence.h"
# include "XCEngine/RHI/OpenGL/OpenGLSampler.h"
# include "XCEngine/RHI/OpenGL/OpenGLCommandList.h"
# include "XCEngine/RHI/OpenGL/OpenGLCommandQueue.h"
# include "XCEngine/RHI/OpenGL/OpenGLSwapChain.h"
2026-03-24 03:49:13 +08:00
# include "XCEngine/RHI/OpenGL/OpenGLTextureUnitAllocator.h"
# include "XCEngine/RHI/OpenGL/OpenGLUniformBufferManager.h"
# include "XCEngine/RHI/OpenGL/OpenGLFramebuffer.h"
# include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
2026-03-23 18:35:49 +08:00
# include "XCEngine/Debug/Logger.h"
2026-03-20 19:05:50 +08:00
static bool s_windowClassRegistered = false ;
static const wchar_t kWindowClassName [ ] = L " XCEngine_OpenGL_WindowClass " ;
2026-03-16 16:07:12 +08:00
2026-03-23 18:35:49 +08:00
typedef const char * ( WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC ) ( HDC hdc ) ;
typedef BOOL ( WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC ) ( HDC hdc , const int * piAttribIList , const FLOAT * pfAttribFList , UINT nMaxFormats , int * piFormats , UINT * nNumFormats ) ;
typedef HGLRC ( WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC ) ( HDC hdc , HGLRC hShareContext , const int * attribList ) ;
static PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = nullptr ;
static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = nullptr ;
static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = nullptr ;
# define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
# define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
# define WGL_CONTEXT_FLAGS_ARB 0x2094
# define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
# define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
# define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x0001
2026-03-16 16:07:12 +08:00
namespace XCEngine {
namespace RHI {
OpenGLDevice : : OpenGLDevice ( )
2026-03-20 19:05:50 +08:00
: m_hwnd ( nullptr )
, m_hdc ( nullptr )
, m_hglrc ( nullptr )
2026-03-16 16:07:12 +08:00
, m_initialized ( false )
2026-03-20 19:05:50 +08:00
, m_ownsWindow ( false )
, m_shouldClose ( false ) {
2026-03-24 03:49:13 +08:00
m_textureUnitAllocator = std : : make_unique < OpenGLTextureUnitAllocator > ( ) ;
m_uniformBufferManager = std : : make_unique < OpenGLUniformBufferManager > ( ) ;
2026-03-16 16:07:12 +08:00
}
OpenGLDevice : : ~ OpenGLDevice ( ) {
Shutdown ( ) ;
}
2026-03-17 17:45:01 +08:00
bool OpenGLDevice : : Initialize ( const RHIDeviceDesc & desc ) {
if ( m_initialized ) {
return true ;
}
if ( desc . windowHandle ) {
2026-03-20 19:05:50 +08:00
return InitializeWithExistingWindow ( static_cast < HWND > ( desc . windowHandle ) ) ;
2026-03-17 17:45:01 +08:00
}
std : : string titleStr = " XCEngine " ;
if ( ! desc . appName . empty ( ) ) {
titleStr = std : : string ( desc . appName . begin ( ) , desc . appName . end ( ) ) ;
}
return CreateRenderWindow ( desc . width , desc . height , titleStr . c_str ( ) , desc . enableDebugLayer ) ;
}
2026-03-20 19:05:50 +08:00
bool OpenGLDevice : : InitializeWithExistingWindow ( HWND hwnd ) {
2026-03-16 16:07:12 +08:00
if ( m_initialized ) {
return true ;
}
2026-03-20 19:05:50 +08:00
if ( ! hwnd ) {
return false ;
}
m_hwnd = hwnd ;
m_hdc = : : GetDC ( m_hwnd ) ;
if ( ! m_hdc ) {
return false ;
}
PIXELFORMATDESCRIPTOR pfd = { } ;
pfd . nSize = sizeof ( PIXELFORMATDESCRIPTOR ) ;
pfd . nVersion = 1 ;
pfd . dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER ;
pfd . iPixelType = PFD_TYPE_RGBA ;
pfd . cColorBits = 32 ;
pfd . cDepthBits = 24 ;
pfd . cStencilBits = 8 ;
pfd . iLayerType = PFD_MAIN_PLANE ;
int pixelFormat = ChoosePixelFormat ( m_hdc , & pfd ) ;
if ( ! pixelFormat ) {
ReleaseDC ( m_hwnd , m_hdc ) ;
m_hdc = nullptr ;
2026-03-16 16:07:12 +08:00
return false ;
}
2026-03-20 19:05:50 +08:00
if ( ! SetPixelFormat ( m_hdc , pixelFormat , & pfd ) ) {
ReleaseDC ( m_hwnd , m_hdc ) ;
m_hdc = nullptr ;
return false ;
}
2026-03-16 16:07:12 +08:00
2026-03-23 18:35:49 +08:00
HGLRC tempRC = wglCreateContext ( m_hdc ) ;
if ( ! tempRC ) {
ReleaseDC ( m_hwnd , m_hdc ) ;
m_hdc = nullptr ;
return false ;
}
if ( ! wglMakeCurrent ( m_hdc , tempRC ) ) {
wglDeleteContext ( tempRC ) ;
2026-03-20 19:05:50 +08:00
ReleaseDC ( m_hwnd , m_hdc ) ;
m_hdc = nullptr ;
return false ;
}
2026-03-23 18:35:49 +08:00
wglGetExtensionsStringARB = ( PFNWGLGETEXTENSIONSSTRINGARBPROC ) wglGetProcAddress ( " wglGetExtensionsStringARB " ) ;
if ( wglGetExtensionsStringARB ) {
const char * extensions = wglGetExtensionsStringARB ( m_hdc ) ;
if ( extensions & & strstr ( extensions , " WGL_ARB_pixel_format " ) ) {
wglChoosePixelFormatARB = ( PFNWGLCHOOSEPIXELFORMATARBPROC ) wglGetProcAddress ( " wglChoosePixelFormatARB " ) ;
}
if ( extensions & & strstr ( extensions , " WGL_ARB_create_context " ) ) {
wglCreateContextAttribsARB = ( PFNWGLCREATECONTEXTATTRIBSARBPROC ) wglGetProcAddress ( " wglCreateContextAttribsARB " ) ;
}
}
wglMakeCurrent ( nullptr , nullptr ) ;
wglDeleteContext ( tempRC ) ;
if ( wglCreateContextAttribsARB ) {
int debugAttribs [ ] = {
WGL_CONTEXT_MAJOR_VERSION_ARB , 4 ,
WGL_CONTEXT_MINOR_VERSION_ARB , 6 ,
WGL_CONTEXT_FLAGS_ARB , WGL_CONTEXT_DEBUG_BIT_ARB ,
WGL_CONTEXT_PROFILE_MASK_ARB , WGL_CONTEXT_CORE_PROFILE_BIT_ARB ,
0 , 0
} ;
m_hglrc = wglCreateContextAttribsARB ( m_hdc , nullptr , debugAttribs ) ;
if ( m_hglrc ) {
XCEngine : : Debug : : Logger : : Get ( ) . Info ( XCEngine : : Debug : : LogCategory : : General , " Created OpenGL debug context with WGL_ARB_create_context " ) ;
}
}
if ( ! m_hglrc ) {
m_hglrc = wglCreateContext ( m_hdc ) ;
if ( m_hglrc ) {
XCEngine : : Debug : : Logger : : Get ( ) . Warning ( XCEngine : : Debug : : LogCategory : : General , " Created OpenGL context without debug bit (wglCreateContextAttribsARB failed) " ) ;
} else {
ReleaseDC ( m_hwnd , m_hdc ) ;
m_hdc = nullptr ;
return false ;
}
}
2026-03-20 19:05:50 +08:00
if ( ! wglMakeCurrent ( m_hdc , m_hglrc ) ) {
wglDeleteContext ( m_hglrc ) ;
ReleaseDC ( m_hwnd , m_hdc ) ;
m_hglrc = nullptr ;
m_hdc = nullptr ;
return false ;
}
if ( ! gladLoadGL ( ) ) {
wglMakeCurrent ( nullptr , nullptr ) ;
wglDeleteContext ( m_hglrc ) ;
ReleaseDC ( m_hwnd , m_hdc ) ;
m_hglrc = nullptr ;
m_hdc = nullptr ;
2026-03-16 16:07:12 +08:00
return false ;
}
2026-03-23 18:35:49 +08:00
GLint contextFlags = 0 ;
glGetIntegerv ( GL_CONTEXT_FLAGS , & contextFlags ) ;
if ( contextFlags & GL_CONTEXT_FLAG_DEBUG_BIT ) {
XCEngine : : Debug : : Logger : : Get ( ) . Info ( XCEngine : : Debug : : LogCategory : : General , " OpenGL debug context is active " ) ;
} else {
XCEngine : : Debug : : Logger : : Get ( ) . Warning ( XCEngine : : Debug : : LogCategory : : General , " OpenGL debug context is NOT active " ) ;
}
2026-03-17 19:35:51 +08:00
const char * vendor = reinterpret_cast < const char * > ( glGetString ( GL_VENDOR ) ) ;
const char * renderer = reinterpret_cast < const char * > ( glGetString ( GL_RENDERER ) ) ;
const char * version = reinterpret_cast < const char * > ( glGetString ( GL_VERSION ) ) ;
m_deviceInfo . vendor = std : : wstring ( vendor ? vendor : " " , vendor ? vendor + strlen ( vendor ) : nullptr ) ;
m_deviceInfo . renderer = std : : wstring ( renderer ? renderer : " " , renderer ? renderer + strlen ( renderer ) : nullptr ) ;
m_deviceInfo . version = std : : wstring ( version ? version : " " , version ? version + strlen ( version ) : nullptr ) ;
2026-03-16 16:07:12 +08:00
2026-03-17 19:44:50 +08:00
GLint majorVersion = 0 , minorVersion = 0 ;
glGetIntegerv ( GL_MAJOR_VERSION , & majorVersion ) ;
glGetIntegerv ( GL_MINOR_VERSION , & minorVersion ) ;
m_deviceInfo . majorVersion = static_cast < uint32_t > ( majorVersion ) ;
m_deviceInfo . minorVersion = static_cast < uint32_t > ( minorVersion ) ;
2026-03-18 02:36:40 +08:00
m_capabilities . majorVersion = majorVersion ;
m_capabilities . minorVersion = minorVersion ;
m_capabilities . bSupportsGeometryShaders = true ;
m_capabilities . bSupportsComputeShaders = GLVersion . major > = 4 & & GLVersion . minor > = 3 ;
m_capabilities . bSupportsTessellation = GLVersion . major > = 4 & & GLVersion . minor > = 1 ;
m_capabilities . bSupportsExplicitMultiThreading = false ;
GLint maxTexSize = 0 ;
glGetIntegerv ( GL_MAX_TEXTURE_SIZE , & maxTexSize ) ;
m_capabilities . maxTexture2DSize = static_cast < uint32_t > ( maxTexSize ) ;
GLint maxCubeSize = 0 ;
glGetIntegerv ( GL_MAX_CUBE_MAP_TEXTURE_SIZE , & maxCubeSize ) ;
m_capabilities . maxTextureCubeSize = static_cast < uint32_t > ( maxCubeSize ) ;
GLint maxRenderTargets = 0 ;
glGetIntegerv ( GL_MAX_DRAW_BUFFERS , & maxRenderTargets ) ;
m_capabilities . maxRenderTargets = static_cast < uint32_t > ( maxRenderTargets ) ;
m_capabilities . maxColorAttachments = static_cast < uint32_t > ( maxRenderTargets ) ;
GLint maxViewports = 0 ;
glGetIntegerv ( GL_MAX_VIEWPORTS , & maxViewports ) ;
m_capabilities . maxViewports = static_cast < uint32_t > ( maxViewports ) ;
GLint maxAnisotropy = 0 ;
glGetIntegerv ( GL_MAX_TEXTURE_MAX_ANISOTROPY , & maxAnisotropy ) ;
m_capabilities . maxAnisotropy = static_cast < uint32_t > ( maxAnisotropy ) ;
GLint maxAttribs = 0 ;
glGetIntegerv ( GL_MAX_VERTEX_ATTRIBS , & maxAttribs ) ;
m_capabilities . maxVertexAttribs = static_cast < uint32_t > ( maxAttribs ) ;
2026-03-24 03:49:13 +08:00
GLint maxTextureUnits = 0 ;
glGetIntegerv ( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS , & maxTextureUnits ) ;
m_textureUnitAllocator - > Initialize ( static_cast < uint32_t > ( maxTextureUnits ) ) ;
GLint maxUniformBlocks = 0 ;
glGetIntegerv ( GL_MAX_UNIFORM_BUFFER_BINDINGS , & maxUniformBlocks ) ;
m_uniformBufferManager - > Initialize ( static_cast < uint32_t > ( maxUniformBlocks ) ) ;
2026-03-18 02:36:40 +08:00
2026-03-16 16:07:12 +08:00
m_initialized = true ;
return true ;
}
2026-03-23 21:43:32 +08:00
bool OpenGLDevice : : CreateRenderWindow ( int width , int height , const char * title , bool enableDebug ) {
if ( m_initialized ) {
return true ;
}
if ( ! s_windowClassRegistered ) {
WNDCLASSEXW wc = { } ;
wc . cbSize = sizeof ( WNDCLASSEXW ) ;
wc . style = CS_HREDRAW | CS_VREDRAW ;
wc . lpfnWndProc = DefWindowProcW ;
wc . hInstance = GetModuleHandleW ( nullptr ) ;
wc . lpszClassName = kWindowClassName ;
if ( ! RegisterClassExW ( & wc ) ) {
return false ;
}
s_windowClassRegistered = true ;
}
std : : wstring titleW ( title ? std : : wstring ( title , title + strlen ( title ) ) : L " XCEngine " ) ;
HWND hwnd = CreateWindowExW (
0 ,
kWindowClassName ,
titleW . c_str ( ) ,
WS_OVERLAPPEDWINDOW ,
CW_USEDEFAULT , CW_USEDEFAULT ,
width , height ,
nullptr ,
nullptr ,
GetModuleHandleW ( nullptr ) ,
nullptr
) ;
if ( ! hwnd ) {
return false ;
}
m_hwnd = hwnd ;
m_ownsWindow = true ;
ShowWindow ( m_hwnd , SW_SHOWNORMAL ) ;
UpdateWindow ( m_hwnd ) ;
return InitializeWithExistingWindow ( m_hwnd ) ;
}
2026-03-16 16:07:12 +08:00
void OpenGLDevice : : Shutdown ( ) {
2026-03-20 19:05:50 +08:00
if ( m_hglrc ) {
wglMakeCurrent ( nullptr , nullptr ) ;
wglDeleteContext ( m_hglrc ) ;
m_hglrc = nullptr ;
2026-03-16 16:07:12 +08:00
}
2026-03-20 19:05:50 +08:00
if ( m_hdc & & m_hwnd ) {
ReleaseDC ( m_hwnd , m_hdc ) ;
m_hdc = nullptr ;
}
if ( m_ownsWindow & & m_hwnd ) {
DestroyWindow ( m_hwnd ) ;
m_hwnd = nullptr ;
}
2026-03-24 03:49:13 +08:00
if ( m_uniformBufferManager ) {
m_uniformBufferManager - > Shutdown ( ) ;
}
if ( m_textureUnitAllocator ) {
m_textureUnitAllocator - > Shutdown ( ) ;
}
2026-03-16 16:07:12 +08:00
m_initialized = false ;
m_ownsWindow = false ;
2026-03-20 19:05:50 +08:00
m_shouldClose = false ;
2026-03-16 16:07:12 +08:00
}
void OpenGLDevice : : SwapBuffers ( ) {
2026-03-20 19:05:50 +08:00
if ( m_hdc ) {
: : SwapBuffers ( m_hdc ) ;
2026-03-16 16:07:12 +08:00
}
}
bool OpenGLDevice : : PollEvents ( ) {
2026-03-20 19:05:50 +08:00
MSG msg ;
while ( PeekMessageW ( & msg , nullptr , 0 , 0 , PM_REMOVE ) ) {
if ( msg . message = = WM_QUIT ) {
m_shouldClose = true ;
return false ;
}
TranslateMessage ( & msg ) ;
DispatchMessageW ( & msg ) ;
}
return ! m_shouldClose ;
2026-03-16 16:07:12 +08:00
}
void OpenGLDevice : : SetShouldClose ( bool shouldClose ) {
2026-03-20 19:05:50 +08:00
m_shouldClose = shouldClose ;
if ( m_hwnd & & shouldClose ) {
PostMessageW ( m_hwnd , WM_CLOSE , 0 , 0 ) ;
2026-03-16 16:07:12 +08:00
}
}
bool OpenGLDevice : : ShouldClose ( ) const {
2026-03-20 19:05:50 +08:00
return m_shouldClose ;
2026-03-16 16:07:12 +08:00
}
2026-03-17 17:45:01 +08:00
RHIBuffer * OpenGLDevice : : CreateBuffer ( const BufferDesc & desc ) {
2026-03-18 02:29:12 +08:00
auto * buffer = new OpenGLBuffer ( ) ;
OpenGLBufferType bufferType = OpenGLBufferType : : Vertex ;
2026-03-18 03:37:34 +08:00
switch ( desc . bufferType ) {
2026-03-20 19:05:50 +08:00
case 1 :
2026-03-18 02:29:12 +08:00
bufferType = OpenGLBufferType : : Index ;
break ;
2026-03-20 19:05:50 +08:00
case 2 :
2026-03-18 02:29:12 +08:00
bufferType = OpenGLBufferType : : Uniform ;
break ;
default :
bufferType = OpenGLBufferType : : Vertex ;
break ;
}
2026-03-18 03:37:34 +08:00
buffer - > Initialize ( bufferType , desc . size , nullptr , false ) ;
2026-03-23 20:32:33 +08:00
buffer - > SetStride ( desc . stride ) ;
2026-03-18 02:29:12 +08:00
return buffer ;
2026-03-17 17:45:01 +08:00
}
RHITexture * OpenGLDevice : : CreateTexture ( const TextureDesc & desc ) {
2026-03-18 02:29:12 +08:00
auto * texture = new OpenGLTexture ( ) ;
OpenGLTextureType type = OpenGLTextureType : : Texture2D ;
2026-03-18 03:37:34 +08:00
switch ( desc . textureType ) {
case 0 :
2026-03-18 02:29:12 +08:00
type = OpenGLTextureType : : Texture1D ;
break ;
2026-03-18 03:37:34 +08:00
case 2 :
2026-03-23 20:32:33 +08:00
type = OpenGLTextureType : : Texture2DArray ;
2026-03-18 02:29:12 +08:00
break ;
2026-03-18 03:37:34 +08:00
case 3 :
2026-03-23 20:32:33 +08:00
type = OpenGLTextureType : : Texture3D ;
break ;
case 4 :
2026-03-18 02:29:12 +08:00
type = OpenGLTextureType : : TextureCube ;
break ;
default :
type = OpenGLTextureType : : Texture2D ;
break ;
}
OpenGLFormat format = OpenGLFormat : : RGBA8 ;
2026-03-23 20:32:33 +08:00
switch ( desc . format ) {
case 1 : format = OpenGLFormat : : R8 ; break ;
case 2 : format = OpenGLFormat : : RG8 ; break ;
case 3 : format = OpenGLFormat : : RGBA8 ; break ;
case 4 : format = OpenGLFormat : : RGBA16F ; break ;
case 5 : format = OpenGLFormat : : RGBA32F ; break ;
case 6 : format = OpenGLFormat : : RGBA16F ; break ;
case 7 : format = OpenGLFormat : : RGBA32F ; break ;
case 8 : format = OpenGLFormat : : Depth24Stencil8 ; break ;
case 9 : format = OpenGLFormat : : Depth32F ; break ;
default : format = OpenGLFormat : : RGBA8 ; break ;
}
2026-03-18 02:29:12 +08:00
texture - > Initialize ( type , desc . width , desc . height , desc . depth , desc . mipLevels , format , nullptr ) ;
2026-03-23 20:32:33 +08:00
texture - > SetFormat ( static_cast < Format > ( desc . format ) ) ;
2026-03-18 02:29:12 +08:00
return texture ;
2026-03-17 17:45:01 +08:00
}
RHISwapChain * OpenGLDevice : : CreateSwapChain ( const SwapChainDesc & desc ) {
2026-03-18 02:29:12 +08:00
auto * swapChain = new OpenGLSwapChain ( ) ;
2026-03-20 19:05:50 +08:00
if ( m_hwnd ) {
2026-03-23 21:43:32 +08:00
swapChain - > Initialize ( this , m_hwnd , desc . width , desc . height ) ;
2026-03-18 02:29:12 +08:00
}
return swapChain ;
2026-03-17 17:45:01 +08:00
}
RHICommandList * OpenGLDevice : : CreateCommandList ( const CommandListDesc & desc ) {
2026-03-18 02:29:12 +08:00
auto * cmdList = new OpenGLCommandList ( ) ;
return cmdList ;
2026-03-17 17:45:01 +08:00
}
RHICommandQueue * OpenGLDevice : : CreateCommandQueue ( const CommandQueueDesc & desc ) {
2026-03-18 02:29:12 +08:00
auto * queue = new OpenGLCommandQueue ( ) ;
return queue ;
2026-03-17 17:45:01 +08:00
}
RHIShader * OpenGLDevice : : CompileShader ( const ShaderCompileDesc & desc ) {
2026-03-18 03:37:34 +08:00
std : : wstring filePath = desc . fileName ;
2026-03-23 20:32:33 +08:00
if ( filePath . empty ( ) ) {
return nullptr ;
}
auto * shader = new OpenGLShader ( ) ;
2026-03-18 03:37:34 +08:00
std : : string entryPoint ( desc . entryPoint . begin ( ) , desc . entryPoint . end ( ) ) ;
std : : string profile ( desc . profile . begin ( ) , desc . profile . end ( ) ) ;
2026-03-23 20:32:33 +08:00
shader - > CompileFromFile ( filePath . c_str ( ) , entryPoint . c_str ( ) , profile . c_str ( ) ) ;
2026-03-18 02:29:12 +08:00
return shader ;
2026-03-17 17:45:01 +08:00
}
RHIPipelineState * OpenGLDevice : : CreatePipelineState ( const PipelineStateDesc & desc ) {
2026-03-18 02:29:12 +08:00
auto * pso = new OpenGLPipelineState ( ) ;
return pso ;
2026-03-17 17:45:01 +08:00
}
RHIFence * OpenGLDevice : : CreateFence ( const FenceDesc & desc ) {
2026-03-18 02:29:12 +08:00
auto * fence = new OpenGLFence ( ) ;
fence - > Initialize ( desc . initialValue > 0 ) ;
return fence ;
2026-03-17 17:45:01 +08:00
}
RHISampler * OpenGLDevice : : CreateSampler ( const SamplerDesc & desc ) {
2026-03-18 02:29:12 +08:00
auto * sampler = new OpenGLSampler ( ) ;
OpenGLSamplerDesc samplerDesc = { } ;
sampler - > Initialize ( samplerDesc ) ;
return sampler ;
2026-03-17 17:45:01 +08:00
}
2026-03-24 03:49:13 +08:00
RHIResourceView * OpenGLDevice : : CreateRenderTargetView ( RHITexture * texture , const ResourceViewDesc & desc ) {
if ( ! texture ) {
return nullptr ;
}
auto * glTexture = static_cast < OpenGLTexture * > ( texture ) ;
FramebufferDesc fbDesc = { } ;
fbDesc . width = static_cast < int > ( texture - > GetWidth ( ) ) ;
fbDesc . height = static_cast < int > ( texture - > GetHeight ( ) ) ;
FramebufferAttachment colorAttachment = { } ;
colorAttachment . texture = glTexture - > GetID ( ) ;
colorAttachment . mipLevel = static_cast < int > ( desc . mipLevel ) ;
colorAttachment . type = FramebufferAttachmentType : : Color ;
colorAttachment . format = desc . format ;
fbDesc . colorAttachments . push_back ( colorAttachment ) ;
auto * framebuffer = new OpenGLFramebuffer ( ) ;
if ( ! framebuffer - > Initialize ( fbDesc ) ) {
delete framebuffer ;
return nullptr ;
}
auto * view = new OpenGLResourceView ( ) ;
if ( ! view - > InitializeAsRenderTarget ( glTexture , desc , framebuffer ) ) {
delete framebuffer ;
delete view ;
return nullptr ;
}
return view ;
}
RHIResourceView * OpenGLDevice : : CreateDepthStencilView ( RHITexture * texture , const ResourceViewDesc & desc ) {
if ( ! texture ) {
return nullptr ;
}
auto * glTexture = static_cast < OpenGLTexture * > ( texture ) ;
FramebufferDesc fbDesc = { } ;
fbDesc . width = static_cast < int > ( texture - > GetWidth ( ) ) ;
fbDesc . height = static_cast < int > ( texture - > GetHeight ( ) ) ;
FramebufferAttachment depthAttachment = { } ;
depthAttachment . texture = glTexture - > GetID ( ) ;
depthAttachment . mipLevel = static_cast < int > ( desc . mipLevel ) ;
depthAttachment . type = FramebufferAttachmentType : : DepthStencil ;
depthAttachment . format = desc . format ;
fbDesc . depthAttachment = depthAttachment ;
auto * framebuffer = new OpenGLFramebuffer ( ) ;
if ( ! framebuffer - > Initialize ( fbDesc ) ) {
delete framebuffer ;
return nullptr ;
}
auto * view = new OpenGLResourceView ( ) ;
if ( ! view - > InitializeAsDepthStencil ( glTexture , desc , framebuffer ) ) {
delete framebuffer ;
delete view ;
return nullptr ;
}
return view ;
}
RHIResourceView * OpenGLDevice : : CreateShaderResourceView ( RHITexture * texture , const ResourceViewDesc & desc ) {
if ( ! texture ) {
return nullptr ;
}
auto * glTexture = static_cast < OpenGLTexture * > ( texture ) ;
auto * view = new OpenGLResourceView ( ) ;
if ( ! view - > InitializeAsShaderResource ( glTexture , desc , m_textureUnitAllocator . get ( ) ) ) {
delete view ;
return nullptr ;
}
return view ;
}
RHIResourceView * OpenGLDevice : : CreateUnorderedAccessView ( RHITexture * texture , const ResourceViewDesc & desc ) {
if ( ! texture ) {
return nullptr ;
}
auto * glTexture = static_cast < OpenGLTexture * > ( texture ) ;
auto * view = new OpenGLResourceView ( ) ;
if ( ! view - > InitializeAsUnorderedAccess ( glTexture , desc , m_textureUnitAllocator . get ( ) ) ) {
delete view ;
return nullptr ;
}
return view ;
}
2026-03-17 17:45:01 +08:00
const RHICapabilities & OpenGLDevice : : GetCapabilities ( ) const {
return m_capabilities ;
}
const RHIDeviceInfo & OpenGLDevice : : GetDeviceInfo ( ) const {
2026-03-17 19:35:51 +08:00
return m_deviceInfo ;
2026-03-17 17:45:01 +08:00
}
void * OpenGLDevice : : GetNativeDevice ( ) {
2026-03-23 21:09:15 +08:00
return m_hglrc ;
2026-03-17 17:45:01 +08:00
}
void * OpenGLDevice : : GetNativeHandle ( ) const {
return nullptr ;
}
2026-03-16 16:07:12 +08:00
} // namespace RHI
2026-03-20 19:05:50 +08:00
} // namespace XCEngine