RHI: Add DescriptorSet abstraction for D3D12 and OpenGL backends
- Add RHIDescriptorSet base class with Update/UpdateSampler/GetNativeHandle - Add RHIDescriptorPool with AllocateSet/FreeSet methods - Add SetGraphicsDescriptorSets/SetComputeDescriptorSets to RHICommandList - Implement D3D12DescriptorSet using descriptor heap allocation - Implement OpenGLDescriptorSet using TextureUnitAllocator - Add CreateDescriptorPool/CreateDescriptorSet factory methods to RHIDevice - Fix unit test SetVertexBuffer -> SetVertexBuffers API - Add SetVertexBuffer convenience method for D3D12 backward compatibility - Update CMakeLists.txt with new source files
This commit is contained in:
146
engine/src/RHI/OpenGL/OpenGLDescriptorSet.cpp
Normal file
146
engine/src/RHI/OpenGL/OpenGLDescriptorSet.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLTextureUnitAllocator.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLSampler.h"
|
||||
#include <glad/glad.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
OpenGLDescriptorSet::OpenGLDescriptorSet()
|
||||
: m_allocator(nullptr)
|
||||
, m_layoutBindings(nullptr)
|
||||
, m_bindingCount(0)
|
||||
, m_bound(false) {
|
||||
}
|
||||
|
||||
OpenGLDescriptorSet::~OpenGLDescriptorSet() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool OpenGLDescriptorSet::Initialize(OpenGLTextureUnitAllocator* allocator, uint32_t count, const DescriptorSetLayoutDesc& layout) {
|
||||
m_allocator = allocator;
|
||||
m_bindingCount = layout.bindingCount;
|
||||
|
||||
if (layout.bindingCount > 0 && layout.bindings != nullptr) {
|
||||
m_layoutBindings = new DescriptorSetLayoutBinding[layout.bindingCount];
|
||||
for (uint32_t i = 0; i < layout.bindingCount; ++i) {
|
||||
m_layoutBindings[i] = layout.bindings[i];
|
||||
}
|
||||
}
|
||||
|
||||
m_bindings.resize(layout.bindingCount);
|
||||
for (uint32_t i = 0; i < layout.bindingCount; ++i) {
|
||||
m_bindings[i].binding = layout.bindings[i].binding;
|
||||
m_bindings[i].type = layout.bindings[i].type;
|
||||
m_bindings[i].count = layout.bindings[i].count;
|
||||
m_bindings[i].textureUnits.resize(layout.bindings[i].count);
|
||||
m_bindings[i].textureIds.resize(layout.bindings[i].count, 0);
|
||||
m_bindings[i].samplerIds.resize(layout.bindings[i].count, 0);
|
||||
|
||||
for (uint32_t j = 0; j < layout.bindings[i].count; ++j) {
|
||||
int32_t unit = m_allocator->Allocate();
|
||||
if (unit < 0) {
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
m_bindings[i].textureUnits[j] = static_cast<uint32_t>(unit);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGLDescriptorSet::Shutdown() {
|
||||
if (m_allocator != nullptr) {
|
||||
for (auto& binding : m_bindings) {
|
||||
for (uint32_t i = 0; i < binding.textureUnits.size(); ++i) {
|
||||
m_allocator->Free(static_cast<int32_t>(binding.textureUnits[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_bindings.clear();
|
||||
m_allocator = nullptr;
|
||||
|
||||
if (m_layoutBindings != nullptr) {
|
||||
delete[] m_layoutBindings;
|
||||
m_layoutBindings = nullptr;
|
||||
}
|
||||
m_bindingCount = 0;
|
||||
}
|
||||
|
||||
void OpenGLDescriptorSet::Update(uint32_t offset, RHIResourceView* view) {
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t bindingIndex = offset;
|
||||
if (bindingIndex >= m_bindings.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
OpenGLResourceView* glView = static_cast<OpenGLResourceView*>(view);
|
||||
uint32_t textureId = glView->GetTexture();
|
||||
|
||||
if (offset < m_bindings[bindingIndex].textureIds.size()) {
|
||||
m_bindings[bindingIndex].textureIds[offset] = textureId;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDescriptorSet::UpdateSampler(uint32_t offset, RHISampler* sampler) {
|
||||
if (sampler == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t bindingIndex = offset;
|
||||
if (bindingIndex >= m_bindings.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
OpenGLSampler* glSampler = static_cast<OpenGLSampler*>(sampler);
|
||||
uint32_t samplerId = glSampler->GetID();
|
||||
|
||||
if (offset < m_bindings[bindingIndex].samplerIds.size()) {
|
||||
m_bindings[bindingIndex].samplerIds[offset] = samplerId;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDescriptorSet::Bind() {
|
||||
for (size_t i = 0; i < m_bindings.size(); ++i) {
|
||||
const auto& binding = m_bindings[i];
|
||||
|
||||
for (size_t j = 0; j < binding.textureUnits.size(); ++j) {
|
||||
uint32_t unit = binding.textureUnits[j];
|
||||
uint32_t textureId = binding.textureIds[j];
|
||||
uint32_t samplerId = binding.samplerIds[j];
|
||||
|
||||
if (textureId != 0) {
|
||||
glActiveTexture(GL_TEXTURE0 + unit);
|
||||
if (binding.type == DescriptorType::Sampler) {
|
||||
glBindTexture(GL_SAMPLER, textureId);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
}
|
||||
}
|
||||
|
||||
if (samplerId != 0) {
|
||||
glBindSampler(unit, samplerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_bound = true;
|
||||
}
|
||||
|
||||
uint32_t OpenGLDescriptorSet::GetBindingPoint(uint32_t binding) const {
|
||||
for (size_t i = 0; i < m_bindings.size(); ++i) {
|
||||
if (m_bindings[i].binding == binding && !m_bindings[i].textureUnits.empty()) {
|
||||
return m_bindings[i].textureUnits[0];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
Reference in New Issue
Block a user