#include "fixtures/RHITestFixture.h" #include "XCEngine/RHI/RHIDescriptorPool.h" #include "XCEngine/RHI/RHIDescriptorSet.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(Format::R8G8B8A8_UNorm); texDesc.textureType = static_cast(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(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(FilterMode::Linear); samplerDesc.addressU = static_cast(TextureAddressMode::Wrap); samplerDesc.addressV = static_cast(TextureAddressMode::Wrap); samplerDesc.addressW = static_cast(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(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(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(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(DescriptorType::CBV); bindings[0].count = 1; bindings[1].binding = 1; bindings[1].type = static_cast(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(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; }