diff --git a/tools/render-test/options.cpp b/tools/render-test/options.cpp index 71a2c988221..0b193499d6c 100644 --- a/tools/render-test/options.cpp +++ b/tools/render-test/options.cpp @@ -17,40 +17,50 @@ namespace renderer_test { using namespace Slang; -// Helper function to check if a feature name is valid -static bool isValidFeatureName( - const UnownedStringSlice& featureName, - DiagnosticSink* sink, - SourceLoc loc) +rhi::Feature getRenderFeatureFromName(const UnownedStringSlice& featureName) { - // WAR: Accept cooperative-matrix-2 sub-features until RHI backend supports them - // These features will be gracefully skipped at runtime if hardware doesn't support them - if (featureName.startsWith("cooperative-matrix-")) + // slang-rhi reports VK_NV_cooperative_matrix2 as one feature, but tests name the individual + // sub-features the extension provides. Resolve each of them to that single feature so a test + // gated on a sub-feature runs on hardware that supports the extension, rather than being + // skipped everywhere. + static const UnownedStringSlice kCooperativeMatrix2SubFeatures[] = { + UnownedStringSlice::fromLiteral("cooperative-matrix-block-loads"), + UnownedStringSlice::fromLiteral("cooperative-matrix-conversions"), + UnownedStringSlice::fromLiteral("cooperative-matrix-per-element-operations"), + UnownedStringSlice::fromLiteral("cooperative-matrix-reductions"), + UnownedStringSlice::fromLiteral("cooperative-matrix-tensor-addressing"), + }; + for (const auto& subFeature : kCooperativeMatrix2SubFeatures) { - if (sink) + if (featureName == subFeature) { - sink->diagnoseRaw( - Severity::Warning, - "Using cooperative-matrix-2 feature that is not yet fully supported " - "in RHI backend. " - "Test will be skipped if hardware doesn't support it."); + return rhi::Feature::CooperativeMatrix2; } - return true; } -#define SLANG_RHI_FEATURES_X(id, name) name, - static const char* kValidFeatureNames[] = {SLANG_RHI_FEATURES(SLANG_RHI_FEATURES_X)}; -#undef SLANG_RHI_FEATURES_X - static const int kFeatureCount = sizeof(kValidFeatureNames) / sizeof(kValidFeatureNames[0]); +#define SLANG_RHI_FEATURES_X(id, name) {UnownedStringSlice::fromLiteral(name), rhi::Feature::id}, + struct FeatureNameMapEntry + { + UnownedStringSlice name; + rhi::Feature feature; + }; + static const FeatureNameMapEntry kFeatureNameMap[] = {SLANG_RHI_FEATURES(SLANG_RHI_FEATURES_X)}; +#undef SLANG_RHI_FEATURES_X - for (int i = 0; i < kFeatureCount; i++) + for (const auto& entry : kFeatureNameMap) { - if (featureName == UnownedStringSlice(kValidFeatureNames[i])) + if (featureName == entry.name) { - return true; + return entry.feature; } } - return false; + return rhi::Feature::_Count; +} + +/// Return true if `featureName` names a feature the runtime requirement check can evaluate. +static bool isValidFeatureName(const UnownedStringSlice& featureName) +{ + return getRenderFeatureFromName(featureName) != rhi::Feature::_Count; } static rhi::DeviceType _toRenderType(Slang::RenderApiType apiType) @@ -162,7 +172,7 @@ static rhi::DeviceType _toRenderType(Slang::RenderApiType apiType) for (const auto& value : values) { // Validate that the feature name is recognized - if (!isValidFeatureName(value, &sink, featuresArg.loc)) + if (!isValidFeatureName(value)) { sink.diagnose( featuresArg.loc, diff --git a/tools/render-test/options.h b/tools/render-test/options.h index 00a4e489151..34d6a9a9157 100644 --- a/tools/render-test/options.h +++ b/tools/render-test/options.h @@ -114,4 +114,15 @@ struct Options Options& outOptions); }; +/// Return the `rhi::Feature` a `-render-feature` name refers to, or `rhi::Feature::_Count` if the +/// name is not recognized. +/// +/// This is the single place that maps a test's feature name onto an RHI feature, so that option +/// parsing (which rejects unknown names) and the runtime requirement check (which decides whether +/// to skip a test) can never disagree. Besides the names generated from `SLANG_RHI_FEATURES`, it +/// resolves the individual `VK_NV_cooperative_matrix2` sub-feature names used by tests -- slang-rhi +/// exposes that extension only as the single `cooperative-matrix-2` feature, so each sub-feature +/// name maps onto it. +rhi::Feature getRenderFeatureFromName(const Slang::UnownedStringSlice& featureName); + } // namespace renderer_test diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp index 68dd0fbf275..b6efc5ab0f9 100644 --- a/tools/render-test/render-test-main.cpp +++ b/tools/render-test/render-test-main.cpp @@ -193,25 +193,6 @@ static void _outputProfileTime(uint64_t startTicks, uint64_t endTicks) out.print("profile-time=%g\n", time); } -static rhi::Feature _getFeatureFromName(const UnownedStringSlice& featureName) -{ - struct FeatureNameMapEntry - { - const char* name; - rhi::Feature feature; - }; - -#define SLANG_RHI_FEATURES_X(id, name) {name, rhi::Feature::id}, - static const FeatureNameMapEntry kFeatureNameMap[] = {SLANG_RHI_FEATURES(SLANG_RHI_FEATURES_X)}; -#undef SLANG_RHI_FEATURES_X - - for (auto& entry : kFeatureNameMap) - if (featureName == UnownedStringSlice(entry.name)) - return entry.feature; - - return rhi::Feature::_Count; -} - class ProgramVars; struct ShaderOutputPlan @@ -1918,7 +1899,7 @@ static SlangResult _innerMain( List requiredFeatureList; for (auto& name : options.renderFeatures) - requiredFeatureList.add(_getFeatureFromName(name.getUnownedSlice())); + requiredFeatureList.add(getRenderFeatureFromName(name.getUnownedSlice())); desc.requiredFeatures = requiredFeatureList.getBuffer(); desc.requiredFeatureCount = (int)requiredFeatureList.getCount();