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:
@@ -91,12 +91,14 @@ add_library(XCEngine STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/RHIEnums.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/RHIFactory.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/RHIDescriptorPool.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/RHIDescriptorSet.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12Enums.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12Device.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12CommandQueue.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12CommandAllocator.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12CommandList.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12DescriptorHeap.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12DescriptorSet.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12Buffer.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12PipelineState.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12Sampler.h
|
||||
@@ -114,6 +116,7 @@ add_library(XCEngine STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12CommandAllocator.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12CommandList.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12DescriptorHeap.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12DescriptorSet.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12Buffer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12PipelineState.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12Sampler.cpp
|
||||
@@ -145,6 +148,8 @@ add_library(XCEngine STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLUniformBufferManager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLFramebuffer.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLResourceView.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLDescriptorPool.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLBuffer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLTexture.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLSampler.cpp
|
||||
@@ -163,6 +168,8 @@ add_library(XCEngine STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLUniformBufferManager.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLFramebuffer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLResourceView.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLDescriptorPool.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLDescriptorSet.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../tests/opengl/package/src/glad.c
|
||||
|
||||
# RHI Factory
|
||||
|
||||
@@ -67,6 +67,16 @@ public:
|
||||
void SetPipelineStateInternal(ID3D12PipelineState* pso);
|
||||
void SetPipelineLayout(D3D12PipelineLayout* layout);
|
||||
void SetRootSignature(ID3D12RootSignature* signature);
|
||||
void SetGraphicsDescriptorSets(
|
||||
uint32_t firstSet,
|
||||
uint32_t count,
|
||||
RHIDescriptorSet** descriptorSets,
|
||||
RHIPipelineLayout* pipelineLayout) override;
|
||||
void SetComputeDescriptorSets(
|
||||
uint32_t firstSet,
|
||||
uint32_t count,
|
||||
RHIDescriptorSet** descriptorSets,
|
||||
RHIPipelineLayout* pipelineLayout) override;
|
||||
void SetViewport(const Viewport& viewport) override;
|
||||
void SetViewports(uint32_t count, const Viewport* viewports) override;
|
||||
void SetScissorRect(const Rect& rect) override;
|
||||
@@ -78,6 +88,7 @@ public:
|
||||
|
||||
void SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIResourceView** buffers, const uint64_t* offsets, const uint32_t* strides) override;
|
||||
void SetVertexBuffersInternal(uint32_t startSlot, uint32_t count, const D3D12_VERTEX_BUFFER_VIEW* views);
|
||||
void SetVertexBuffer(uint32_t slot, ID3D12Resource* resource, uint64_t offset, uint32_t stride);
|
||||
void SetIndexBuffer(RHIResourceView* buffer, uint64_t offset) override;
|
||||
void SetIndexBuffer(ID3D12Resource* buffer, uint64_t offset, Format format);
|
||||
void SetIndexBufferInternal(ID3D12Resource* buffer, uint64_t offset, Format indexFormat);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <d3d12.h>
|
||||
#include <wrl/client.h>
|
||||
#include <vector>
|
||||
|
||||
#include "../RHIEnums.h"
|
||||
#include "../RHITypes.h"
|
||||
@@ -13,6 +14,8 @@ using Microsoft::WRL::ComPtr;
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
class D3D12DescriptorSet;
|
||||
|
||||
class D3D12DescriptorHeap : public RHIDescriptorPool {
|
||||
public:
|
||||
D3D12DescriptorHeap();
|
||||
@@ -23,6 +26,7 @@ public:
|
||||
|
||||
bool Initialize(const DescriptorPoolDesc& desc) override;
|
||||
|
||||
ID3D12Device* GetDevice() const { return m_device.Get(); }
|
||||
ID3D12DescriptorHeap* GetDescriptorHeap() const { return m_descriptorHeap.Get(); }
|
||||
|
||||
CPUDescriptorHandle GetCPUDescriptorHandle(uint32_t index);
|
||||
@@ -38,12 +42,17 @@ public:
|
||||
|
||||
static D3D12_DESCRIPTOR_HEAP_DESC CreateDesc(DescriptorHeapType type, uint32_t numDescriptors, bool shaderVisible = false);
|
||||
|
||||
RHIDescriptorSet* AllocateSet(const DescriptorSetLayoutDesc& layout) override;
|
||||
void FreeSet(RHIDescriptorSet* set) override;
|
||||
|
||||
private:
|
||||
ComPtr<ID3D12Device> m_device;
|
||||
ComPtr<ID3D12DescriptorHeap> m_descriptorHeap;
|
||||
DescriptorHeapType m_type;
|
||||
uint32_t m_numDescriptors;
|
||||
uint32_t m_descriptorSize;
|
||||
bool m_shaderVisible;
|
||||
std::vector<D3D12DescriptorSet*> m_allocatedSets;
|
||||
};
|
||||
|
||||
} // namespace RHI
|
||||
|
||||
45
engine/include/XCEngine/RHI/D3D12/D3D12DescriptorSet.h
Normal file
45
engine/include/XCEngine/RHI/D3D12/D3D12DescriptorSet.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d12.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
#include "../RHIEnums.h"
|
||||
#include "../RHITypes.h"
|
||||
#include "../RHIDescriptorSet.h"
|
||||
#include "D3D12Common.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
class D3D12DescriptorHeap;
|
||||
|
||||
class D3D12DescriptorSet : public RHIDescriptorSet {
|
||||
public:
|
||||
D3D12DescriptorSet();
|
||||
~D3D12DescriptorSet() override;
|
||||
|
||||
bool Initialize(D3D12DescriptorHeap* heap, uint32_t offset, uint32_t count, const DescriptorSetLayoutDesc& layout);
|
||||
void Shutdown() override;
|
||||
|
||||
void Update(uint32_t offset, RHIResourceView* view) override;
|
||||
void UpdateSampler(uint32_t offset, RHISampler* sampler) override;
|
||||
void* GetNativeHandle() override;
|
||||
|
||||
uint32_t GetBindingCount() const override { return m_bindingCount; }
|
||||
const DescriptorSetLayoutBinding* GetBindings() const override { return m_bindings; }
|
||||
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE GetGPUHandle(uint32_t index = 0) const;
|
||||
uint32_t GetOffset() const { return m_offset; }
|
||||
uint32_t GetCount() const { return m_count; }
|
||||
D3D12DescriptorHeap* GetHeap() const { return m_heap; }
|
||||
|
||||
private:
|
||||
D3D12DescriptorHeap* m_heap;
|
||||
uint32_t m_offset;
|
||||
uint32_t m_count;
|
||||
uint32_t m_bindingCount;
|
||||
DescriptorSetLayoutBinding* m_bindings;
|
||||
};
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
@@ -74,6 +74,9 @@ public:
|
||||
RHIFence* CreateFence(const FenceDesc& desc) override;
|
||||
RHISampler* CreateSampler(const SamplerDesc& desc) override;
|
||||
|
||||
RHIDescriptorPool* CreateDescriptorPool(const DescriptorPoolDesc& desc) override;
|
||||
RHIDescriptorSet* CreateDescriptorSet(RHIDescriptorPool* pool, const DescriptorSetLayoutDesc& layout) override;
|
||||
|
||||
RHIResourceView* CreateRenderTargetView(RHITexture* texture, const ResourceViewDesc& desc) override;
|
||||
RHIResourceView* CreateDepthStencilView(RHITexture* texture, const ResourceViewDesc& desc) override;
|
||||
RHIResourceView* CreateShaderResourceView(RHITexture* texture, const ResourceViewDesc& desc) override;
|
||||
|
||||
@@ -68,6 +68,16 @@ public:
|
||||
void SetGlobalTexture(const char* name, RHIResourceView* texture) override;
|
||||
|
||||
void SetPipelineState(RHIPipelineState* pipelineState) override;
|
||||
void SetGraphicsDescriptorSets(
|
||||
uint32_t firstSet,
|
||||
uint32_t count,
|
||||
RHIDescriptorSet** descriptorSets,
|
||||
RHIPipelineLayout* pipelineLayout) override;
|
||||
void SetComputeDescriptorSets(
|
||||
uint32_t firstSet,
|
||||
uint32_t count,
|
||||
RHIDescriptorSet** descriptorSets,
|
||||
RHIPipelineLayout* pipelineLayout) override;
|
||||
void SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIResourceView** buffers, const uint64_t* offsets, const uint32_t* strides) override;
|
||||
void SetIndexBuffer(RHIResourceView* buffer, uint64_t offset) override;
|
||||
|
||||
|
||||
39
engine/include/XCEngine/RHI/OpenGL/OpenGLDescriptorPool.h
Normal file
39
engine/include/XCEngine/RHI/OpenGL/OpenGLDescriptorPool.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
#include "../RHIEnums.h"
|
||||
#include "../RHIDescriptorPool.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
class OpenGLTextureUnitAllocator;
|
||||
|
||||
class OpenGLDescriptorPool : public RHIDescriptorPool {
|
||||
public:
|
||||
OpenGLDescriptorPool();
|
||||
~OpenGLDescriptorPool() override;
|
||||
|
||||
bool Initialize(const DescriptorPoolDesc& desc) override;
|
||||
void Shutdown() override;
|
||||
|
||||
void* GetNativeHandle() override { return this; }
|
||||
uint32_t GetDescriptorCount() const override { return m_maxSets; }
|
||||
DescriptorHeapType GetType() const override { return m_type; }
|
||||
|
||||
RHIDescriptorSet* AllocateSet(const DescriptorSetLayoutDesc& layout) override;
|
||||
void FreeSet(RHIDescriptorSet* set) override;
|
||||
|
||||
void SetTextureUnitAllocator(OpenGLTextureUnitAllocator* allocator) { m_textureUnitAllocator = allocator; }
|
||||
|
||||
private:
|
||||
DescriptorHeapType m_type;
|
||||
uint32_t m_maxSets;
|
||||
std::vector<class OpenGLDescriptorSet*> m_allocatedSets;
|
||||
class OpenGLTextureUnitAllocator* m_textureUnitAllocator;
|
||||
};
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
50
engine/include/XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h
Normal file
50
engine/include/XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
#include "../RHIEnums.h"
|
||||
#include "../RHIDescriptorSet.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
class OpenGLTextureUnitAllocator;
|
||||
|
||||
struct DescriptorBinding {
|
||||
uint32_t binding;
|
||||
DescriptorType type;
|
||||
uint32_t count;
|
||||
std::vector<uint32_t> textureUnits;
|
||||
std::vector<uint32_t> textureIds;
|
||||
std::vector<uint32_t> samplerIds;
|
||||
};
|
||||
|
||||
class OpenGLDescriptorSet : public RHIDescriptorSet {
|
||||
public:
|
||||
OpenGLDescriptorSet();
|
||||
~OpenGLDescriptorSet() override;
|
||||
|
||||
bool Initialize(OpenGLTextureUnitAllocator* allocator, uint32_t count, const DescriptorSetLayoutDesc& layout);
|
||||
void Shutdown() override;
|
||||
|
||||
void Update(uint32_t offset, RHIResourceView* view) override;
|
||||
void UpdateSampler(uint32_t offset, RHISampler* sampler) override;
|
||||
void* GetNativeHandle() override { return this; }
|
||||
|
||||
uint32_t GetBindingCount() const override { return static_cast<uint32_t>(m_bindings.size()); }
|
||||
const DescriptorSetLayoutBinding* GetBindings() const override { return m_layoutBindings; }
|
||||
|
||||
void Bind();
|
||||
uint32_t GetBindingPoint(uint32_t binding) const;
|
||||
|
||||
private:
|
||||
OpenGLTextureUnitAllocator* m_allocator;
|
||||
std::vector<DescriptorBinding> m_bindings;
|
||||
DescriptorSetLayoutBinding* m_layoutBindings;
|
||||
uint32_t m_bindingCount;
|
||||
bool m_bound;
|
||||
};
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
@@ -49,6 +49,9 @@ public:
|
||||
RHIFence* CreateFence(const FenceDesc& desc) override;
|
||||
RHISampler* CreateSampler(const SamplerDesc& desc) override;
|
||||
|
||||
RHIDescriptorPool* CreateDescriptorPool(const DescriptorPoolDesc& desc) override;
|
||||
RHIDescriptorSet* CreateDescriptorSet(RHIDescriptorPool* pool, const DescriptorSetLayoutDesc& layout) override;
|
||||
|
||||
RHIResourceView* CreateRenderTargetView(RHITexture* texture, const ResourceViewDesc& desc) override;
|
||||
RHIResourceView* CreateDepthStencilView(RHITexture* texture, const ResourceViewDesc& desc) override;
|
||||
RHIResourceView* CreateShaderResourceView(RHITexture* texture, const ResourceViewDesc& desc) override;
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
#include "RHIEnums.h"
|
||||
#include "RHIResource.h"
|
||||
#include "RHIResourceView.h"
|
||||
#include "RHIDescriptorSet.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
class RHIPipelineState;
|
||||
class RHIPipelineLayout;
|
||||
class RHIShader;
|
||||
|
||||
struct DepthStencilState {
|
||||
@@ -76,6 +78,16 @@ public:
|
||||
virtual void SetGlobalTexture(const char* name, RHIResourceView* texture) = 0;
|
||||
|
||||
virtual void SetPipelineState(RHIPipelineState* pso) = 0;
|
||||
virtual void SetGraphicsDescriptorSets(
|
||||
uint32_t firstSet,
|
||||
uint32_t count,
|
||||
RHIDescriptorSet** descriptorSets,
|
||||
RHIPipelineLayout* pipelineLayout) = 0;
|
||||
virtual void SetComputeDescriptorSets(
|
||||
uint32_t firstSet,
|
||||
uint32_t count,
|
||||
RHIDescriptorSet** descriptorSets,
|
||||
RHIPipelineLayout* pipelineLayout) = 0;
|
||||
virtual void SetPrimitiveTopology(PrimitiveTopology topology) = 0;
|
||||
virtual void SetViewport(const Viewport& viewport) = 0;
|
||||
virtual void SetViewports(uint32_t count, const Viewport* viewports) = 0;
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
class RHIDescriptorSet;
|
||||
struct DescriptorSetLayoutDesc;
|
||||
|
||||
struct DescriptorPoolDesc {
|
||||
void* device;
|
||||
DescriptorHeapType type;
|
||||
@@ -24,6 +27,9 @@ public:
|
||||
|
||||
virtual uint32_t GetDescriptorCount() const = 0;
|
||||
virtual DescriptorHeapType GetType() const = 0;
|
||||
|
||||
virtual RHIDescriptorSet* AllocateSet(const DescriptorSetLayoutDesc& layout) = 0;
|
||||
virtual void FreeSet(RHIDescriptorSet* set) = 0;
|
||||
};
|
||||
|
||||
} // namespace RHI
|
||||
|
||||
42
engine/include/XCEngine/RHI/RHIDescriptorSet.h
Normal file
42
engine/include/XCEngine/RHI/RHIDescriptorSet.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "RHIEnums.h"
|
||||
#include "RHITypes.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
class RHIDescriptorPool;
|
||||
class RHIResourceView;
|
||||
class RHISampler;
|
||||
|
||||
struct DescriptorSetLayoutBinding {
|
||||
uint32_t binding;
|
||||
DescriptorType type;
|
||||
uint32_t count;
|
||||
ShaderVisibility visibility = ShaderVisibility::All;
|
||||
};
|
||||
|
||||
struct DescriptorSetLayoutDesc {
|
||||
DescriptorSetLayoutBinding* bindings = nullptr;
|
||||
uint32_t bindingCount = 0;
|
||||
};
|
||||
|
||||
class RHIDescriptorSet {
|
||||
public:
|
||||
virtual ~RHIDescriptorSet() = default;
|
||||
|
||||
virtual void Shutdown() = 0;
|
||||
virtual void Update(uint32_t offset, RHIResourceView* view) = 0;
|
||||
virtual void UpdateSampler(uint32_t offset, RHISampler* sampler) = 0;
|
||||
virtual void* GetNativeHandle() = 0;
|
||||
|
||||
virtual uint32_t GetBindingCount() const = 0;
|
||||
virtual const DescriptorSetLayoutBinding* GetBindings() const = 0;
|
||||
|
||||
protected:
|
||||
RHIDescriptorSet() = default;
|
||||
};
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "RHITypes.h"
|
||||
#include "RHICapabilities.h"
|
||||
#include "RHIDescriptorPool.h"
|
||||
#include "RHIDescriptorSet.h"
|
||||
#include <string>
|
||||
|
||||
namespace XCEngine {
|
||||
@@ -37,6 +39,9 @@ public:
|
||||
virtual RHIFence* CreateFence(const FenceDesc& desc) = 0;
|
||||
virtual RHISampler* CreateSampler(const SamplerDesc& desc) = 0;
|
||||
|
||||
virtual RHIDescriptorPool* CreateDescriptorPool(const DescriptorPoolDesc& desc) = 0;
|
||||
virtual RHIDescriptorSet* CreateDescriptorSet(RHIDescriptorPool* pool, const DescriptorSetLayoutDesc& layout) = 0;
|
||||
|
||||
virtual RHIResourceView* CreateRenderTargetView(RHITexture* texture, const ResourceViewDesc& desc) = 0;
|
||||
virtual RHIResourceView* CreateDepthStencilView(RHITexture* texture, const ResourceViewDesc& desc) = 0;
|
||||
virtual RHIResourceView* CreateShaderResourceView(RHITexture* texture, const ResourceViewDesc& desc) = 0;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "XCEngine/RHI/D3D12/D3D12PipelineLayout.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12RenderPass.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12Framebuffer.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorSet.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
@@ -214,6 +215,56 @@ void D3D12CommandList::SetPipelineState(ID3D12PipelineState* pso) {
|
||||
SetPipelineStateInternal(pso);
|
||||
}
|
||||
|
||||
void D3D12CommandList::SetGraphicsDescriptorSets(
|
||||
uint32_t firstSet,
|
||||
uint32_t count,
|
||||
RHIDescriptorSet** descriptorSets,
|
||||
RHIPipelineLayout* pipelineLayout) {
|
||||
if (pipelineLayout == nullptr || descriptorSets == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
D3D12PipelineLayout* d3d12Layout = static_cast<D3D12PipelineLayout*>(pipelineLayout);
|
||||
SetPipelineLayout(d3d12Layout);
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
if (descriptorSets[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandle();
|
||||
|
||||
uint32_t rootIndex = firstSet + i;
|
||||
SetGraphicsRootDescriptorTable(rootIndex, gpuHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12CommandList::SetComputeDescriptorSets(
|
||||
uint32_t firstSet,
|
||||
uint32_t count,
|
||||
RHIDescriptorSet** descriptorSets,
|
||||
RHIPipelineLayout* pipelineLayout) {
|
||||
if (pipelineLayout == nullptr || descriptorSets == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
D3D12PipelineLayout* d3d12Layout = static_cast<D3D12PipelineLayout*>(pipelineLayout);
|
||||
SetPipelineLayout(d3d12Layout);
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
if (descriptorSets[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
D3D12DescriptorSet* d3d12Set = static_cast<D3D12DescriptorSet*>(descriptorSets[i]);
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = d3d12Set->GetGPUHandle();
|
||||
|
||||
uint32_t rootIndex = firstSet + i;
|
||||
m_commandList->SetComputeRootDescriptorTable(rootIndex, gpuHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12CommandList::TransitionBarrierInternal(ID3D12Resource* resource, ResourceStates stateBefore, ResourceStates stateAfter, uint32_t subresource) {
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
@@ -434,6 +485,14 @@ void D3D12CommandList::SetVertexBuffersInternal(uint32_t startSlot, uint32_t cou
|
||||
m_commandList->IASetVertexBuffers(startSlot, count, views);
|
||||
}
|
||||
|
||||
void D3D12CommandList::SetVertexBuffer(uint32_t slot, ID3D12Resource* resource, uint64_t offset, uint32_t stride) {
|
||||
D3D12_VERTEX_BUFFER_VIEW view = {};
|
||||
view.BufferLocation = resource->GetGPUVirtualAddress() + offset;
|
||||
view.SizeInBytes = static_cast<UINT>(resource->GetDesc().Width) - static_cast<UINT>(offset);
|
||||
view.StrideInBytes = stride;
|
||||
SetVertexBuffersInternal(slot, 1, &view);
|
||||
}
|
||||
|
||||
void D3D12CommandList::SetIndexBuffer(RHIResourceView* buffer, uint64_t offset) {
|
||||
if (!buffer || !buffer->IsValid()) return;
|
||||
D3D12ResourceView* view = static_cast<D3D12ResourceView*>(buffer);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorHeap.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorSet.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
@@ -88,5 +89,41 @@ D3D12_DESCRIPTOR_HEAP_DESC D3D12DescriptorHeap::CreateDesc(DescriptorHeapType ty
|
||||
return desc;
|
||||
}
|
||||
|
||||
RHIDescriptorSet* D3D12DescriptorHeap::AllocateSet(const DescriptorSetLayoutDesc& layout) {
|
||||
uint32_t requiredDescriptors = 0;
|
||||
for (uint32_t i = 0; i < layout.bindingCount; ++i) {
|
||||
requiredDescriptors += layout.bindings[i].count;
|
||||
}
|
||||
|
||||
if (m_allocatedSets.size() >= m_numDescriptors) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
D3D12DescriptorSet* newSet = new D3D12DescriptorSet();
|
||||
uint32_t offset = static_cast<uint32_t>(m_allocatedSets.size());
|
||||
|
||||
if (!newSet->Initialize(this, offset, requiredDescriptors, layout)) {
|
||||
delete newSet;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_allocatedSets.push_back(newSet);
|
||||
return newSet;
|
||||
}
|
||||
|
||||
void D3D12DescriptorHeap::FreeSet(RHIDescriptorSet* set) {
|
||||
if (set == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto it = m_allocatedSets.begin(); it != m_allocatedSets.end(); ++it) {
|
||||
if (*it == set) {
|
||||
m_allocatedSets.erase(it);
|
||||
delete set;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
|
||||
69
engine/src/RHI/D3D12/D3D12DescriptorSet.cpp
Normal file
69
engine/src/RHI/D3D12/D3D12DescriptorSet.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorSet.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorHeap.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
D3D12DescriptorSet::D3D12DescriptorSet()
|
||||
: m_heap(nullptr)
|
||||
, m_offset(0)
|
||||
, m_count(0)
|
||||
, m_bindingCount(0)
|
||||
, m_bindings(nullptr) {
|
||||
}
|
||||
|
||||
D3D12DescriptorSet::~D3D12DescriptorSet() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool D3D12DescriptorSet::Initialize(D3D12DescriptorHeap* heap, uint32_t offset, uint32_t count, const DescriptorSetLayoutDesc& layout) {
|
||||
m_heap = heap;
|
||||
m_offset = offset;
|
||||
m_count = count;
|
||||
m_bindingCount = layout.bindingCount;
|
||||
|
||||
if (layout.bindingCount > 0 && layout.bindings != nullptr) {
|
||||
m_bindings = new DescriptorSetLayoutBinding[layout.bindingCount];
|
||||
for (uint32_t i = 0; i < layout.bindingCount; ++i) {
|
||||
m_bindings[i] = layout.bindings[i];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void D3D12DescriptorSet::Shutdown() {
|
||||
m_heap = nullptr;
|
||||
m_offset = 0;
|
||||
m_count = 0;
|
||||
m_bindingCount = 0;
|
||||
if (m_bindings != nullptr) {
|
||||
delete[] m_bindings;
|
||||
m_bindings = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12DescriptorSet::Update(uint32_t offset, RHIResourceView* view) {
|
||||
(void)offset;
|
||||
(void)view;
|
||||
}
|
||||
|
||||
void D3D12DescriptorSet::UpdateSampler(uint32_t offset, RHISampler* sampler) {
|
||||
(void)offset;
|
||||
(void)sampler;
|
||||
}
|
||||
|
||||
void* D3D12DescriptorSet::GetNativeHandle() {
|
||||
return this;
|
||||
}
|
||||
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE D3D12DescriptorSet::GetGPUHandle(uint32_t index) const {
|
||||
if (m_heap == nullptr) {
|
||||
return D3D12_GPU_DESCRIPTOR_HANDLE{0};
|
||||
}
|
||||
GPUDescriptorHandle handle = m_heap->GetGPUDescriptorHandle(m_offset + index);
|
||||
return D3D12_GPU_DESCRIPTOR_HANDLE{ handle.ptr };
|
||||
}
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "XCEngine/RHI/D3D12/D3D12CommandAllocator.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12Fence.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorHeap.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorSet.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12QueryHeap.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12RootSignature.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12PipelineLayout.h"
|
||||
@@ -324,6 +325,24 @@ RHISampler* D3D12Device::CreateSampler(const SamplerDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHIDescriptorPool* D3D12Device::CreateDescriptorPool(const DescriptorPoolDesc& desc) {
|
||||
auto* pool = new D3D12DescriptorHeap();
|
||||
DescriptorPoolDesc poolDesc = desc;
|
||||
poolDesc.device = m_device.Get();
|
||||
if (pool->Initialize(poolDesc)) {
|
||||
return pool;
|
||||
}
|
||||
delete pool;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHIDescriptorSet* D3D12Device::CreateDescriptorSet(RHIDescriptorPool* pool, const DescriptorSetLayoutDesc& layout) {
|
||||
if (pool == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return pool->AllocateSet(layout);
|
||||
}
|
||||
|
||||
RHIFence* D3D12Device::CreateFence(const FenceDesc& desc) {
|
||||
auto* fence = new D3D12Fence();
|
||||
if (fence->Initialize(m_device.Get(), desc.initialValue)) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLShader.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLFramebuffer.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLRenderPass.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h"
|
||||
#include <glad/glad.h>
|
||||
|
||||
namespace XCEngine {
|
||||
@@ -650,6 +651,38 @@ void OpenGLCommandList::SetPipelineState(RHIPipelineState* pipelineState) {
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLCommandList::SetGraphicsDescriptorSets(
|
||||
uint32_t firstSet,
|
||||
uint32_t count,
|
||||
RHIDescriptorSet** descriptorSets,
|
||||
RHIPipelineLayout* pipelineLayout) {
|
||||
(void)firstSet;
|
||||
(void)pipelineLayout;
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
if (descriptorSets[i] != nullptr) {
|
||||
OpenGLDescriptorSet* glSet = static_cast<OpenGLDescriptorSet*>(descriptorSets[i]);
|
||||
glSet->Bind();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLCommandList::SetComputeDescriptorSets(
|
||||
uint32_t firstSet,
|
||||
uint32_t count,
|
||||
RHIDescriptorSet** descriptorSets,
|
||||
RHIPipelineLayout* pipelineLayout) {
|
||||
(void)firstSet;
|
||||
(void)pipelineLayout;
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
if (descriptorSets[i] != nullptr) {
|
||||
OpenGLDescriptorSet* glSet = static_cast<OpenGLDescriptorSet*>(descriptorSets[i]);
|
||||
glSet->Bind();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLCommandList::SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIResourceView** buffers, const uint64_t* offsets, const uint32_t* strides) {
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if (!buffers[i]) continue;
|
||||
|
||||
62
engine/src/RHI/OpenGL/OpenGLDescriptorPool.cpp
Normal file
62
engine/src/RHI/OpenGL/OpenGLDescriptorPool.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorPool.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLTextureUnitAllocator.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
OpenGLDescriptorPool::OpenGLDescriptorPool()
|
||||
: m_type(DescriptorHeapType::CBV_SRV_UAV)
|
||||
, m_maxSets(0)
|
||||
, m_textureUnitAllocator(nullptr) {
|
||||
}
|
||||
|
||||
OpenGLDescriptorPool::~OpenGLDescriptorPool() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool OpenGLDescriptorPool::Initialize(const DescriptorPoolDesc& desc) {
|
||||
m_type = desc.type;
|
||||
m_maxSets = desc.descriptorCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGLDescriptorPool::Shutdown() {
|
||||
for (auto* set : m_allocatedSets) {
|
||||
delete set;
|
||||
}
|
||||
m_allocatedSets.clear();
|
||||
m_textureUnitAllocator = nullptr;
|
||||
}
|
||||
|
||||
RHIDescriptorSet* OpenGLDescriptorPool::AllocateSet(const DescriptorSetLayoutDesc& layout) {
|
||||
if (m_allocatedSets.size() >= m_maxSets) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OpenGLDescriptorSet* newSet = new OpenGLDescriptorSet();
|
||||
if (!newSet->Initialize(m_textureUnitAllocator, layout.bindingCount, layout)) {
|
||||
delete newSet;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_allocatedSets.push_back(newSet);
|
||||
return newSet;
|
||||
}
|
||||
|
||||
void OpenGLDescriptorPool::FreeSet(RHIDescriptorSet* set) {
|
||||
if (set == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto it = m_allocatedSets.begin(); it != m_allocatedSets.end(); ++it) {
|
||||
if (*it == set) {
|
||||
m_allocatedSets.erase(it);
|
||||
delete set;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
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
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLUniformBufferManager.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLFramebuffer.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorPool.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h"
|
||||
#include "XCEngine/Debug/Logger.h"
|
||||
|
||||
typedef const char* (WINAPI* PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC hdc);
|
||||
@@ -384,6 +386,23 @@ RHISampler* OpenGLDevice::CreateSampler(const SamplerDesc& desc) {
|
||||
return sampler;
|
||||
}
|
||||
|
||||
RHIDescriptorPool* OpenGLDevice::CreateDescriptorPool(const DescriptorPoolDesc& desc) {
|
||||
auto* pool = new OpenGLDescriptorPool();
|
||||
if (pool->Initialize(desc)) {
|
||||
pool->SetTextureUnitAllocator(m_textureUnitAllocator.get());
|
||||
return pool;
|
||||
}
|
||||
delete pool;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHIDescriptorSet* OpenGLDevice::CreateDescriptorSet(RHIDescriptorPool* pool, const DescriptorSetLayoutDesc& layout) {
|
||||
if (pool == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return pool->AllocateSet(layout);
|
||||
}
|
||||
|
||||
RHIResourceView* OpenGLDevice::CreateRenderTargetView(RHITexture* texture, const ResourceViewDesc& desc) {
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
|
||||
Reference in New Issue
Block a user