Skip to content
68 changes: 47 additions & 21 deletions tests/shaders/runtime_test_discovery.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,28 +194,54 @@ namespace HLSLTestDiscovery
inline bool runTest(const TestFunction& test, std::string& errorMsg)
{
try {
stf::ShaderTestFixture fixture(ShaderTest::GetFixtureDesc());
auto shaderDir = (ShaderTest::GetExecutableDirectory() / "Shaders").wstring();

auto result = fixture.RunTest(stf::ShaderTestFixture::RuntimeTestDesc{
.CompilationEnv{ .Source = std::filesystem::path(test.filePath),
.CompilationFlags = { L"-I", shaderDir } },
.TestName = test.name,
.ThreadGroupCount{ 1, 1, 1 } });

if (!result) {
// Extract detailed error information from the result
// This includes line numbers, thread IDs, and actual/expected values
std::ostringstream oss;
oss << result;
errorMsg = oss.str();

// Also print to stdout for immediate visibility during test runs
std::cout << "\n"
<< errorMsg << "\n";
return false;
auto runWithDevice = [&test, &errorMsg](const stf::GPUDevice::EDeviceType deviceType) {
stf::ShaderTestFixture fixture(ShaderTest::GetFixtureDesc(deviceType));
auto shaderDir = (ShaderTest::GetExecutableDirectory() / "Shaders").wstring();

auto result = fixture.RunTest(stf::ShaderTestFixture::RuntimeTestDesc{
.CompilationEnv{ .Source = std::filesystem::path(test.filePath),
.CompilationFlags = { L"-I", shaderDir } },
.TestName = test.name,
.ThreadGroupCount{ 1, 1, 1 } });

if (!result) {
// Extract detailed error information from the result
// This includes line numbers, thread IDs, and actual/expected values
std::ostringstream oss;
oss << result;
errorMsg = oss.str();

// Also print to stdout for immediate visibility during test runs
std::cout << "\n"
<< errorMsg << "\n";
return false;
}

return true;
};

if (ShaderTest::GetPreferredDevice() == ShaderTest::EPreferredDevice::Hardware) {
return runWithDevice(stf::GPUDevice::EDeviceType::Hardware);
}

if (ShaderTest::GetPreferredDevice() == ShaderTest::EPreferredDevice::Software) {
return runWithDevice(stf::GPUDevice::EDeviceType::Software);
}

try {
const bool hardwareResult = runWithDevice(stf::GPUDevice::EDeviceType::Hardware);
ShaderTest::SetPreferredDevice(ShaderTest::EPreferredDevice::Hardware);
return hardwareResult;
} catch (const stf::HrException& e) {
if (e.Error() == E_INVALIDARG) {
std::cout << "\n[ShaderTests] Hardware D3D12 path returned E_INVALIDARG; retrying with software WARP device.\n";
const bool softwareResult = runWithDevice(stf::GPUDevice::EDeviceType::Software);
ShaderTest::SetPreferredDevice(ShaderTest::EPreferredDevice::Software);
return softwareResult;
} else {
throw;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
return true;
} catch (const std::exception& e) {
errorMsg = e.what();
std::cout << "\nException: " << errorMsg << "\n";
Expand Down
60 changes: 56 additions & 4 deletions tests/shaders/test_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,59 @@

#include <Framework/ShaderTestFixture.h>
#include <filesystem>
#include <stdexcept>
#include <vector>

#ifdef _WIN32
# include <windows.h>
#endif

namespace ShaderTest
{
enum class EPreferredDevice
{
Undecided,
Hardware,
Software
};

inline EPreferredDevice& GetPreferredDeviceState()
{
static EPreferredDevice preferredDevice = EPreferredDevice::Undecided;
return preferredDevice;
}

inline void SetPreferredDevice(const EPreferredDevice preferredDevice)
{
GetPreferredDeviceState() = preferredDevice;
}

inline EPreferredDevice GetPreferredDevice()
{
return GetPreferredDeviceState();
}

inline stf::GPUDevice::EDeviceType ToGPUDeviceType(const EPreferredDevice preferredDevice)
{
if (preferredDevice == EPreferredDevice::Software) {
return stf::GPUDevice::EDeviceType::Software;
}

return stf::GPUDevice::EDeviceType::Hardware;
}

inline stf::GPUDevice::EDeviceType GetPreferredGPUDeviceType()
{
const EPreferredDevice preferredDevice = GetPreferredDevice();
if (preferredDevice == EPreferredDevice::Undecided) {
throw std::logic_error(
"Preferred GPU device is undecided. Call ShaderTest::SetPreferredDevice(...) "
"or use ShaderTest::GetFixtureDesc(deviceType) with an explicit device.");
}

return ToGPUDeviceType(preferredDevice);
}

/// Get the directory containing the test executable
/// This is portable across different working directories and drive letters
inline std::filesystem::path GetExecutableDirectory()
Expand Down Expand Up @@ -52,15 +98,21 @@ namespace ShaderTest
};
}

/// Get standard fixture description for hardware testing
inline stf::ShaderTestFixture::FixtureDesc GetFixtureDesc()
/// Get fixture description for an explicitly selected GPU device type
inline stf::ShaderTestFixture::FixtureDesc GetFixtureDesc(const stf::GPUDevice::EDeviceType deviceType)
{
return stf::ShaderTestFixture::FixtureDesc{
.Mappings = GetShaderDirectoryMappings(),
.GPUDeviceParams{
.DebugLevel = stf::GPUDevice::EDebugLevel::Off, // Disable debug layer (may conflict with some drivers)
.DeviceType = stf::GPUDevice::EDeviceType::Hardware, // Use real GPU instead of WARP
.DebugLevel = stf::GPUDevice::EDebugLevel::Off, // Disable debug layer (may conflict with some drivers)
.DeviceType = deviceType,
.EnableGPUCapture = false }
};
}

/// Get fixture description using the shared preferred device selection
inline stf::ShaderTestFixture::FixtureDesc GetFixtureDesc()
{
return GetFixtureDesc(GetPreferredGPUDeviceType());
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
5 changes: 3 additions & 2 deletions tests/shaders/test_helpers_unified.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
#define SHADER_TEST(test_name, tags, shader_path, hlsl_function, x, y, z) \
TEST_CASE(test_name, tags) \
{ \
stf::ShaderTestFixture fixture(ShaderTest::GetFixtureDesc()); \
stf::ShaderTestFixture fixture( \
ShaderTest::GetFixtureDesc(stf::GPUDevice::EDeviceType::Hardware)); \
auto shaderDir = (ShaderTest::GetExecutableDirectory() / "Shaders").wstring(); \
auto result = fixture.RunTest(stf::ShaderTestFixture::RuntimeTestDesc{ \
.CompilationEnv{ .Source = std::filesystem::path(shader_path), \
Expand Down Expand Up @@ -87,7 +88,7 @@ inline void GenerateShaderTests(const char* shaderPath, const ShaderTestEntry (&
for (const auto& entry : entries) {
DYNAMIC_SECTION(entry.testName)
{
stf::ShaderTestFixture fixture(ShaderTest::GetFixtureDesc());
stf::ShaderTestFixture fixture(ShaderTest::GetFixtureDesc(stf::GPUDevice::EDeviceType::Hardware));
auto result = fixture.RunTest(stf::ShaderTestFixture::RuntimeTestDesc{
.CompilationEnv{ .Source = std::filesystem::path(shaderPath),
.CompilationFlags = { L"-I", shaderDir } },
Expand Down
Loading