diff options
| author | Gangzheng Tong <tonggangzheng@gmail.com> | 2025-07-08 23:44:56 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-09 06:44:56 +0000 |
| commit | 43d0c2100ef1a5df4b54525e50eb29fe7c39ec16 (patch) | |
| tree | 25ec4fb9c726115f90bdaa9878f2f4ca372ad0a6 /tools/gfx-unit-test/gfx-test-util.cpp | |
| parent | 00746bf09047cdf01c19dac513a532bcf3ed3ea3 (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.cpp | 355 |
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 |
