fix(rhi): make opengl descriptor binding set-aware
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLPipelineLayout.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLTextureUnitAllocator.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLSampler.h"
|
||||
@@ -7,6 +8,32 @@
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
namespace {
|
||||
|
||||
uint32_t ResolveBindingPoint(
|
||||
const OpenGLPipelineLayout* pipelineLayout,
|
||||
uint32_t setIndex,
|
||||
const DescriptorBinding& binding) {
|
||||
if (pipelineLayout == nullptr || !pipelineLayout->UsesSetLayouts()) {
|
||||
return binding.binding;
|
||||
}
|
||||
|
||||
switch (binding.type) {
|
||||
case DescriptorType::CBV:
|
||||
return pipelineLayout->GetConstantBufferBindingPoint(setIndex, binding.binding);
|
||||
case DescriptorType::SRV:
|
||||
return pipelineLayout->GetShaderResourceBindingPoint(setIndex, binding.binding);
|
||||
case DescriptorType::UAV:
|
||||
return pipelineLayout->GetUnorderedAccessBindingPoint(setIndex, binding.binding);
|
||||
case DescriptorType::Sampler:
|
||||
return pipelineLayout->GetSamplerBindingPoint(setIndex, binding.binding);
|
||||
default:
|
||||
return UINT32_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
OpenGLDescriptorSet::OpenGLDescriptorSet()
|
||||
: m_allocator(nullptr)
|
||||
, m_layoutBindings(nullptr)
|
||||
@@ -97,6 +124,7 @@ void OpenGLDescriptorSet::Shutdown() {
|
||||
|
||||
m_bindings.clear();
|
||||
m_allocator = nullptr;
|
||||
m_bound = false;
|
||||
|
||||
if (m_layoutBindings != nullptr) {
|
||||
delete[] m_layoutBindings;
|
||||
@@ -105,6 +133,20 @@ void OpenGLDescriptorSet::Shutdown() {
|
||||
m_bindingCount = 0;
|
||||
}
|
||||
|
||||
void OpenGLDescriptorSet::EnsureConstantBufferUploaded() {
|
||||
if (!m_constantBufferDirty || m_constantBufferData.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_constantBuffer == 0) {
|
||||
glGenBuffers(1, reinterpret_cast<GLuint*>(&m_constantBuffer));
|
||||
}
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, m_constantBuffer);
|
||||
glBufferData(GL_UNIFORM_BUFFER, m_constantBufferData.size(), m_constantBufferData.data(), GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
m_constantBufferDirty = false;
|
||||
}
|
||||
|
||||
void OpenGLDescriptorSet::Update(uint32_t offset, RHIResourceView* view) {
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
@@ -134,15 +176,7 @@ void OpenGLDescriptorSet::UpdateSampler(uint32_t offset, RHISampler* sampler) {
|
||||
}
|
||||
|
||||
void OpenGLDescriptorSet::Bind() {
|
||||
if (m_constantBufferDirty && !m_constantBufferData.empty()) {
|
||||
if (m_constantBuffer == 0) {
|
||||
glGenBuffers(1, reinterpret_cast<GLuint*>(&m_constantBuffer));
|
||||
}
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, m_constantBuffer);
|
||||
glBufferData(GL_UNIFORM_BUFFER, m_constantBufferData.size(), m_constantBufferData.data(), GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
m_constantBufferDirty = false;
|
||||
}
|
||||
EnsureConstantBufferUploaded();
|
||||
|
||||
if (m_constantBuffer != 0) {
|
||||
for (const auto& binding : m_bindings) {
|
||||
@@ -178,6 +212,56 @@ void OpenGLDescriptorSet::Bind() {
|
||||
m_bound = true;
|
||||
}
|
||||
|
||||
void OpenGLDescriptorSet::BindWithPipelineLayout(const OpenGLPipelineLayout* pipelineLayout, uint32_t setIndex) {
|
||||
EnsureConstantBufferUploaded();
|
||||
|
||||
if (m_constantBuffer != 0) {
|
||||
for (const auto& binding : m_bindings) {
|
||||
if (binding.type != DescriptorType::CBV) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint32_t baseBindingPoint = ResolveBindingPoint(pipelineLayout, setIndex, binding);
|
||||
if (baseBindingPoint == UINT32_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < binding.count; ++i) {
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, baseBindingPoint + i, m_constantBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& binding : m_bindings) {
|
||||
const uint32_t baseBindingPoint = ResolveBindingPoint(pipelineLayout, setIndex, binding);
|
||||
if (baseBindingPoint == UINT32_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < binding.textureIds.size(); ++i) {
|
||||
const uint32_t bindingPoint = baseBindingPoint + static_cast<uint32_t>(i);
|
||||
const uint32_t textureId = binding.textureIds[i];
|
||||
if (textureId != 0) {
|
||||
if (binding.type == DescriptorType::UAV) {
|
||||
glBindImageTexture(bindingPoint, textureId, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
|
||||
} else if (binding.type != DescriptorType::Sampler) {
|
||||
glActiveTexture(GL_TEXTURE0 + bindingPoint);
|
||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
}
|
||||
}
|
||||
|
||||
if (binding.type == DescriptorType::Sampler && i < binding.samplerIds.size()) {
|
||||
const uint32_t samplerId = binding.samplerIds[i];
|
||||
if (samplerId != 0) {
|
||||
glBindSampler(bindingPoint, samplerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_bound = true;
|
||||
}
|
||||
|
||||
void OpenGLDescriptorSet::Unbind() {
|
||||
for (size_t i = 0; i < m_bindings.size(); ++i) {
|
||||
const auto& binding = m_bindings[i];
|
||||
|
||||
Reference in New Issue
Block a user