#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 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 = static_cast(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(unit); } } return true; } void OpenGLDescriptorSet::Shutdown() { if (m_constantBuffer != 0) { glDeleteBuffers(1, reinterpret_cast(&m_constantBuffer)); m_constantBuffer = 0; } if (m_allocator != nullptr) { for (auto& binding : m_bindings) { for (uint32_t i = 0; i < binding.textureUnits.size(); ++i) { m_allocator->Free(static_cast(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(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(sampler); uint32_t samplerId = glSampler->GetID(); if (offset < m_bindings[bindingIndex].samplerIds.size()) { m_bindings[bindingIndex].samplerIds[offset] = samplerId; } } void OpenGLDescriptorSet::Bind() { if (m_constantBufferDirty && !m_constantBufferData.empty()) { if (m_constantBuffer == 0) { glGenBuffers(1, reinterpret_cast(&m_constantBuffer)); } glBindBuffer(GL_UNIFORM_BUFFER, m_constantBuffer); glBufferData(GL_UNIFORM_BUFFER, m_constantBufferData.size(), m_constantBufferData.data(), GL_DYNAMIC_DRAW); glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_constantBuffer); m_constantBufferDirty = false; } 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; } void OpenGLDescriptorSet::Unbind() { 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]; glActiveTexture(GL_TEXTURE0 + unit); glBindTexture(GL_TEXTURE_2D, 0); glBindSampler(unit, 0); } } m_bound = false; } 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; } void OpenGLDescriptorSet::WriteConstant(uint32_t binding, const void* data, size_t size, size_t offset) { size_t requiredSize = offset + size; if (m_constantBufferData.size() < requiredSize) { m_constantBufferData.resize(requiredSize); } memcpy(m_constantBufferData.data() + offset, data, size); m_constantBufferDirty = true; } } // namespace RHI } // namespace XCEngine