Files
XCEngine/tests/RHI/unit/test_descriptor_set.cpp

525 lines
15 KiB
C++
Raw Normal View History

#include "fixtures/RHITestFixture.h"
#include "XCEngine/RHI/D3D12/D3D12DescriptorSet.h"
#include "XCEngine/RHI/RHIDescriptorPool.h"
#include "XCEngine/RHI/RHIDescriptorSet.h"
#include "XCEngine/RHI/RHIBuffer.h"
#include "XCEngine/RHI/RHISampler.h"
#include "XCEngine/RHI/RHIResourceView.h"
#include "XCEngine/RHI/RHITexture.h"
using namespace XCEngine::RHI;
TEST_P(RHITestFixture, DescriptorSet_Allocate_Basic) {
DescriptorPoolDesc poolDesc = {};
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
poolDesc.descriptorCount = 10;
poolDesc.shaderVisible = true;
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
if (pool == nullptr) {
return;
}
DescriptorSetLayoutDesc layoutDesc = {};
layoutDesc.bindings = nullptr;
layoutDesc.bindingCount = 0;
RHIDescriptorSet* set = pool->AllocateSet(layoutDesc);
if (set != nullptr) {
EXPECT_GE(set->GetBindingCount(), 0u);
set->Shutdown();
delete set;
}
pool->Shutdown();
delete pool;
}
TEST_P(RHITestFixture, DescriptorSet_Update_ResourceView) {
DescriptorPoolDesc poolDesc = {};
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
poolDesc.descriptorCount = 10;
poolDesc.shaderVisible = true;
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
if (pool == nullptr) {
return;
}
TextureDesc texDesc = {};
texDesc.width = 256;
texDesc.height = 256;
texDesc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
texDesc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
texDesc.sampleCount = 1;
RHITexture* texture = GetDevice()->CreateTexture(texDesc);
if (texture == nullptr) {
pool->Shutdown();
delete pool;
return;
}
RHIResourceView* srv = GetDevice()->CreateShaderResourceView(texture, {});
if (srv == nullptr) {
texture->Shutdown();
delete texture;
pool->Shutdown();
delete pool;
return;
}
DescriptorSetLayoutDesc layoutDesc = {};
layoutDesc.bindingCount = 1;
DescriptorSetLayoutBinding binding = {};
binding.binding = 0;
binding.type = static_cast<uint32_t>(DescriptorType::SRV);
binding.count = 1;
layoutDesc.bindings = &binding;
RHIDescriptorSet* set = pool->AllocateSet(layoutDesc);
if (set != nullptr) {
set->Update(0, srv);
set->Shutdown();
delete set;
}
srv->Shutdown();
delete srv;
texture->Shutdown();
delete texture;
pool->Shutdown();
delete pool;
}
TEST_P(RHITestFixture, DescriptorSet_UpdateSampler) {
DescriptorPoolDesc poolDesc = {};
poolDesc.type = DescriptorHeapType::Sampler;
poolDesc.descriptorCount = 10;
poolDesc.shaderVisible = true;
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
if (pool == nullptr) {
return;
}
SamplerDesc samplerDesc = {};
samplerDesc.filter = static_cast<uint32_t>(FilterMode::Linear);
samplerDesc.addressU = static_cast<uint32_t>(TextureAddressMode::Wrap);
samplerDesc.addressV = static_cast<uint32_t>(TextureAddressMode::Wrap);
samplerDesc.addressW = static_cast<uint32_t>(TextureAddressMode::Wrap);
RHISampler* sampler = GetDevice()->CreateSampler(samplerDesc);
if (sampler == nullptr) {
pool->Shutdown();
delete pool;
return;
}
DescriptorSetLayoutDesc layoutDesc = {};
layoutDesc.bindingCount = 1;
DescriptorSetLayoutBinding binding = {};
binding.binding = 0;
binding.type = static_cast<uint32_t>(DescriptorType::Sampler);
binding.count = 1;
layoutDesc.bindings = &binding;
RHIDescriptorSet* set = pool->AllocateSet(layoutDesc);
if (set != nullptr) {
set->UpdateSampler(0, sampler);
set->Shutdown();
delete set;
}
sampler->Shutdown();
delete sampler;
pool->Shutdown();
delete pool;
}
TEST_P(RHITestFixture, DescriptorSet_WriteConstant) {
DescriptorPoolDesc poolDesc = {};
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
poolDesc.descriptorCount = 10;
poolDesc.shaderVisible = false;
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
if (pool == nullptr) {
return;
}
DescriptorSetLayoutDesc layoutDesc = {};
layoutDesc.bindingCount = 1;
DescriptorSetLayoutBinding binding = {};
binding.binding = 0;
binding.type = static_cast<uint32_t>(DescriptorType::CBV);
binding.count = 1;
layoutDesc.bindings = &binding;
RHIDescriptorSet* set = pool->AllocateSet(layoutDesc);
if (set != nullptr) {
float testData[16] = { 1.0f, 2.0f, 3.0f, 4.0f };
set->WriteConstant(0, testData, sizeof(testData));
void* constantData = set->GetConstantBufferData();
EXPECT_NE(constantData, nullptr);
size_t constantSize = set->GetConstantBufferSize();
EXPECT_GE(constantSize, sizeof(testData));
set->Shutdown();
delete set;
}
pool->Shutdown();
delete pool;
}
TEST_P(RHITestFixture, DescriptorSet_WriteConstant_PartialUpdate) {
DescriptorPoolDesc poolDesc = {};
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
poolDesc.descriptorCount = 10;
poolDesc.shaderVisible = false;
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
if (pool == nullptr) {
return;
}
DescriptorSetLayoutDesc layoutDesc = {};
layoutDesc.bindingCount = 1;
DescriptorSetLayoutBinding binding = {};
binding.binding = 0;
binding.type = static_cast<uint32_t>(DescriptorType::CBV);
binding.count = 1;
layoutDesc.bindings = &binding;
RHIDescriptorSet* set = pool->AllocateSet(layoutDesc);
if (set != nullptr) {
float offsetData[4] = { 100.0f, 200.0f };
set->WriteConstant(0, offsetData, sizeof(offsetData), 0);
EXPECT_TRUE(set->IsConstantDirty());
set->MarkConstantClean();
EXPECT_FALSE(set->IsConstantDirty());
set->Shutdown();
delete set;
}
pool->Shutdown();
delete pool;
}
TEST_P(RHITestFixture, DescriptorSet_Bind_Unbind) {
DescriptorPoolDesc poolDesc = {};
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
poolDesc.descriptorCount = 10;
poolDesc.shaderVisible = true;
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
if (pool == nullptr) {
return;
}
DescriptorSetLayoutDesc layoutDesc = {};
layoutDesc.bindingCount = 0;
RHIDescriptorSet* set = pool->AllocateSet(layoutDesc);
if (set != nullptr) {
set->Bind();
set->Unbind();
set->Shutdown();
delete set;
}
pool->Shutdown();
delete pool;
}
TEST_P(RHITestFixture, DescriptorSet_GetBindings) {
DescriptorPoolDesc poolDesc = {};
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
poolDesc.descriptorCount = 10;
poolDesc.shaderVisible = true;
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
if (pool == nullptr) {
return;
}
DescriptorSetLayoutDesc layoutDesc = {};
layoutDesc.bindingCount = 2;
DescriptorSetLayoutBinding bindings[2] = {};
bindings[0].binding = 0;
bindings[0].type = static_cast<uint32_t>(DescriptorType::CBV);
bindings[0].count = 1;
bindings[1].binding = 1;
bindings[1].type = static_cast<uint32_t>(DescriptorType::SRV);
bindings[1].count = 2;
layoutDesc.bindings = bindings;
RHIDescriptorSet* set = pool->AllocateSet(layoutDesc);
if (set != nullptr) {
EXPECT_EQ(set->GetBindingCount(), 2u);
const DescriptorSetLayoutBinding* retrievedBindings = set->GetBindings();
ASSERT_NE(retrievedBindings, nullptr);
EXPECT_EQ(retrievedBindings[0].binding, 0u);
EXPECT_EQ(retrievedBindings[1].binding, 1u);
set->Shutdown();
delete set;
}
pool->Shutdown();
delete pool;
}
TEST_P(RHITestFixture, DescriptorSet_MultipleAllocations) {
DescriptorPoolDesc poolDesc = {};
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
poolDesc.descriptorCount = 100;
poolDesc.shaderVisible = true;
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
if (pool == nullptr) {
return;
}
RHIDescriptorSet* sets[10] = { nullptr };
for (int i = 0; i < 10; ++i) {
DescriptorSetLayoutDesc layoutDesc = {};
layoutDesc.bindingCount = 0;
sets[i] = pool->AllocateSet(layoutDesc);
}
for (int i = 0; i < 10; ++i) {
if (sets[i] != nullptr) {
sets[i]->Shutdown();
delete sets[i];
}
}
pool->Shutdown();
delete pool;
}
TEST_P(RHITestFixture, DescriptorSet_FreeSet_ViaPool) {
DescriptorPoolDesc poolDesc = {};
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
poolDesc.descriptorCount = 10;
poolDesc.shaderVisible = true;
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
if (pool == nullptr) {
return;
}
DescriptorSetLayoutDesc layoutDesc = {};
layoutDesc.bindingCount = 0;
RHIDescriptorSet* set = pool->AllocateSet(layoutDesc);
if (set != nullptr) {
pool->FreeSet(set);
set = nullptr;
}
pool->Shutdown();
delete pool;
}
TEST_P(RHITestFixture, DescriptorSet_ConstantBufferSize) {
DescriptorPoolDesc poolDesc = {};
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
poolDesc.descriptorCount = 10;
poolDesc.shaderVisible = false;
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
if (pool == nullptr) {
return;
}
DescriptorSetLayoutDesc layoutDesc = {};
layoutDesc.bindingCount = 1;
DescriptorSetLayoutBinding binding = {};
binding.binding = 0;
binding.type = static_cast<uint32_t>(DescriptorType::CBV);
binding.count = 1;
layoutDesc.bindings = &binding;
RHIDescriptorSet* set = pool->AllocateSet(layoutDesc);
if (set != nullptr) {
float data[64] = {};
set->WriteConstant(0, data, sizeof(data));
EXPECT_GE(set->GetConstantBufferSize(), sizeof(data));
set->Shutdown();
delete set;
}
pool->Shutdown();
delete pool;
}
TEST_P(RHITestFixture, DescriptorSet_Update_BufferResourceView) {
DescriptorPoolDesc poolDesc = {};
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
poolDesc.descriptorCount = 10;
poolDesc.shaderVisible = true;
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
ASSERT_NE(pool, nullptr);
BufferDesc bufferDesc = {};
bufferDesc.size = 256;
bufferDesc.stride = 16;
bufferDesc.bufferType = static_cast<uint32_t>(BufferType::Storage);
RHIBuffer* buffer = GetDevice()->CreateBuffer(bufferDesc);
ASSERT_NE(buffer, nullptr);
ResourceViewDesc viewDesc = {};
viewDesc.dimension = ResourceViewDimension::StructuredBuffer;
viewDesc.structureByteStride = 16;
viewDesc.elementCount = 16;
RHIResourceView* srv = GetDevice()->CreateShaderResourceView(buffer, viewDesc);
ASSERT_NE(srv, nullptr);
DescriptorSetLayoutBinding binding = {};
binding.binding = 0;
binding.type = static_cast<uint32_t>(DescriptorType::SRV);
binding.count = 1;
binding.visibility = static_cast<uint32_t>(ShaderVisibility::All);
binding.resourceDimension = ResourceViewDimension::StructuredBuffer;
DescriptorSetLayoutDesc layoutDesc = {};
layoutDesc.bindingCount = 1;
layoutDesc.bindings = &binding;
RHIDescriptorSet* set = pool->AllocateSet(layoutDesc);
ASSERT_NE(set, nullptr);
ASSERT_NE(set->GetBindings(), nullptr);
EXPECT_EQ(set->GetBindings()[0].resourceDimension, ResourceViewDimension::StructuredBuffer);
set->Update(0, srv);
set->Shutdown();
delete set;
srv->Shutdown();
delete srv;
buffer->Shutdown();
delete buffer;
pool->Shutdown();
delete pool;
}
TEST_P(RHITestFixture, DescriptorSet_MultipleAllocations_AdvanceDescriptorOffsets) {
DescriptorPoolDesc poolDesc = {};
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
poolDesc.descriptorCount = 8;
poolDesc.shaderVisible = true;
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
ASSERT_NE(pool, nullptr);
DescriptorSetLayoutBinding bindings[2] = {};
bindings[0].binding = 0;
bindings[0].type = static_cast<uint32_t>(DescriptorType::SRV);
bindings[0].count = 1;
bindings[1].binding = 1;
bindings[1].type = static_cast<uint32_t>(DescriptorType::SRV);
bindings[1].count = 1;
DescriptorSetLayoutDesc layoutDesc = {};
layoutDesc.bindings = bindings;
layoutDesc.bindingCount = 2;
RHIDescriptorSet* firstSet = pool->AllocateSet(layoutDesc);
RHIDescriptorSet* secondSet = pool->AllocateSet(layoutDesc);
ASSERT_NE(firstSet, nullptr);
ASSERT_NE(secondSet, nullptr);
if (GetBackendType() == RHIType::D3D12) {
auto* firstD3D12Set = static_cast<D3D12DescriptorSet*>(firstSet);
auto* secondD3D12Set = static_cast<D3D12DescriptorSet*>(secondSet);
EXPECT_EQ(firstD3D12Set->GetOffset(), 0u);
EXPECT_EQ(secondD3D12Set->GetOffset(), 2u);
}
firstSet->Shutdown();
delete firstSet;
secondSet->Shutdown();
delete secondSet;
pool->Shutdown();
delete pool;
}
TEST_P(RHITestFixture, DescriptorSet_Update_BufferViews) {
DescriptorPoolDesc poolDesc = {};
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
poolDesc.descriptorCount = 8;
poolDesc.shaderVisible = true;
RHIDescriptorPool* pool = GetDevice()->CreateDescriptorPool(poolDesc);
ASSERT_NE(pool, nullptr);
BufferDesc bufferDesc = {};
bufferDesc.size = 256;
bufferDesc.stride = 16;
bufferDesc.bufferType = static_cast<uint32_t>(BufferType::Storage);
RHIBuffer* buffer = GetDevice()->CreateBuffer(bufferDesc);
ASSERT_NE(buffer, nullptr);
ResourceViewDesc srvDesc = {};
srvDesc.dimension = ResourceViewDimension::StructuredBuffer;
srvDesc.structureByteStride = 16;
srvDesc.elementCount = 8;
ResourceViewDesc uavDesc = {};
uavDesc.dimension = ResourceViewDimension::RawBuffer;
uavDesc.firstElement = 4;
uavDesc.elementCount = 8;
RHIResourceView* srv = GetDevice()->CreateShaderResourceView(buffer, srvDesc);
RHIResourceView* uav = GetDevice()->CreateUnorderedAccessView(buffer, uavDesc);
ASSERT_NE(srv, nullptr);
ASSERT_NE(uav, nullptr);
DescriptorSetLayoutBinding bindings[2] = {};
bindings[0].binding = 0;
bindings[0].type = static_cast<uint32_t>(DescriptorType::SRV);
bindings[0].count = 1;
bindings[0].resourceDimension = ResourceViewDimension::StructuredBuffer;
bindings[1].binding = 1;
bindings[1].type = static_cast<uint32_t>(DescriptorType::UAV);
bindings[1].count = 1;
bindings[1].resourceDimension = ResourceViewDimension::RawBuffer;
DescriptorSetLayoutDesc layoutDesc = {};
layoutDesc.bindings = bindings;
layoutDesc.bindingCount = 2;
RHIDescriptorSet* set = pool->AllocateSet(layoutDesc);
ASSERT_NE(set, nullptr);
set->Update(0, srv);
set->Update(1, uav);
set->Bind();
set->Unbind();
set->Shutdown();
delete set;
srv->Shutdown();
delete srv;
uav->Shutdown();
delete uav;
buffer->Shutdown();
delete buffer;
pool->Shutdown();
delete pool;
}