Refactor RHI ResourceView abstraction layer for unified cross-platform interface

- Create unified RHIResourceView base interface with type-specific Initialize methods
- Implement D3D12ResourceView with RTV/DSV/SRV/UAV/CBV support
- Implement OpenGL ResourceView simulation layer using FBO, texture units, and UBO
- Add OpenGLTextureUnitAllocator for managing texture unit bindings
- Add OpenGLUniformBufferManager for UBO binding points
- Add OpenGLFramebuffer for FBO management
- Remove deprecated D3D12 view classes (RenderTargetView, DepthStencilView, etc.)
- Fix ExecuteCommandLists type confusion bug by adding GetNativeHandle to RHICommandList
- Fix test bug where Close() was called before ExecuteCommandLists
- Update all integration tests to use new D3D12ResourceView class
- All tests pass: 144 unit tests + 8 integration tests
This commit is contained in:
2026-03-24 03:49:13 +08:00
parent 86b6d6b042
commit 0a3fe842b9
32 changed files with 1288 additions and 233 deletions

View File

@@ -59,7 +59,8 @@ void D3D12CommandQueue::ExecuteCommandLists(uint32_t count, void** lists) {
std::vector<ID3D12CommandList*> cmdLists(count);
for (uint32_t i = 0; i < count; ++i) {
if (lists[i]) {
cmdLists[i] = static_cast<ID3D12CommandList*>(lists[i]);
RHICommandList* cmdList = static_cast<RHICommandList*>(lists[i]);
cmdLists[i] = static_cast<ID3D12CommandList*>(cmdList->GetNativeHandle());
}
}

View File

@@ -12,11 +12,7 @@
#include "XCEngine/RHI/D3D12/D3D12Buffer.h"
#include "XCEngine/RHI/D3D12/D3D12SwapChain.h"
#include "XCEngine/RHI/D3D12/D3D12Shader.h"
#include "XCEngine/RHI/D3D12/D3D12RenderTargetView.h"
#include "XCEngine/RHI/D3D12/D3D12DepthStencilView.h"
#include "XCEngine/RHI/D3D12/D3D12ShaderResourceView.h"
#include "XCEngine/RHI/D3D12/D3D12UnorderedAccessView.h"
#include "XCEngine/RHI/D3D12/D3D12ConstantBufferView.h"
#include "XCEngine/RHI/D3D12/D3D12ResourceView.h"
#include <stdio.h>
#ifdef _DEBUG
@@ -376,6 +372,109 @@ RHIPipelineState* D3D12Device::CreatePipelineState(const PipelineStateDesc& desc
return nullptr;
}
RHIResourceView* D3D12Device::CreateRenderTargetView(RHITexture* texture, const ResourceViewDesc& desc) {
auto* view = new D3D12ResourceView();
auto* d3d12Texture = static_cast<D3D12Texture*>(texture);
ID3D12Resource* resource = d3d12Texture->GetResource();
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
rtvDesc.Format = static_cast<DXGI_FORMAT>(desc.format);
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
DescriptorHeapDesc heapDesc = {};
heapDesc.descriptorCount = 1;
heapDesc.heapType = static_cast<uint32_t>(DescriptorHeapType::RTV);
heapDesc.shaderVisible = false;
auto* heapPool = CreateDescriptorHeap(heapDesc);
auto* heap = static_cast<D3D12DescriptorHeap*>(heapPool);
view->InitializeAsRenderTarget(m_device.Get(), resource, &rtvDesc, heap, 0);
return view;
}
RHIResourceView* D3D12Device::CreateDepthStencilView(RHITexture* texture, const ResourceViewDesc& desc) {
auto* view = new D3D12ResourceView();
auto* d3d12Texture = static_cast<D3D12Texture*>(texture);
ID3D12Resource* resource = d3d12Texture->GetResource();
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
dsvDesc.Format = static_cast<DXGI_FORMAT>(desc.format);
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
DescriptorHeapDesc heapDesc = {};
heapDesc.descriptorCount = 1;
heapDesc.heapType = static_cast<uint32_t>(DescriptorHeapType::DSV);
heapDesc.shaderVisible = false;
auto* heapPool = CreateDescriptorHeap(heapDesc);
auto* heap = static_cast<D3D12DescriptorHeap*>(heapPool);
view->InitializeAsDepthStencil(m_device.Get(), resource, &dsvDesc, heap, 0);
return view;
}
RHIResourceView* D3D12Device::CreateShaderResourceView(RHITexture* texture, const ResourceViewDesc& desc) {
auto* view = new D3D12ResourceView();
auto* d3d12Texture = static_cast<D3D12Texture*>(texture);
ID3D12Resource* resource = d3d12Texture->GetResource();
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = static_cast<DXGI_FORMAT>(desc.format);
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = desc.mipLevel > 0 ? desc.mipLevel : 1;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
DescriptorHeapDesc heapDesc = {};
heapDesc.descriptorCount = 1;
heapDesc.heapType = static_cast<uint32_t>(DescriptorHeapType::CBV_SRV_UAV);
heapDesc.shaderVisible = true;
auto* heapPool = CreateDescriptorHeap(heapDesc);
auto* heap = static_cast<D3D12DescriptorHeap*>(heapPool);
view->InitializeAsShaderResource(m_device.Get(), resource, &srvDesc, heap, 0);
return view;
}
RHIResourceView* D3D12Device::CreateUnorderedAccessView(RHITexture* texture, const ResourceViewDesc& desc) {
auto* view = new D3D12ResourceView();
auto* d3d12Texture = static_cast<D3D12Texture*>(texture);
ID3D12Resource* resource = d3d12Texture->GetResource();
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
uavDesc.Format = static_cast<DXGI_FORMAT>(desc.format);
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
DescriptorHeapDesc heapDesc = {};
heapDesc.descriptorCount = 1;
heapDesc.heapType = static_cast<uint32_t>(DescriptorHeapType::CBV_SRV_UAV);
heapDesc.shaderVisible = true;
auto* heapPool = CreateDescriptorHeap(heapDesc);
auto* heap = static_cast<D3D12DescriptorHeap*>(heapPool);
view->InitializeAsUnorderedAccess(m_device.Get(), resource, &uavDesc, heap, 0);
return view;
}
D3D12DescriptorHeap* D3D12Device::CreateDescriptorHeap(const DescriptorHeapDesc& desc) {
auto* heap = new D3D12DescriptorHeap();
if (!heap->Initialize(m_device.Get(),
static_cast<DescriptorHeapType>(desc.heapType),
desc.descriptorCount,
desc.shaderVisible)) {
delete heap;
return nullptr;
}
return heap;
}
D3D12QueryHeap* D3D12Device::CreateQueryHeap(const QueryHeapDesc& desc) {
return nullptr;
}
D3D12RootSignature* D3D12Device::CreateRootSignature(const RootSignatureDesc& desc) {
return nullptr;
}
D3D12CommandQueue* D3D12Device::CreateCommandQueueImpl(const CommandQueueDesc& desc) {
return nullptr;
}

View File

@@ -0,0 +1,143 @@
#include "XCEngine/RHI/D3D12/D3D12ResourceView.h"
#include "XCEngine/RHI/D3D12/D3D12DescriptorHeap.h"
namespace XCEngine {
namespace RHI {
D3D12ResourceView::D3D12ResourceView()
: m_viewType(ResourceViewType::ShaderResource)
, m_handle({0})
, m_resource(nullptr)
, m_heap(nullptr)
, m_slotIndex(0) {
}
D3D12ResourceView::~D3D12ResourceView() {
Shutdown();
}
void D3D12ResourceView::Shutdown() {
m_handle = {};
m_resource = nullptr;
m_heap = nullptr;
m_slotIndex = 0;
}
void* D3D12ResourceView::GetNativeHandle() {
return this;
}
bool D3D12ResourceView::IsValid() const {
return m_handle.ptr != 0 && m_resource != nullptr;
}
void D3D12ResourceView::InitializeAsRenderTarget(ID3D12Device* device, ID3D12Resource* resource,
const D3D12_RENDER_TARGET_VIEW_DESC* desc,
D3D12DescriptorHeap* heap, uint32_t slotIndex) {
m_viewType = ResourceViewType::RenderTarget;
m_resource = resource;
m_heap = heap;
m_slotIndex = slotIndex;
m_handle = heap->GetCPUDescriptorHandleForHeapStart();
m_handle.ptr += slotIndex * heap->GetDescriptorSize();
device->CreateRenderTargetView(resource, desc, m_handle);
}
void D3D12ResourceView::InitializeAsDepthStencil(ID3D12Device* device, ID3D12Resource* resource,
const D3D12_DEPTH_STENCIL_VIEW_DESC* desc,
D3D12DescriptorHeap* heap, uint32_t slotIndex) {
m_viewType = ResourceViewType::DepthStencil;
m_resource = resource;
m_heap = heap;
m_slotIndex = slotIndex;
m_handle = heap->GetCPUDescriptorHandleForHeapStart();
m_handle.ptr += slotIndex * heap->GetDescriptorSize();
device->CreateDepthStencilView(resource, desc, m_handle);
}
void D3D12ResourceView::InitializeAsShaderResource(ID3D12Device* device, ID3D12Resource* resource,
const D3D12_SHADER_RESOURCE_VIEW_DESC* desc,
D3D12DescriptorHeap* heap, uint32_t slotIndex) {
m_viewType = ResourceViewType::ShaderResource;
m_resource = resource;
m_heap = heap;
m_slotIndex = slotIndex;
m_handle = heap->GetCPUDescriptorHandleForHeapStart();
m_handle.ptr += slotIndex * heap->GetDescriptorSize();
device->CreateShaderResourceView(resource, desc, m_handle);
}
void D3D12ResourceView::InitializeAsUnorderedAccess(ID3D12Device* device, ID3D12Resource* resource,
const D3D12_UNORDERED_ACCESS_VIEW_DESC* desc,
D3D12DescriptorHeap* heap, uint32_t slotIndex) {
m_viewType = ResourceViewType::UnorderedAccess;
m_resource = resource;
m_heap = heap;
m_slotIndex = slotIndex;
m_handle = heap->GetCPUDescriptorHandleForHeapStart();
m_handle.ptr += slotIndex * heap->GetDescriptorSize();
device->CreateUnorderedAccessView(resource, nullptr, desc, m_handle);
}
void D3D12ResourceView::InitializeAsConstantBuffer(ID3D12Device* device, ID3D12Resource* resource,
const D3D12_CONSTANT_BUFFER_VIEW_DESC* desc,
D3D12DescriptorHeap* heap, uint32_t slotIndex) {
m_viewType = ResourceViewType::ConstantBuffer;
m_resource = resource;
m_heap = heap;
m_slotIndex = slotIndex;
m_handle = heap->GetCPUDescriptorHandleForHeapStart();
m_handle.ptr += slotIndex * heap->GetDescriptorSize();
device->CreateConstantBufferView(desc, m_handle);
}
GPUDescriptorHandle D3D12ResourceView::GetGPUHandle() const {
if (m_heap) {
return m_heap->GetGPUDescriptorHandle(m_slotIndex);
}
return {};
}
D3D12_RENDER_TARGET_VIEW_DESC D3D12ResourceView::CreateRenderTargetDesc(Format format, D3D12_RTV_DIMENSION dimension) {
D3D12_RENDER_TARGET_VIEW_DESC desc = {};
desc.Format = ToD3D12(format);
desc.ViewDimension = dimension;
return desc;
}
D3D12_DEPTH_STENCIL_VIEW_DESC D3D12ResourceView::CreateDepthStencilDesc(Format format, D3D12_DSV_DIMENSION dimension) {
D3D12_DEPTH_STENCIL_VIEW_DESC desc = {};
desc.Format = ToD3D12(format);
desc.ViewDimension = dimension;
return desc;
}
D3D12_SHADER_RESOURCE_VIEW_DESC D3D12ResourceView::CreateShaderResourceDesc(Format format, D3D12_SRV_DIMENSION dimension, uint32_t mipLevels) {
D3D12_SHADER_RESOURCE_VIEW_DESC desc = {};
desc.Format = ToD3D12(format);
desc.ViewDimension = dimension;
if (mipLevels == 0) {
desc.Texture2D.MostDetailedMip = 0;
desc.Texture2D.MipLevels = 1;
} else {
desc.Texture2D.MostDetailedMip = 0;
desc.Texture2D.MipLevels = mipLevels;
}
desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
return desc;
}
D3D12_UNORDERED_ACCESS_VIEW_DESC D3D12ResourceView::CreateUnorderedAccessDesc(Format format, D3D12_UAV_DIMENSION dimension) {
D3D12_UNORDERED_ACCESS_VIEW_DESC desc = {};
desc.Format = ToD3D12(format);
desc.ViewDimension = dimension;
return desc;
}
} // namespace RHI
} // namespace XCEngine

View File

@@ -14,6 +14,10 @@
#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/OpenGLResourceView.h"
#include "XCEngine/Debug/Logger.h"
static bool s_windowClassRegistered = false;
@@ -44,6 +48,8 @@ OpenGLDevice::OpenGLDevice()
, m_initialized(false)
, m_ownsWindow(false)
, m_shouldClose(false) {
m_textureUnitAllocator = std::make_unique<OpenGLTextureUnitAllocator>();
m_uniformBufferManager = std::make_unique<OpenGLUniformBufferManager>();
}
OpenGLDevice::~OpenGLDevice() {
@@ -229,6 +235,14 @@ bool OpenGLDevice::InitializeWithExistingWindow(HWND hwnd) {
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;
@@ -297,6 +311,13 @@ void OpenGLDevice::Shutdown() {
m_hwnd = nullptr;
}
if (m_uniformBufferManager) {
m_uniformBufferManager->Shutdown();
}
if (m_textureUnitAllocator) {
m_textureUnitAllocator->Shutdown();
}
m_initialized = false;
m_ownsWindow = false;
m_shouldClose = false;
@@ -441,6 +462,106 @@ RHISampler* OpenGLDevice::CreateSampler(const SamplerDesc& desc) {
return sampler;
}
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;
}

View File

@@ -0,0 +1,141 @@
#include "XCEngine/RHI/OpenGL/OpenGLFramebuffer.h"
#include <glad/glad.h>
namespace XCEngine {
namespace RHI {
OpenGLFramebuffer::OpenGLFramebuffer()
: m_framebuffer(0)
, m_width(0)
, m_height(0)
, m_samples(1) {
}
OpenGLFramebuffer::~OpenGLFramebuffer() {
Shutdown();
}
bool OpenGLFramebuffer::Initialize(const FramebufferDesc& desc) {
m_width = desc.width;
m_height = desc.height;
m_samples = desc.samples;
m_desc = desc;
glGenFramebuffers(1, &m_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
GLenum drawBuffers[16] = { GL_NONE };
int drawBufferCount = 0;
for (size_t i = 0; i < desc.colorAttachments.size() && i < 16; ++i) {
const auto& attachment = desc.colorAttachments[i];
GLenum glAttachment = GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(i);
switch (attachment.type) {
case FramebufferAttachmentType::Color:
if (attachment.layer == 0 && attachment.mipLevel == 0) {
glFramebufferTexture2D(GL_FRAMEBUFFER, glAttachment, GL_TEXTURE_2D, attachment.texture, 0);
} else if (attachment.layer > 0) {
glFramebufferTextureLayer(GL_FRAMEBUFFER, glAttachment, attachment.texture, attachment.mipLevel, attachment.layer);
} else {
glFramebufferTexture(GL_FRAMEBUFFER, glAttachment, attachment.texture, attachment.mipLevel);
}
break;
}
drawBuffers[drawBufferCount++] = glAttachment;
}
if (desc.depthAttachment.texture != 0) {
GLenum depthAttachment = GL_DEPTH_ATTACHMENT;
if (desc.stencilAttachment.texture != 0) {
depthAttachment = GL_DEPTH_STENCIL_ATTACHMENT;
}
if (desc.depthAttachment.layer == 0 && desc.depthAttachment.mipLevel == 0) {
glFramebufferTexture2D(GL_FRAMEBUFFER, depthAttachment, GL_TEXTURE_2D, desc.depthAttachment.texture, 0);
} else if (desc.depthAttachment.layer > 0) {
glFramebufferTextureLayer(GL_FRAMEBUFFER, depthAttachment, desc.depthAttachment.texture, desc.depthAttachment.mipLevel, desc.depthAttachment.layer);
} else {
glFramebufferTexture(GL_FRAMEBUFFER, depthAttachment, desc.depthAttachment.texture, desc.depthAttachment.mipLevel);
}
}
if (desc.stencilAttachment.texture != 0 && desc.stencilAttachment.texture != desc.depthAttachment.texture) {
if (desc.stencilAttachment.layer == 0 && desc.stencilAttachment.mipLevel == 0) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, desc.stencilAttachment.texture, 0);
} else if (desc.stencilAttachment.layer > 0) {
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, desc.stencilAttachment.texture, desc.stencilAttachment.mipLevel, desc.stencilAttachment.layer);
} else {
glFramebufferTexture(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, desc.stencilAttachment.texture, desc.stencilAttachment.mipLevel);
}
}
if (drawBufferCount > 0) {
glDrawBuffers(drawBufferCount, drawBuffers);
} else {
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
}
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return false;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return true;
}
void OpenGLFramebuffer::Shutdown() {
if (m_framebuffer) {
glDeleteFramebuffers(1, &m_framebuffer);
m_framebuffer = 0;
}
m_width = 0;
m_height = 0;
m_samples = 1;
}
void OpenGLFramebuffer::Bind() {
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
}
void OpenGLFramebuffer::Unbind() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void OpenGLFramebuffer::ClearColor(int attachmentIndex, float r, float g, float b, float a) {
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
glClearBufferfv(GL_COLOR, attachmentIndex, &r);
}
void OpenGLFramebuffer::ClearDepth(float depth) {
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
glClearDepth(depth);
glClear(GL_DEPTH_BUFFER_BIT);
}
void OpenGLFramebuffer::ClearStencil(uint8_t stencil) {
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
glClearStencil(stencil);
glClear(GL_STENCIL_BUFFER_BIT);
}
void OpenGLFramebuffer::ClearDepthStencil(float depth, uint8_t stencil) {
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
glClearDepth(depth);
glClearStencil(stencil);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
void OpenGLFramebuffer::BindFramebuffer(unsigned int framebuffer) {
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
}
void OpenGLFramebuffer::UnbindFramebuffer() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,192 @@
#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 <glad/glad.h>
namespace XCEngine {
namespace RHI {
OpenGLResourceView::OpenGLResourceView()
: m_viewType(ResourceViewType::RenderTarget)
, 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<void*>(static_cast<uintptr_t>(m_framebufferID));
case ResourceViewType::ShaderResource:
case ResourceViewType::UnorderedAccess:
return reinterpret_cast<void*>(static_cast<uintptr_t>(m_texture ? m_texture->GetID() : 0));
case ResourceViewType::ConstantBuffer:
return reinterpret_cast<void*>(static_cast<uintptr_t>(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) {
(void)desc;
if (!texture || !framebuffer) {
return false;
}
m_viewType = ResourceViewType::RenderTarget;
m_texture = texture;
m_framebuffer = framebuffer;
m_framebufferID = framebuffer->GetFramebuffer();
return true;
}
bool OpenGLResourceView::InitializeAsDepthStencil(
OpenGLTexture* texture,
const ResourceViewDesc& desc,
OpenGLFramebuffer* framebuffer) {
(void)desc;
if (!texture || !framebuffer) {
return false;
}
m_viewType = ResourceViewType::DepthStencil;
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_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_texture = texture;
m_textureUnit = unit;
m_textureUnitAllocator = allocator;
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(static_cast<GLenum>(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_buffer = buffer;
m_bindingPoint = bindingPoint;
m_uniformBufferManager = manager;
manager->BindBuffer(bindingPoint, buffer, 0, static_cast<uint32_t>(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

View File

@@ -0,0 +1,89 @@
#include "XCEngine/RHI/OpenGL/OpenGLTextureUnitAllocator.h"
#include "XCEngine/RHI/OpenGL/OpenGLTexture.h"
#include <glad/glad.h>
namespace XCEngine {
namespace RHI {
OpenGLTextureUnitAllocator::OpenGLTextureUnitAllocator()
: m_maxUnits(0) {
}
OpenGLTextureUnitAllocator::~OpenGLTextureUnitAllocator() {
Shutdown();
}
void OpenGLTextureUnitAllocator::Initialize(uint32_t maxUnits) {
m_maxUnits = maxUnits;
m_allocated.resize(maxUnits, false);
m_boundTextures.resize(maxUnits, nullptr);
}
void OpenGLTextureUnitAllocator::Shutdown() {
for (uint32_t i = 0; i < m_maxUnits; ++i) {
if (m_allocated[i]) {
Free(static_cast<int32_t>(i));
}
}
m_allocated.clear();
m_boundTextures.clear();
m_maxUnits = 0;
}
int32_t OpenGLTextureUnitAllocator::Allocate() {
for (uint32_t i = 0; i < m_maxUnits; ++i) {
if (!m_allocated[i]) {
m_allocated[i] = true;
return static_cast<int32_t>(i);
}
}
return -1;
}
void OpenGLTextureUnitAllocator::Free(int32_t unit) {
if (unit < 0 || unit >= static_cast<int32_t>(m_maxUnits)) {
return;
}
UnbindTexture(unit);
m_allocated[unit] = false;
}
void OpenGLTextureUnitAllocator::BindTexture(int32_t unit, OpenGLTexture* texture) {
if (unit < 0 || unit >= static_cast<int32_t>(m_maxUnits)) {
return;
}
glActiveTexture(GL_TEXTURE0 + unit);
if (texture) {
glBindTexture(static_cast<GLenum>(texture->GetOpenGLType()), texture->GetID());
} else {
glBindTexture(GL_TEXTURE_2D, 0);
}
m_boundTextures[unit] = texture;
}
void OpenGLTextureUnitAllocator::UnbindTexture(int32_t unit) {
if (unit < 0 || unit >= static_cast<int32_t>(m_maxUnits)) {
return;
}
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_2D, 0);
m_boundTextures[unit] = nullptr;
}
OpenGLTexture* OpenGLTextureUnitAllocator::GetBoundTexture(int32_t unit) const {
if (unit < 0 || unit >= static_cast<int32_t>(m_maxUnits)) {
return nullptr;
}
return m_boundTextures[unit];
}
bool OpenGLTextureUnitAllocator::IsAllocated(int32_t unit) const {
if (unit < 0 || unit >= static_cast<int32_t>(m_maxUnits)) {
return false;
}
return m_allocated[unit];
}
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,87 @@
#include "XCEngine/RHI/OpenGL/OpenGLUniformBufferManager.h"
#include "XCEngine/RHI/OpenGL/OpenGLBuffer.h"
#include <glad/glad.h>
namespace XCEngine {
namespace RHI {
OpenGLUniformBufferManager::OpenGLUniformBufferManager()
: m_maxBindingPoints(0) {
}
OpenGLUniformBufferManager::~OpenGLUniformBufferManager() {
Shutdown();
}
void OpenGLUniformBufferManager::Initialize(uint32_t maxBindingPoints) {
m_maxBindingPoints = maxBindingPoints;
m_allocated.resize(maxBindingPoints, false);
m_boundBuffers.resize(maxBindingPoints, nullptr);
}
void OpenGLUniformBufferManager::Shutdown() {
for (uint32_t i = 0; i < m_maxBindingPoints; ++i) {
if (m_allocated[i]) {
Free(static_cast<int32_t>(i));
}
}
m_allocated.clear();
m_boundBuffers.clear();
m_maxBindingPoints = 0;
}
int32_t OpenGLUniformBufferManager::Allocate() {
for (uint32_t i = 0; i < m_maxBindingPoints; ++i) {
if (!m_allocated[i]) {
m_allocated[i] = true;
return static_cast<int32_t>(i);
}
}
return -1;
}
void OpenGLUniformBufferManager::Free(int32_t bindingPoint) {
if (bindingPoint < 0 || bindingPoint >= static_cast<int32_t>(m_maxBindingPoints)) {
return;
}
UnbindBuffer(bindingPoint);
m_allocated[bindingPoint] = false;
}
void OpenGLUniformBufferManager::BindBuffer(int32_t bindingPoint, OpenGLBuffer* buffer, uint32_t offset, uint32_t size) {
if (bindingPoint < 0 || bindingPoint >= static_cast<int32_t>(m_maxBindingPoints)) {
return;
}
if (buffer) {
glBindBufferBase(GL_UNIFORM_BUFFER, bindingPoint, buffer->GetID());
} else {
glBindBufferBase(GL_UNIFORM_BUFFER, bindingPoint, 0);
}
m_boundBuffers[bindingPoint] = buffer;
}
void OpenGLUniformBufferManager::UnbindBuffer(int32_t bindingPoint) {
if (bindingPoint < 0 || bindingPoint >= static_cast<int32_t>(m_maxBindingPoints)) {
return;
}
glBindBufferBase(GL_UNIFORM_BUFFER, bindingPoint, 0);
m_boundBuffers[bindingPoint] = nullptr;
}
OpenGLBuffer* OpenGLUniformBufferManager::GetBoundBuffer(int32_t bindingPoint) const {
if (bindingPoint < 0 || bindingPoint >= static_cast<int32_t>(m_maxBindingPoints)) {
return nullptr;
}
return m_boundBuffers[bindingPoint];
}
bool OpenGLUniformBufferManager::IsAllocated(int32_t bindingPoint) const {
if (bindingPoint < 0 || bindingPoint >= static_cast<int32_t>(m_maxBindingPoints)) {
return false;
}
return m_allocated[bindingPoint];
}
} // namespace RHI
} // namespace XCEngine