Add RHI vertex and index buffer views

This commit is contained in:
2026-03-25 23:07:22 +08:00
parent 268daf7bc9
commit aaf9cce418
14 changed files with 342 additions and 19 deletions

View File

@@ -408,9 +408,10 @@ void D3D12CommandList::SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIR
for (uint32_t i = 0; i < count; ++i) {
if (buffers[i] && buffers[i]->IsValid()) {
D3D12ResourceView* view = static_cast<D3D12ResourceView*>(buffers[i]);
views[i].BufferLocation = view->GetResource()->GetGPUVirtualAddress() + offsets[i];
views[i].StrideInBytes = strides[i];
views[i].SizeInBytes = static_cast<UINT>(view->GetResource()->GetDesc().Width) - static_cast<UINT>(offsets[i]);
const uint32_t stride = strides[i] > 0 ? strides[i] : view->GetBufferStride();
views[i].BufferLocation = view->GetBufferLocation() + offsets[i];
views[i].StrideInBytes = stride;
views[i].SizeInBytes = view->GetBufferSize() > offsets[i] ? view->GetBufferSize() - static_cast<UINT>(offsets[i]) : 0;
}
}
SetVertexBuffersInternal(startSlot, count, views.data());
@@ -431,7 +432,8 @@ void D3D12CommandList::SetVertexBuffer(uint32_t slot, ID3D12Resource* resource,
void D3D12CommandList::SetIndexBuffer(RHIResourceView* buffer, uint64_t offset) {
if (!buffer || !buffer->IsValid()) return;
D3D12ResourceView* view = static_cast<D3D12ResourceView*>(buffer);
SetIndexBufferInternal(view->GetResource(), offset, Format::R32_UInt);
const Format format = view->GetFormat() == Format::Unknown ? Format::R32_UInt : view->GetFormat();
SetIndexBufferInternal(view->GetResource(), view->GetBufferOffset() + offset, format);
}
void D3D12CommandList::SetIndexBuffer(ID3D12Resource* buffer, uint64_t offset, Format format) {

View File

@@ -19,6 +19,7 @@
#include "XCEngine/RHI/D3D12/D3D12Framebuffer.h"
#include <stdio.h>
#include <memory>
#include <string>
#ifdef _DEBUG
#include <dxgidebug.h>
@@ -27,6 +28,19 @@
namespace XCEngine {
namespace RHI {
namespace {
std::string NarrowAscii(const std::wstring& value) {
std::string result;
result.reserve(value.size());
for (wchar_t ch : value) {
result.push_back(static_cast<char>(ch));
}
return result;
}
} // namespace
D3D12Device::D3D12Device()
: m_isDeviceRemoved(false)
, m_initialized(false)
@@ -293,14 +307,16 @@ RHITexture* D3D12Device::CreateTexture(const TextureDesc& desc) {
RHIShader* D3D12Device::CreateShader(const ShaderCompileDesc& desc) {
auto* shader = new D3D12Shader();
const char* entryPoint = desc.entryPoint.empty() ? nullptr : reinterpret_cast<const char*>(desc.entryPoint.c_str());
const char* profile = desc.profile.empty() ? nullptr : reinterpret_cast<const char*>(desc.profile.c_str());
const std::string entryPoint = NarrowAscii(desc.entryPoint);
const std::string profile = NarrowAscii(desc.profile);
const char* entryPointPtr = entryPoint.empty() ? nullptr : entryPoint.c_str();
const char* profilePtr = profile.empty() ? nullptr : profile.c_str();
bool success = false;
if (!desc.source.empty()) {
success = shader->Compile(desc.source.data(), desc.source.size(), entryPoint, profile);
success = shader->Compile(desc.source.data(), desc.source.size(), entryPointPtr, profilePtr);
} else if (!desc.fileName.empty()) {
success = shader->CompileFromFile(desc.fileName.c_str(), entryPoint, profile);
success = shader->CompileFromFile(desc.fileName.c_str(), entryPointPtr, profilePtr);
}
if (success) {
@@ -386,6 +402,36 @@ RHIFence* D3D12Device::CreateFence(const FenceDesc& desc) {
return nullptr;
}
RHIResourceView* D3D12Device::CreateVertexBufferView(RHIBuffer* buffer, const ResourceViewDesc& desc) {
if (!buffer) {
return nullptr;
}
auto* view = new D3D12ResourceView();
view->InitializeAsVertexBuffer(static_cast<D3D12Buffer*>(buffer), desc);
if (!view->IsValid()) {
delete view;
return nullptr;
}
return view;
}
RHIResourceView* D3D12Device::CreateIndexBufferView(RHIBuffer* buffer, const ResourceViewDesc& desc) {
if (!buffer) {
return nullptr;
}
auto* view = new D3D12ResourceView();
view->InitializeAsIndexBuffer(static_cast<D3D12Buffer*>(buffer), desc);
if (!view->IsValid()) {
delete view;
return nullptr;
}
return view;
}
RHISwapChain* D3D12Device::CreateSwapChain(const SwapChainDesc& desc, RHICommandQueue* presentQueue) {
if (presentQueue == nullptr) {
return nullptr;

View File

@@ -1,4 +1,5 @@
#include "XCEngine/RHI/D3D12/D3D12ResourceView.h"
#include "XCEngine/RHI/D3D12/D3D12Buffer.h"
#include "XCEngine/RHI/D3D12/D3D12DescriptorHeap.h"
namespace XCEngine {
@@ -12,7 +13,11 @@ D3D12ResourceView::D3D12ResourceView()
, m_resource(nullptr)
, m_heap(nullptr)
, m_slotIndex(0)
, m_ownedHeap(nullptr) {
, m_ownedHeap(nullptr)
, m_bufferLocation(0)
, m_bufferOffset(0)
, m_bufferSize(0)
, m_bufferStride(0) {
}
D3D12ResourceView::~D3D12ResourceView() {
@@ -28,14 +33,30 @@ void D3D12ResourceView::Shutdown() {
}
m_heap = nullptr;
m_slotIndex = 0;
m_bufferLocation = 0;
m_bufferOffset = 0;
m_bufferSize = 0;
m_bufferStride = 0;
}
void* D3D12ResourceView::GetNativeHandle() {
return reinterpret_cast<void*>(m_handle.ptr);
switch (m_viewType) {
case ResourceViewType::VertexBuffer:
case ResourceViewType::IndexBuffer:
return m_resource;
default:
return reinterpret_cast<void*>(m_handle.ptr);
}
}
bool D3D12ResourceView::IsValid() const {
return m_handle.ptr != 0 && m_resource != nullptr;
switch (m_viewType) {
case ResourceViewType::VertexBuffer:
case ResourceViewType::IndexBuffer:
return m_resource != nullptr;
default:
return m_handle.ptr != 0 && m_resource != nullptr;
}
}
void D3D12ResourceView::InitializeAsRenderTarget(ID3D12Device* device, ID3D12Resource* resource,
@@ -113,6 +134,36 @@ void D3D12ResourceView::InitializeAsConstantBuffer(ID3D12Device* device, ID3D12R
device->CreateConstantBufferView(desc, m_handle);
}
void D3D12ResourceView::InitializeAsVertexBuffer(D3D12Buffer* buffer, const ResourceViewDesc& desc) {
if (buffer == nullptr) {
return;
}
m_viewType = ResourceViewType::VertexBuffer;
m_format = Format::Unknown;
m_dimension = ResourceViewDimension::Buffer;
m_resource = buffer->GetResource();
m_bufferOffset = desc.bufferLocation;
m_bufferLocation = buffer->GetGPUVirtualAddress() + desc.bufferLocation;
m_bufferSize = static_cast<uint32_t>(buffer->GetSize() - desc.bufferLocation);
m_bufferStride = desc.structureByteStride > 0 ? desc.structureByteStride : buffer->GetStride();
}
void D3D12ResourceView::InitializeAsIndexBuffer(D3D12Buffer* buffer, const ResourceViewDesc& desc) {
if (buffer == nullptr) {
return;
}
m_viewType = ResourceViewType::IndexBuffer;
m_format = desc.format != 0 ? static_cast<Format>(desc.format) : Format::R32_UInt;
m_dimension = ResourceViewDimension::Buffer;
m_resource = buffer->GetResource();
m_bufferOffset = desc.bufferLocation;
m_bufferLocation = buffer->GetGPUVirtualAddress() + desc.bufferLocation;
m_bufferSize = static_cast<uint32_t>(buffer->GetSize() - desc.bufferLocation);
m_bufferStride = buffer->GetStride();
}
GPUDescriptorHandle D3D12ResourceView::GetGPUHandle() const {
if (m_heap) {
return m_heap->GetGPUDescriptorHandle(m_slotIndex);
@@ -162,4 +213,4 @@ void D3D12ResourceView::SetOwnedHeap(std::unique_ptr<D3D12DescriptorHeap> heap)
}
} // namespace RHI
} // namespace XCEngine
} // namespace XCEngine

View File

@@ -641,7 +641,9 @@ void OpenGLCommandList::SetVertexBuffers(uint32_t startSlot, uint32_t count, RHI
GLuint glBuffer = view->GetBuffer();
glBindBuffer(GL_ARRAY_BUFFER, glBuffer);
glEnableVertexAttribArray(startSlot + i);
glVertexAttribPointer(startSlot + i, strides[i] / sizeof(float), GL_FLOAT, GL_FALSE, strides[i], reinterpret_cast<void*>(static_cast<uintptr_t>(offsets[i])));
const uint32_t stride = strides[i] > 0 ? strides[i] : view->GetBufferStride();
const uint64_t offset = view->GetBufferOffset() + offsets[i];
glVertexAttribPointer(startSlot + i, stride / sizeof(float), GL_FLOAT, GL_FALSE, stride, reinterpret_cast<void*>(static_cast<uintptr_t>(offset)));
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}

View File

@@ -468,6 +468,34 @@ RHIDescriptorSet* OpenGLDevice::CreateDescriptorSet(RHIDescriptorPool* pool, con
return pool->AllocateSet(layout);
}
RHIResourceView* OpenGLDevice::CreateVertexBufferView(RHIBuffer* buffer, const ResourceViewDesc& desc) {
if (!buffer) {
return nullptr;
}
auto* view = new OpenGLResourceView();
if (!view->InitializeAsVertexBuffer(static_cast<OpenGLBuffer*>(buffer), desc)) {
delete view;
return nullptr;
}
return view;
}
RHIResourceView* OpenGLDevice::CreateIndexBufferView(RHIBuffer* buffer, const ResourceViewDesc& desc) {
if (!buffer) {
return nullptr;
}
auto* view = new OpenGLResourceView();
if (!view->InitializeAsIndexBuffer(static_cast<OpenGLBuffer*>(buffer), desc)) {
delete view;
return nullptr;
}
return view;
}
RHIResourceView* OpenGLDevice::CreateRenderTargetView(RHITexture* texture, const ResourceViewDesc& desc) {
if (!texture) {
return nullptr;

View File

@@ -21,7 +21,10 @@ OpenGLResourceView::OpenGLResourceView()
, m_buffer(nullptr)
, m_framebuffer(nullptr)
, m_textureUnitAllocator(nullptr)
, m_uniformBufferManager(nullptr) {
, m_uniformBufferManager(nullptr)
, m_bufferOffset(0)
, m_bufferSize(0)
, m_bufferStride(0) {
}
OpenGLResourceView::~OpenGLResourceView() {
@@ -47,10 +50,16 @@ void OpenGLResourceView::Shutdown() {
m_framebufferID = 0;
m_texture = nullptr;
m_buffer = nullptr;
m_bufferOffset = 0;
m_bufferSize = 0;
m_bufferStride = 0;
}
void* OpenGLResourceView::GetNativeHandle() {
switch (m_viewType) {
case ResourceViewType::VertexBuffer:
case ResourceViewType::IndexBuffer:
return reinterpret_cast<void*>(static_cast<uintptr_t>(m_buffer ? m_buffer->GetID() : 0));
case ResourceViewType::RenderTarget:
case ResourceViewType::DepthStencil:
return reinterpret_cast<void*>(static_cast<uintptr_t>(m_framebufferID));
@@ -66,6 +75,9 @@ void* OpenGLResourceView::GetNativeHandle() {
bool OpenGLResourceView::IsValid() const {
switch (m_viewType) {
case ResourceViewType::VertexBuffer:
case ResourceViewType::IndexBuffer:
return m_buffer != nullptr && m_buffer->GetID() != 0;
case ResourceViewType::RenderTarget:
case ResourceViewType::DepthStencil:
return m_framebufferID != 0;
@@ -186,6 +198,40 @@ bool OpenGLResourceView::InitializeAsConstantBuffer(
return true;
}
bool OpenGLResourceView::InitializeAsVertexBuffer(
OpenGLBuffer* buffer,
const ResourceViewDesc& desc) {
if (!buffer) {
return false;
}
m_viewType = ResourceViewType::VertexBuffer;
m_format = Format::Unknown;
m_dimension = ResourceViewDimension::Buffer;
m_buffer = buffer;
m_bufferOffset = desc.bufferLocation;
m_bufferSize = static_cast<uint32_t>(buffer->GetSize());
m_bufferStride = desc.structureByteStride > 0 ? desc.structureByteStride : buffer->GetStride();
return true;
}
bool OpenGLResourceView::InitializeAsIndexBuffer(
OpenGLBuffer* buffer,
const ResourceViewDesc& desc) {
if (!buffer) {
return false;
}
m_viewType = ResourceViewType::IndexBuffer;
m_format = desc.format != 0 ? static_cast<Format>(desc.format) : Format::R32_UInt;
m_dimension = ResourceViewDimension::Buffer;
m_buffer = buffer;
m_bufferOffset = desc.bufferLocation;
m_bufferSize = static_cast<uint32_t>(buffer->GetSize());
m_bufferStride = buffer->GetStride();
return true;
}
unsigned int OpenGLResourceView::GetFramebuffer() const {
return m_framebuffer ? m_framebuffer->GetFramebuffer() : 0;
}
@@ -199,4 +245,4 @@ unsigned int OpenGLResourceView::GetBuffer() const {
}
} // namespace RHI
} // namespace XCEngine
} // namespace XCEngine