summaryrefslogtreecommitdiffstats
path: root/tools/gfx-unit-test/gfx-test-util.cpp
diff options
context:
space:
mode:
authorGangzheng Tong <tonggangzheng@gmail.com>2025-07-08 23:44:56 -0700
committerGitHub <noreply@github.com>2025-07-09 06:44:56 +0000
commit43d0c2100ef1a5df4b54525e50eb29fe7c39ec16 (patch)
tree25ec4fb9c726115f90bdaa9878f2f4ca372ad0a6 /tools/gfx-unit-test/gfx-test-util.cpp
parent00746bf09047cdf01c19dac513a532bcf3ed3ea3 (diff)
Convert gfx unit tests and examples to use slang-rhi (#7577)
* Port first gfx unit test to slang-rhi * port triangle example to use slang-rhi * port platform-test to slang-rhi * Update platform-test to throttle mouse move events * port gpu-printing example to use slang-rhi * port model-viewer example to use slang-rhi * port ray-tracing example to use slang-rhi * port ray-tracing pipeline example to use slang-rhi * port reflection parameter blocks example to use slang-rhi * port shader-object example to use slang-rhi * port shader-toy example to use slang-rhi * Port most of tests to slang-rhi * port link-time-constant-array-size to use slang-rhi * Fix tests and find matching tests in slang-rhi * port autodiff-texture * remove gfx target; port nv-aftermath-example * update include path for shader-cursor.h * Disabled 2 more ported tests * fix build error * remove gfx test * put slang-rhi (static-lib) before slang (shared) * format code (#7621) Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> * add debug callback * format code (#7649) Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> * Address review comments; revert back to use SLANG_CHECK_MSG --------- Co-authored-by: slangbot <ellieh+slangbot@nvidia.com> Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
Diffstat (limited to 'tools/gfx-unit-test/gfx-test-util.cpp')
-rw-r--r--tools/gfx-unit-test/gfx-test-util.cpp355
1 files changed, 156 insertions, 199 deletions
diff --git a/tools/gfx-unit-test/gfx-test-util.cpp b/tools/gfx-unit-test/gfx-test-util.cpp
index 688bf048e..4072b9814 100644
--- a/tools/gfx-unit-test/gfx-test-util.cpp
+++ b/tools/gfx-unit-test/gfx-test-util.cpp
@@ -15,6 +15,29 @@ using Slang::ComPtr;
namespace gfx_test
{
+class DebugPrinter : public rhi::IDebugCallback
+{
+public:
+ virtual SLANG_NO_THROW void SLANG_MCALL handleMessage(
+ rhi::DebugMessageType type,
+ rhi::DebugMessageSource source,
+ const char* message) override
+ {
+ static const char* kTypeStrings[] = {"INFO", "WARN", "ERROR"};
+ static const char* kSourceStrings[] = {"Layer", "Driver", "Slang"};
+ if (type == rhi::DebugMessageType::Error)
+ {
+ printf("[%s] (%s) %s\n", kTypeStrings[int(type)], kSourceStrings[int(source)], message);
+ fflush(stdout);
+ }
+ }
+ static DebugPrinter* getInstance()
+ {
+ static DebugPrinter instance;
+ return &instance;
+ }
+};
+
void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob)
{
if (diagnosticsBlob != nullptr)
@@ -25,16 +48,16 @@ void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob)
}
}
-Slang::Result loadComputeProgram(
- gfx::IDevice* device,
- Slang::ComPtr<gfx::IShaderProgram>& outShaderProgram,
+Result loadComputeProgram(
+ IDevice* device,
+ ComPtr<IShaderProgram>& outShaderProgram,
const char* shaderModuleName,
const char* entryPointName,
slang::ProgramLayout*& slangReflection)
{
- Slang::ComPtr<slang::ISession> slangSession;
+ ComPtr<slang::ISession> slangSession;
SLANG_RETURN_ON_FAIL(device->getSlangSession(slangSession.writeRef()));
- Slang::ComPtr<slang::IBlob> diagnosticsBlob;
+ ComPtr<slang::IBlob> diagnosticsBlob;
slang::IModule* module = slangSession->loadModule(shaderModuleName, diagnosticsBlob.writeRef());
diagnoseIfNeeded(diagnosticsBlob);
if (!module)
@@ -44,14 +67,14 @@ Slang::Result loadComputeProgram(
SLANG_RETURN_ON_FAIL(
module->findEntryPointByName(entryPointName, computeEntryPoint.writeRef()));
- Slang::List<slang::IComponentType*> componentTypes;
- componentTypes.add(module);
- componentTypes.add(computeEntryPoint);
+ std::vector<slang::IComponentType*> componentTypes;
+ componentTypes.push_back(module);
+ componentTypes.push_back(computeEntryPoint);
- Slang::ComPtr<slang::IComponentType> composedProgram;
- SlangResult result = slangSession->createCompositeComponentType(
- componentTypes.getBuffer(),
- componentTypes.getCount(),
+ ComPtr<slang::IComponentType> composedProgram;
+ Result result = slangSession->createCompositeComponentType(
+ componentTypes.data(),
+ componentTypes.size(),
composedProgram.writeRef(),
diagnosticsBlob.writeRef());
diagnoseIfNeeded(diagnosticsBlob);
@@ -62,30 +85,21 @@ Slang::Result loadComputeProgram(
diagnoseIfNeeded(diagnosticsBlob);
SLANG_RETURN_ON_FAIL(result);
- composedProgram = linkedProgram;
- slangReflection = composedProgram->getLayout();
-
- gfx::IShaderProgram::Desc programDesc = {};
- programDesc.slangGlobalScope = composedProgram.get();
-
- auto shaderProgram = device->createProgram(programDesc);
- if (!shaderProgram)
- return SLANG_FAIL;
-
- outShaderProgram = shaderProgram;
- return SLANG_OK;
+ slangReflection = linkedProgram->getLayout();
+ outShaderProgram = device->createShaderProgram(linkedProgram, diagnosticsBlob.writeRef());
+ diagnoseIfNeeded(diagnosticsBlob);
+ return outShaderProgram ? SLANG_OK : SLANG_FAIL;
}
-Slang::Result loadComputeProgram(
- gfx::IDevice* device,
+Result loadComputeProgram(
+ IDevice* device,
slang::ISession* slangSession,
- Slang::ComPtr<gfx::IShaderProgram>& outShaderProgram,
+ ComPtr<IShaderProgram>& outShaderProgram,
const char* shaderModuleName,
const char* entryPointName,
- slang::ProgramLayout*& slangReflection,
- PrecompilationMode precompilationMode)
+ slang::ProgramLayout*& slangReflection)
{
- Slang::ComPtr<slang::IBlob> diagnosticsBlob;
+ ComPtr<slang::IBlob> diagnosticsBlob;
slang::IModule* module = slangSession->loadModule(shaderModuleName, diagnosticsBlob.writeRef());
diagnoseIfNeeded(diagnosticsBlob);
if (!module)
@@ -95,14 +109,14 @@ Slang::Result loadComputeProgram(
SLANG_RETURN_ON_FAIL(
module->findEntryPointByName(entryPointName, computeEntryPoint.writeRef()));
- Slang::List<slang::IComponentType*> componentTypes;
- componentTypes.add(module);
- componentTypes.add(computeEntryPoint);
+ std::vector<slang::IComponentType*> componentTypes;
+ componentTypes.push_back(module);
+ componentTypes.push_back(computeEntryPoint);
- Slang::ComPtr<slang::IComponentType> composedProgram;
- SlangResult result = slangSession->createCompositeComponentType(
- componentTypes.getBuffer(),
- componentTypes.getCount(),
+ ComPtr<slang::IComponentType> composedProgram;
+ Result result = slangSession->createCompositeComponentType(
+ componentTypes.data(),
+ componentTypes.size(),
composedProgram.writeRef(),
diagnosticsBlob.writeRef());
diagnoseIfNeeded(diagnosticsBlob);
@@ -113,55 +127,71 @@ Slang::Result loadComputeProgram(
diagnoseIfNeeded(diagnosticsBlob);
SLANG_RETURN_ON_FAIL(result);
- composedProgram = linkedProgram;
- slangReflection = composedProgram->getLayout();
-
- gfx::IShaderProgram::Desc programDesc = {};
- programDesc.slangGlobalScope = composedProgram.get();
- if (precompilationMode == PrecompilationMode::ExternalLink)
- {
- programDesc.downstreamLinkMode = gfx::IShaderProgram::DownstreamLinkMode::Deferred;
- }
- else
- {
- programDesc.downstreamLinkMode = gfx::IShaderProgram::DownstreamLinkMode::None;
- }
-
- auto shaderProgram = device->createProgram(programDesc);
-
- outShaderProgram = shaderProgram;
- return SLANG_OK;
+ slangReflection = linkedProgram->getLayout();
+ outShaderProgram = device->createShaderProgram(linkedProgram, diagnosticsBlob.writeRef());
+ diagnoseIfNeeded(diagnosticsBlob);
+ return outShaderProgram ? SLANG_OK : SLANG_FAIL;
}
-Slang::Result loadComputeProgramFromSource(
- gfx::IDevice* device,
- Slang::ComPtr<gfx::IShaderProgram>& outShaderProgram,
- Slang::String source)
+Result loadComputeProgramFromSource(
+ IDevice* device,
+ ComPtr<IShaderProgram>& outShaderProgram,
+ std::string_view source)
{
- Slang::ComPtr<slang::IBlob> diagnosticsBlob;
+ auto slangSession = device->getSlangSession();
+ slang::IModule* module = nullptr;
+ ComPtr<slang::IBlob> diagnosticsBlob;
+ size_t hash = std::hash<std::string_view>()(source);
+ std::string moduleName = "source_module_" + std::to_string(hash);
+ auto srcBlob = Slang::UnownedRawBlob::create(source.data(), source.size());
+ module = slangSession->loadModuleFromSource(
+ moduleName.data(),
+ moduleName.data(),
+ srcBlob,
+ diagnosticsBlob.writeRef());
+ diagnoseIfNeeded(diagnosticsBlob);
+ if (!module)
+ return SLANG_FAIL;
+
+ std::vector<ComPtr<slang::IComponentType>> componentTypes;
+ componentTypes.push_back(ComPtr<slang::IComponentType>(module));
- gfx::IShaderProgram::CreateDesc2 programDesc = {};
- programDesc.sourceType = gfx::ShaderModuleSourceType::SlangSource;
- programDesc.sourceData = (void*)source.getBuffer();
- programDesc.sourceDataSize = source.getLength();
+ for (SlangInt32 i = 0; i < module->getDefinedEntryPointCount(); i++)
+ {
+ ComPtr<slang::IEntryPoint> entryPoint;
+ SLANG_RETURN_ON_FAIL(module->getDefinedEntryPoint(i, entryPoint.writeRef()));
+ componentTypes.push_back(ComPtr<slang::IComponentType>(entryPoint.get()));
+ }
- return device->createProgram2(
- programDesc,
- outShaderProgram.writeRef(),
+ std::vector<slang::IComponentType*> rawComponentTypes;
+ for (auto& compType : componentTypes)
+ rawComponentTypes.push_back(compType.get());
+
+ ComPtr<slang::IComponentType> linkedProgram;
+ Result result = slangSession->createCompositeComponentType(
+ rawComponentTypes.data(),
+ rawComponentTypes.size(),
+ linkedProgram.writeRef(),
diagnosticsBlob.writeRef());
+ diagnoseIfNeeded(diagnosticsBlob);
+ SLANG_RETURN_ON_FAIL(result);
+
+ outShaderProgram = device->createShaderProgram(linkedProgram, diagnosticsBlob.writeRef());
+ diagnoseIfNeeded(diagnosticsBlob);
+ return outShaderProgram ? SLANG_OK : SLANG_FAIL;
}
-Slang::Result loadGraphicsProgram(
- gfx::IDevice* device,
- Slang::ComPtr<gfx::IShaderProgram>& outShaderProgram,
+Result loadGraphicsProgram(
+ IDevice* device,
+ ComPtr<IShaderProgram>& outShaderProgram,
const char* shaderModuleName,
const char* vertexEntryPointName,
const char* fragmentEntryPointName,
slang::ProgramLayout*& slangReflection)
{
- Slang::ComPtr<slang::ISession> slangSession;
+ ComPtr<slang::ISession> slangSession;
SLANG_RETURN_ON_FAIL(device->getSlangSession(slangSession.writeRef()));
- Slang::ComPtr<slang::IBlob> diagnosticsBlob;
+ ComPtr<slang::IBlob> diagnosticsBlob;
slang::IModule* module = slangSession->loadModule(shaderModuleName, diagnosticsBlob.writeRef());
diagnoseIfNeeded(diagnosticsBlob);
if (!module)
@@ -175,158 +205,85 @@ Slang::Result loadGraphicsProgram(
SLANG_RETURN_ON_FAIL(
module->findEntryPointByName(fragmentEntryPointName, fragmentEntryPoint.writeRef()));
- Slang::List<slang::IComponentType*> componentTypes;
- componentTypes.add(module);
- componentTypes.add(vertexEntryPoint);
- componentTypes.add(fragmentEntryPoint);
+ std::vector<slang::IComponentType*> componentTypes;
+ componentTypes.push_back(module);
+ componentTypes.push_back(vertexEntryPoint);
+ componentTypes.push_back(fragmentEntryPoint);
- Slang::ComPtr<slang::IComponentType> composedProgram;
- SlangResult result = slangSession->createCompositeComponentType(
- componentTypes.getBuffer(),
- componentTypes.getCount(),
+ ComPtr<slang::IComponentType> composedProgram;
+ Result result = slangSession->createCompositeComponentType(
+ componentTypes.data(),
+ componentTypes.size(),
composedProgram.writeRef(),
diagnosticsBlob.writeRef());
diagnoseIfNeeded(diagnosticsBlob);
SLANG_RETURN_ON_FAIL(result);
- slangReflection = composedProgram->getLayout();
- gfx::IShaderProgram::Desc programDesc = {};
- programDesc.slangGlobalScope = composedProgram.get();
-
- auto shaderProgram = device->createProgram(programDesc);
-
- outShaderProgram = shaderProgram;
- return SLANG_OK;
-}
-
-void compareComputeResult(
- gfx::IDevice* device,
- gfx::ITextureResource* texture,
- gfx::ResourceState state,
- void* expectedResult,
- size_t expectedResultRowPitch,
- size_t rowCount)
-{
- // Read back the results.
- ComPtr<ISlangBlob> resultBlob;
- size_t rowPitch = 0;
- size_t pixelSize = 0;
- GFX_CHECK_CALL_ABORT(
- device->readTextureResource(texture, state, resultBlob.writeRef(), &rowPitch, &pixelSize));
- // Compare results.
- for (size_t row = 0; row < rowCount; row++)
- {
- SLANG_CHECK(
- memcmp(
- (uint8_t*)resultBlob->getBufferPointer() + rowPitch * row,
- (uint8_t*)expectedResult + expectedResultRowPitch * row,
- expectedResultRowPitch) == 0);
- }
-}
-
-void compareComputeResult(
- gfx::IDevice* device,
- gfx::IBufferResource* buffer,
- size_t offset,
- const void* expectedResult,
- size_t expectedBufferSize)
-{
- // Read back the results.
- ComPtr<ISlangBlob> resultBlob;
- GFX_CHECK_CALL_ABORT(
- device->readBufferResource(buffer, offset, expectedBufferSize, resultBlob.writeRef()));
- SLANG_CHECK(resultBlob->getBufferSize() == expectedBufferSize);
- // Compare results.
- SLANG_CHECK(
- memcmp(resultBlob->getBufferPointer(), (uint8_t*)expectedResult, expectedBufferSize) == 0);
-}
-
-void compareComputeResultFuzzy(
- const float* result,
- float* expectedResult,
- size_t expectedBufferSize)
-{
- for (size_t i = 0; i < expectedBufferSize / sizeof(float); ++i)
- {
- SLANG_CHECK(abs(result[i] - expectedResult[i]) <= 0.01);
- }
-}
+ ComPtr<slang::IComponentType> linkedProgram;
+ result = composedProgram->link(linkedProgram.writeRef(), diagnosticsBlob.writeRef());
+ diagnoseIfNeeded(diagnosticsBlob);
+ SLANG_RETURN_ON_FAIL(result);
-void compareComputeResultFuzzy(
- gfx::IDevice* device,
- gfx::IBufferResource* buffer,
- float* expectedResult,
- size_t expectedBufferSize)
-{
- // Read back the results.
- ComPtr<ISlangBlob> resultBlob;
- GFX_CHECK_CALL_ABORT(
- device->readBufferResource(buffer, 0, expectedBufferSize, resultBlob.writeRef()));
- SLANG_CHECK(resultBlob->getBufferSize() == expectedBufferSize);
- // Compare results with a tolerance of 0.01.
- auto result = (float*)resultBlob->getBufferPointer();
- compareComputeResultFuzzy(result, expectedResult, expectedBufferSize);
+ slangReflection = linkedProgram->getLayout();
+ outShaderProgram = device->createShaderProgram(linkedProgram, diagnosticsBlob.writeRef());
+ diagnoseIfNeeded(diagnosticsBlob);
+ return outShaderProgram ? SLANG_OK : SLANG_FAIL;
}
-Slang::ComPtr<gfx::IDevice> createTestingDevice(
+Slang::ComPtr<IDevice> createTestingDevice(
UnitTestContext* context,
- Slang::RenderApiFlag::Enum api,
- Slang::List<const char*> additionalSearchPaths,
- gfx::IDevice::ShaderCacheDesc shaderCache)
+ DeviceType deviceType,
+ Slang::List<const char*> additionalSearchPaths)
{
- Slang::ComPtr<gfx::IDevice> device;
- gfx::IDevice::Desc deviceDesc = {};
- switch (api)
- {
- case Slang::RenderApiFlag::D3D11:
- deviceDesc.deviceType = gfx::DeviceType::DirectX11;
- break;
- case Slang::RenderApiFlag::D3D12:
- deviceDesc.deviceType = gfx::DeviceType::DirectX12;
- break;
- case Slang::RenderApiFlag::Vulkan:
- deviceDesc.deviceType = gfx::DeviceType::Vulkan;
- break;
- case Slang::RenderApiFlag::CPU:
- deviceDesc.deviceType = gfx::DeviceType::CPU;
- break;
- case Slang::RenderApiFlag::CUDA:
- deviceDesc.deviceType = gfx::DeviceType::CUDA;
- break;
- default:
- SLANG_IGNORE_TEST
- }
+ Slang::ComPtr<IDevice> device;
+ DeviceDesc deviceDesc = {};
+ deviceDesc.deviceType = deviceType;
+
deviceDesc.slang.slangGlobalSession = context->slangGlobalSession;
Slang::List<const char*> searchPaths = getSlangSearchPaths();
searchPaths.addRange(additionalSearchPaths);
deviceDesc.slang.searchPaths = searchPaths.getBuffer();
- deviceDesc.slang.searchPathCount = (gfx::GfxCount)searchPaths.getCount();
- deviceDesc.shaderCache = shaderCache;
+ deviceDesc.slang.searchPathCount = searchPaths.getCount();
- gfx::D3D12DeviceExtendedDesc extDesc = {};
- extDesc.rootParameterShaderAttributeName = "root";
+ std::vector<slang::PreprocessorMacroDesc> preprocessorMacros;
+ std::vector<slang::CompilerOptionEntry> compilerOptions;
- gfx::SlangSessionExtendedDesc slangExtDesc = {};
- Slang::List<slang::CompilerOptionEntry> entries;
slang::CompilerOptionEntry emitSpirvDirectlyEntry;
emitSpirvDirectlyEntry.name = slang::CompilerOptionName::EmitSpirvDirectly;
emitSpirvDirectlyEntry.value.intValue0 = 1;
- entries.add(emitSpirvDirectlyEntry);
-#if GFX_ENABLE_SPIRV_DEBUG
- slang::CompilerOptionEntry debugLevelCompilerOptionEntry;
+ compilerOptions.push_back(emitSpirvDirectlyEntry);
+#if DEBUG_SPIRV
+ slang::CompilerOptionEntry debugLevelCompilerOptionEntry = {};
debugLevelCompilerOptionEntry.name = slang::CompilerOptionName::DebugInformation;
debugLevelCompilerOptionEntry.value.intValue0 = SLANG_DEBUG_INFO_LEVEL_STANDARD;
- entries.add(debugLevelCompilerOptionEntry);
+ compilerOptions.push_back(debugLevelCompilerOptionEntry);
+#endif
+#if DUMP_INTERMEDIATES
+ slang::CompilerOptionEntry dumpIntermediatesOptionEntry = {};
+ dumpIntermediatesOptionEntry.name = slang::CompilerOptionName::DumpIntermediates;
+ dumpIntermediatesOptionEntry.value.intValue0 = 1;
+ compilerOptions.push_back(dumpIntermediatesOptionEntry);
#endif
- slangExtDesc.compilerOptionEntries = entries.getBuffer();
- slangExtDesc.compilerOptionEntryCount = (uint32_t)entries.getCount();
- deviceDesc.extendedDescCount = 2;
- void* extDescPtrs[2] = {&extDesc, &slangExtDesc};
- deviceDesc.extendedDescs = extDescPtrs;
+ deviceDesc.slang.preprocessorMacros = preprocessorMacros.data();
+ deviceDesc.slang.preprocessorMacroCount = preprocessorMacros.size();
+ deviceDesc.slang.compilerOptionEntries = compilerOptions.data();
+ deviceDesc.slang.compilerOptionEntryCount = compilerOptions.size();
+
+ if (context->enableDebugLayers)
+ {
+ deviceDesc.enableValidation = context->enableDebugLayers;
+ deviceDesc.debugCallback = DebugPrinter::getInstance();
+ }
+
+ D3D12DeviceExtendedDesc extDesc = {};
+ if (deviceType == DeviceType::D3D12)
+ {
+ extDesc.rootParameterShaderAttributeName = "root";
+ deviceDesc.next = &extDesc;
+ }
- gfx::gfxEnableDebugLayer(context->enableDebugLayers);
- auto createDeviceResult = gfxCreateDevice(&deviceDesc, device.writeRef());
+ auto createDeviceResult = getRHI()->createDevice(deviceDesc, device.writeRef());
if (SLANG_FAILED(createDeviceResult))
{
SLANG_IGNORE_TEST