Use centralized OpenGLEnums.h for enum conversion: - Remove local ToGL* functions from OpenGLCommandList - Replace with ToOpenGL() and ToOpenGLClearBuffer() from OpenGLEnums - Simplify OpenGLTexture, OpenGLBuffer, OpenGLSampler, etc.
582 lines
19 KiB
C++
582 lines
19 KiB
C++
#define WIN32_LEAN_AND_MEAN
|
|
#define NOMINMAX
|
|
|
|
#include <glad/glad.h>
|
|
#include <windows.h>
|
|
|
|
#include "XCEngine/RHI/OpenGL/OpenGLDevice.h"
|
|
#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"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLTextureUnitAllocator.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLUniformBufferManager.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLFramebuffer.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLRenderPass.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorPool.h"
|
|
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h"
|
|
#include "XCEngine/Debug/Logger.h"
|
|
|
|
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
|
|
|
|
namespace XCEngine {
|
|
namespace RHI {
|
|
|
|
OpenGLDevice::OpenGLDevice()
|
|
: m_hwnd(nullptr)
|
|
, m_hdc(nullptr)
|
|
, m_hglrc(nullptr)
|
|
, m_initialized(false) {
|
|
m_textureUnitAllocator = std::make_unique<OpenGLTextureUnitAllocator>();
|
|
m_uniformBufferManager = std::make_unique<OpenGLUniformBufferManager>();
|
|
}
|
|
|
|
OpenGLDevice::~OpenGLDevice() {
|
|
Shutdown();
|
|
}
|
|
|
|
bool OpenGLDevice::Initialize(const RHIDeviceDesc& desc) {
|
|
if (m_initialized) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool OpenGLDevice::InitializeWithExistingWindow(HWND hwnd) {
|
|
if (m_initialized) {
|
|
return true;
|
|
}
|
|
|
|
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;
|
|
return false;
|
|
}
|
|
|
|
if (!SetPixelFormat(m_hdc, pixelFormat, &pfd)) {
|
|
ReleaseDC(m_hwnd, m_hdc);
|
|
m_hdc = nullptr;
|
|
return false;
|
|
}
|
|
|
|
HGLRC tempRC = wglCreateContext(m_hdc);
|
|
if (!tempRC) {
|
|
ReleaseDC(m_hwnd, m_hdc);
|
|
m_hdc = nullptr;
|
|
return false;
|
|
}
|
|
|
|
if (!wglMakeCurrent(m_hdc, tempRC)) {
|
|
wglDeleteContext(tempRC);
|
|
ReleaseDC(m_hwnd, m_hdc);
|
|
m_hdc = nullptr;
|
|
return false;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
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;
|
|
return false;
|
|
}
|
|
|
|
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");
|
|
}
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
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));
|
|
|
|
m_initialized = true;
|
|
return true;
|
|
}
|
|
|
|
void OpenGLDevice::Shutdown() {
|
|
if (m_hglrc) {
|
|
wglMakeCurrent(nullptr, nullptr);
|
|
wglDeleteContext(m_hglrc);
|
|
m_hglrc = nullptr;
|
|
}
|
|
|
|
if (m_hdc && m_hwnd) {
|
|
ReleaseDC(m_hwnd, m_hdc);
|
|
m_hdc = nullptr;
|
|
m_hwnd = nullptr;
|
|
}
|
|
|
|
if (m_uniformBufferManager) {
|
|
m_uniformBufferManager->Shutdown();
|
|
}
|
|
if (m_textureUnitAllocator) {
|
|
m_textureUnitAllocator->Shutdown();
|
|
}
|
|
|
|
m_initialized = false;
|
|
}
|
|
|
|
bool OpenGLDevice::MakeContextCurrent() {
|
|
if (m_hdc && m_hglrc) {
|
|
return ::wglMakeCurrent(m_hdc, m_hglrc) == TRUE;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void OpenGLDevice::SwapBuffers() {
|
|
if (m_hdc) {
|
|
::SwapBuffers(m_hdc);
|
|
}
|
|
}
|
|
|
|
RHIBuffer* OpenGLDevice::CreateBuffer(const BufferDesc& desc) {
|
|
auto* buffer = new OpenGLBuffer();
|
|
OpenGLBufferType bufferType = OpenGLBufferType::Vertex;
|
|
|
|
switch (desc.bufferType) {
|
|
case 1:
|
|
bufferType = OpenGLBufferType::Index;
|
|
break;
|
|
case 2:
|
|
bufferType = OpenGLBufferType::Uniform;
|
|
break;
|
|
default:
|
|
bufferType = OpenGLBufferType::Vertex;
|
|
break;
|
|
}
|
|
|
|
buffer->Initialize(bufferType, desc.size, nullptr, false);
|
|
buffer->SetStride(desc.stride);
|
|
return buffer;
|
|
}
|
|
|
|
RHITexture* OpenGLDevice::CreateTexture(const TextureDesc& desc) {
|
|
auto* texture = new OpenGLTexture();
|
|
|
|
OpenGLTextureType type = OpenGLTextureType::Texture2D;
|
|
switch (desc.textureType) {
|
|
case 0:
|
|
type = OpenGLTextureType::Texture1D;
|
|
break;
|
|
case 2:
|
|
type = OpenGLTextureType::Texture2DArray;
|
|
break;
|
|
case 3:
|
|
type = OpenGLTextureType::Texture3D;
|
|
break;
|
|
case 4:
|
|
type = OpenGLTextureType::TextureCube;
|
|
break;
|
|
default:
|
|
type = OpenGLTextureType::Texture2D;
|
|
break;
|
|
}
|
|
|
|
OpenGLFormat format = OpenGLFormat::RGBA8;
|
|
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;
|
|
}
|
|
texture->Initialize(type, desc.width, desc.height, desc.depth, desc.mipLevels, format, nullptr);
|
|
texture->SetFormat(static_cast<Format>(desc.format));
|
|
return texture;
|
|
}
|
|
|
|
RHISwapChain* OpenGLDevice::CreateSwapChain(const SwapChainDesc& desc) {
|
|
auto* swapChain = new OpenGLSwapChain();
|
|
HWND hwnd = static_cast<HWND>(desc.windowHandle);
|
|
if (hwnd) {
|
|
swapChain->Initialize(this, hwnd, desc.width, desc.height);
|
|
}
|
|
return swapChain;
|
|
}
|
|
|
|
RHICommandList* OpenGLDevice::CreateCommandList(const CommandListDesc& desc) {
|
|
auto* cmdList = new OpenGLCommandList();
|
|
return cmdList;
|
|
}
|
|
|
|
RHICommandQueue* OpenGLDevice::CreateCommandQueue(const CommandQueueDesc& desc) {
|
|
auto* queue = new OpenGLCommandQueue();
|
|
return queue;
|
|
}
|
|
|
|
RHIShader* OpenGLDevice::CreateShader(const ShaderCompileDesc& desc) {
|
|
auto* shader = new OpenGLShader();
|
|
|
|
if (desc.sourceLanguage == ShaderLanguage::GLSL && !desc.source.empty()) {
|
|
const char* sourceStr = reinterpret_cast<const char*>(desc.source.data());
|
|
ShaderType shaderType = ShaderType::Vertex;
|
|
|
|
std::string profile(desc.profile.begin(), desc.profile.end());
|
|
if (profile.find("vs") != std::string::npos) {
|
|
shaderType = ShaderType::Vertex;
|
|
} else if (profile.find("ps") != std::string::npos || profile.find("fs") != std::string::npos) {
|
|
shaderType = ShaderType::Fragment;
|
|
} else if (profile.find("gs") != std::string::npos) {
|
|
shaderType = ShaderType::Geometry;
|
|
} else if (profile.find("cs") != std::string::npos) {
|
|
shaderType = ShaderType::Compute;
|
|
}
|
|
|
|
if (shader->Compile(sourceStr, shaderType)) {
|
|
return shader;
|
|
}
|
|
delete shader;
|
|
return nullptr;
|
|
}
|
|
|
|
if (!desc.fileName.empty()) {
|
|
std::wstring filePath = desc.fileName;
|
|
std::string entryPoint(desc.entryPoint.begin(), desc.entryPoint.end());
|
|
std::string profile(desc.profile.begin(), desc.profile.end());
|
|
shader->CompileFromFile(filePath.c_str(), entryPoint.c_str(), profile.c_str());
|
|
return shader;
|
|
}
|
|
|
|
delete shader;
|
|
return nullptr;
|
|
}
|
|
|
|
RHIPipelineState* OpenGLDevice::CreatePipelineState(const GraphicsPipelineDesc& desc) {
|
|
auto* pso = new OpenGLPipelineState();
|
|
pso->SetInputLayout(desc.inputLayout);
|
|
pso->SetRasterizerState(desc.rasterizerState);
|
|
pso->SetBlendState(desc.blendState);
|
|
pso->SetDepthStencilState(desc.depthStencilState);
|
|
pso->SetTopology(desc.topologyType);
|
|
pso->SetRenderTargetFormats(desc.renderTargetCount, desc.renderTargetFormats, desc.depthStencilFormat);
|
|
pso->SetSampleCount(desc.sampleCount);
|
|
return pso;
|
|
}
|
|
|
|
RHIPipelineLayout* OpenGLDevice::CreatePipelineLayout(const RHIPipelineLayoutDesc& desc) {
|
|
return nullptr;
|
|
}
|
|
|
|
RHIFence* OpenGLDevice::CreateFence(const FenceDesc& desc) {
|
|
auto* fence = new OpenGLFence();
|
|
fence->Initialize(desc.initialValue > 0);
|
|
return fence;
|
|
}
|
|
|
|
RHISampler* OpenGLDevice::CreateSampler(const SamplerDesc& desc) {
|
|
auto* sampler = new OpenGLSampler();
|
|
OpenGLSamplerDesc samplerDesc = {};
|
|
sampler->Initialize(samplerDesc);
|
|
return sampler;
|
|
}
|
|
|
|
RHIRenderPass* OpenGLDevice::CreateRenderPass(
|
|
uint32_t colorAttachmentCount,
|
|
const AttachmentDesc* colorAttachments,
|
|
const AttachmentDesc* depthStencilAttachment) {
|
|
auto* renderPass = new OpenGLRenderPass();
|
|
if (!renderPass->Initialize(colorAttachmentCount, colorAttachments, depthStencilAttachment)) {
|
|
delete renderPass;
|
|
return nullptr;
|
|
}
|
|
return renderPass;
|
|
}
|
|
|
|
RHIFramebuffer* OpenGLDevice::CreateFramebuffer(
|
|
class RHIRenderPass* renderPass,
|
|
uint32_t width, uint32_t height,
|
|
uint32_t colorAttachmentCount,
|
|
RHIResourceView** colorAttachments,
|
|
RHIResourceView* depthStencilAttachment) {
|
|
auto* framebuffer = new OpenGLFramebuffer();
|
|
if (!framebuffer->Initialize(renderPass, width, height, colorAttachmentCount, colorAttachments, depthStencilAttachment)) {
|
|
delete framebuffer;
|
|
return nullptr;
|
|
}
|
|
return framebuffer;
|
|
}
|
|
|
|
RHIDescriptorPool* OpenGLDevice::CreateDescriptorPool(const DescriptorPoolDesc& desc) {
|
|
auto* pool = new OpenGLDescriptorPool();
|
|
if (pool->Initialize(desc)) {
|
|
pool->SetTextureUnitAllocator(m_textureUnitAllocator.get());
|
|
return pool;
|
|
}
|
|
delete pool;
|
|
return nullptr;
|
|
}
|
|
|
|
RHIDescriptorSet* OpenGLDevice::CreateDescriptorSet(RHIDescriptorPool* pool, const DescriptorSetLayoutDesc& layout) {
|
|
if (pool == nullptr) {
|
|
return nullptr;
|
|
}
|
|
return pool->AllocateSet(layout);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
const RHICapabilities& OpenGLDevice::GetCapabilities() const {
|
|
return m_capabilities;
|
|
}
|
|
|
|
const RHIDeviceInfo& OpenGLDevice::GetDeviceInfo() const {
|
|
return m_deviceInfo;
|
|
}
|
|
|
|
void* OpenGLDevice::GetNativeDevice() {
|
|
return m_hglrc;
|
|
}
|
|
|
|
void* OpenGLDevice::GetNativeHandle() const {
|
|
return nullptr;
|
|
}
|
|
|
|
} // namespace RHI
|
|
} // namespace XCEngine
|