diff --git a/73_SpirvKeysTest/CMakeLists.txt b/73_SpirvKeysTest/CMakeLists.txt new file mode 100644 index 000000000..a101fa5a9 --- /dev/null +++ b/73_SpirvKeysTest/CMakeLists.txt @@ -0,0 +1,140 @@ +include(common) + +nbl_create_executable_project("" "" "" "") + +target_compile_definitions(${EXECUTABLE_NAME} PRIVATE NBL_SPIRV_CFG="$") + +set(OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/auto-gen") +file(MAKE_DIRECTORY "${OUTPUT_DIRECTORY}") + +enable_testing() + +add_test(NAME ${EXECUTABLE_NAME} + COMMAND "$" + WORKING_DIRECTORY "$" + COMMAND_EXPAND_LISTS +) + +set(HLSL_INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.hlsl") +file(TO_CMAKE_PATH "${HLSL_INPUT}" HLSL_INPUT) + +set(JSON_TEMPLATE [=[ +[ + { + "INPUT": "@HLSL_INPUT@", + "KEY": "k_plain", + "COMPILE_OPTIONS": ["-T", "cs_6_8"] + }, + { + "INPUT": "@HLSL_INPUT@", + "KEY": "k_ints", + "COMPILE_OPTIONS": ["-T", "cs_6_8", "-DNBL_TEST_HAS_I"], + "CAPS": [ + { + "kind": "custom", + "struct": "i", + "members": [ + { "name": "b1", "type": "bool", "values": [1] }, + { "name": "b0", "type": "bool", "values": [0] }, + { "name": "u16", "type": "uint16_t", "values": [65535] }, + { "name": "u32", "type": "uint32_t", "values": [123456789] }, + { "name": "u64", "type": "uint64_t", "values": [1234567890123] }, + { "name": "s16", "type": "int16_t", "values": [-32768] }, + { "name": "s32", "type": "int32_t", "values": [-123456789] }, + { "name": "s64", "type": "int64_t", "values": [-1234567890123] } + ] + } + ] + }, + { + "INPUT": "@HLSL_INPUT@", + "KEY": "k_two", + "COMPILE_OPTIONS": ["-T", "cs_6_8", "-DNBL_TEST_HAS_T"], + "CAPS": [ + { + "kind": "custom", + "struct": "t", + "members": [ + { "name": "sel", "type": "uint32_t", "values": [0, 1] } + ] + } + ] + }, + { + "INPUT": "@HLSL_INPUT@", + "KEY": "k_f", + "COMPILE_OPTIONS": ["-T", "cs_6_8", "-DNBL_TEST_HAS_F"], + "CAPS": [ + { + "kind": "custom", + "struct": "f", + "members": [ + { "name": "min", "type": "float", "values": [1.17549435e-38] }, + { "name": "max", "type": "float", "values": [3.40282347e+38] }, + { "name": "neg", "type": "float", "values": [-1] }, + { "name": "exp", "type": "float", "values": ["1.25e-1"] } + ] + } + ] + }, + { + "INPUT": "@HLSL_INPUT@", + "KEY": "k_d", + "COMPILE_OPTIONS": ["-T", "cs_6_8", "-DNBL_TEST_HAS_D"], + "CAPS": [ + { + "kind": "custom", + "struct": "d", + "members": [ + { "name": "min", "type": "double", "values": ["2.2250738585072010e-308"] }, + { "name": "max", "type": "double", "values": ["1.7976931348623165e+308"] }, + { "name": "neg", "type": "double", "values": [-1.0] }, + { "name": "exp", "type": "double", "values": ["1.25e-1"] } + ] + } + ] + }, + { + "INPUT": "@HLSL_INPUT@", + "KEY": "k_mix", + "COMPILE_OPTIONS": ["-T", "cs_6_8", "-DNBL_TEST_HAS_M", "-DNBL_TEST_HAS_LIMITS", "-DNBL_TEST_HAS_FEATURES"], + "CAPS": [ + { + "kind": "custom", + "struct": "m", + "members": [ + { "name": "md", "type": "uint32_t", "values": [7] }, + { "name": "en", "type": "bool", "values": [1] }, + { "name": "sc", "type": "float", "values": [1] } + ] + }, + { + "kind": "limits", + "members": [ + { "name": "maxImageDimension2D", "type": "uint32_t", "values": [16384] } + ] + }, + { + "kind": "features", + "members": [ + { "name": "shaderCullDistance", "type": "bool", "values": [1] } + ] + } + ] + } +] +]=]) +string(CONFIGURE "${JSON_TEMPLATE}" JSON @ONLY) + +NBL_CREATE_NSC_COMPILE_RULES( + TARGET ${EXECUTABLE_NAME}SPIRV + LINK_TO ${EXECUTABLE_NAME} + BINARY_DIR ${OUTPUT_DIRECTORY} + MOUNT_POINT_DEFINE NBL_THIS_EXAMPLE_BUILD_MOUNT_POINT + COMMON_OPTIONS -I ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VAR KEYS + INCLUDE nbl/this_example/builtin/build/spirv/keys.hpp + NAMESPACE nbl::this_example::builtin::build + INPUTS ${JSON} + DISCARD_DEFAULT_GLOB +) diff --git a/73_SpirvKeysTest/input.hlsl b/73_SpirvKeysTest/input.hlsl new file mode 100644 index 000000000..b8ce7b132 --- /dev/null +++ b/73_SpirvKeysTest/input.hlsl @@ -0,0 +1,77 @@ +#include "nbl/builtin/hlsl/cpp_compat/basic.h" + +template +struct DummyCaps +{ +#if defined(NBL_TEST_HAS_I) + static const uint32_t u16 = Caps::i::u16; + static const uint32_t u32 = Caps::i::u32; +#endif +#if defined(NBL_TEST_HAS_M) + static const uint32_t md = Caps::m::md; + static const bool en = Caps::m::en; +#endif +#if defined(NBL_TEST_HAS_F) + static const float fmin = Caps::f::min; +#endif +#if defined(NBL_TEST_HAS_D) + static const double dmax = Caps::d::max; +#endif +#if defined(NBL_TEST_HAS_LIMITS) + static const uint32_t lim = Caps::maxImageDimension2D; +#endif +#if defined(NBL_TEST_HAS_FEATURES) + static const bool feat = Caps::shaderCullDistance; +#endif +#if defined(NBL_TEST_HAS_T) + static const uint32_t sel = Caps::t::sel; +#endif +}; + +template +uint32_t dummyValue() +{ + uint32_t v = 0u; +#if defined(NBL_TEST_HAS_I) + v += DummyCaps::u16 + DummyCaps::u32; +#endif +#if defined(NBL_TEST_HAS_M) + v += DummyCaps::md; + v += DummyCaps::en ? 1u : 0u; +#endif +#if defined(NBL_TEST_HAS_FEATURES) + if (DummyCaps::feat) + { +#if defined(NBL_TEST_HAS_LIMITS) + v += DummyCaps::lim; +#endif + } +#elif defined(NBL_TEST_HAS_LIMITS) + v += DummyCaps::lim; +#endif +#if defined(NBL_TEST_HAS_F) + float f = DummyCaps::fmin; + v += uint32_t(f); +#endif +#if defined(NBL_TEST_HAS_D) + double d = DummyCaps::dmax; + v += uint32_t(d); +#endif +#if defined(NBL_TEST_HAS_T) + v += DummyCaps::sel; +#endif + return v; +} + +[numthreads(1, 1, 1)] +[shader("compute")] +void main(uint3 tid : SV_DispatchThreadID) +{ + const uint32_t v = dummyValue(); + if (tid.x == 0u) + { + uint32_t sink = v; + if (sink == 0u) + return; + } +} diff --git a/73_SpirvKeysTest/main.cpp b/73_SpirvKeysTest/main.cpp new file mode 100644 index 000000000..dee9bbecd --- /dev/null +++ b/73_SpirvKeysTest/main.cpp @@ -0,0 +1,137 @@ +#include + +#include + +#include "nbl/application_templates/MonoDeviceApplication.hpp" +#include "nbl/this_example/builtin/build/spirv/keys.hpp" + +using namespace nbl; +using namespace nbl::core; +using namespace nbl::system; +using namespace nbl::video; +using namespace nbl::application_templates; + +static inline const nbl::video::ILogicalDevice* g_device = nullptr; + +#ifndef NBL_SPIRV_CFG +#error "NBL_SPIRV_CFG must be defined via target_compile_definitions" +#endif + +#define NBL_SPIRV_CFG_PREFIX NBL_SPIRV_CFG "/" + +template +constexpr bool buffer_equals(const Buffer& buf) +{ + constexpr size_t expected_size = sizeof(Expected.value) - 1; + if (buf.size() != expected_size) + return false; + for (size_t i = 0; i < expected_size; ++i) + { + if (buf.data()[i] != Expected.value[i]) + return false; + } + return true; +} + +template +bool check_key() +{ + constexpr auto keyBuf = nbl::this_example::builtin::build::get_spirv_key(Args...); + constexpr bool matches_ct = buffer_equals(keyBuf); + static_assert(matches_ct); + + if constexpr (requires { nbl::core::detail::SpirvKeyBuilder::build_from_device(static_cast(nullptr), Args...); }) + { + if (g_device) + return buffer_equals(nbl::this_example::builtin::build::get_spirv_key(g_device, Args...)); + } + + return buffer_equals(nbl::this_example::builtin::build::get_spirv_key(Args...)); +} + +static constexpr struct +{ + bool b1 = true; + bool b0 = false; + uint16_t u16 = 65535u; + uint32_t u32 = 123456789u; + uint64_t u64 = 1234567890123ull; + int16_t s16 = -32768; + int32_t s32 = -123456789; + int64_t s64 = -1234567890123ll; +} userI; + +static constexpr struct +{ + uint32_t sel = 1u; +} userT; + +static constexpr struct +{ + float min = std::numeric_limits::min(); + float max = std::numeric_limits::max(); + float neg = -1.0f; + float exp = 1.25e-1f; +} userF; + +static constexpr struct +{ + double min = std::numeric_limits::min(); + double max = std::numeric_limits::max(); + double neg = -1.0; + double exp = 1.25e-1; +} userD; + +static constexpr struct +{ + uint32_t md = 7u; + bool en = true; + float sc = 1.0f; +} userMix; + +static constexpr struct +{ + uint32_t maxImageDimension2D = 16384u; +} limits; + +static constexpr struct +{ + bool shaderCullDistance = true; +} features; + +class SpirvKeysTestApp final : public MonoDeviceApplication +{ + using device_base_t = MonoDeviceApplication; + +public: + SpirvKeysTestApp(const path& _localInputCWD, const path& _localOutputCWD, const path& _sharedInputCWD, const path& _sharedOutputCWD) : + IApplicationFramework(_localInputCWD, _localOutputCWD, _sharedInputCWD, _sharedOutputCWD) {} + + bool onAppInitialized(smart_refctd_ptr&& system) override + { + if (!device_base_t::onAppInitialized(smart_refctd_ptr(system))) + return false; + g_device = m_device.get(); + + bool ok = true; +#define SPIRV_KEY_TEST(KEY, EXPECTED, ...) ok &= check_key(); + SPIRV_KEY_TEST("k_plain", NBL_SPIRV_CFG_PREFIX "17607079465834866896.spv") + SPIRV_KEY_TEST("k_ints", NBL_SPIRV_CFG_PREFIX "14243079605119175996.spv", userI) + SPIRV_KEY_TEST("k_two", NBL_SPIRV_CFG_PREFIX "1951476947873668308.spv", userT) + SPIRV_KEY_TEST("k_f", NBL_SPIRV_CFG_PREFIX "13139524696082068358.spv", userF) + SPIRV_KEY_TEST("k_d", NBL_SPIRV_CFG_PREFIX "6202300474512380728.spv", userD) + SPIRV_KEY_TEST("k_mix", NBL_SPIRV_CFG_PREFIX "4015040960322118342.spv", userMix, limits, features) +#undef SPIRV_KEY_TEST + + if (!ok) + return logFail("SpirvKeysTest failed"); + + return true; + } + + void workLoopBody() override {} + + bool keepRunning() override { return false; } +}; + +NBL_MAIN_FUNC(SpirvKeysTestApp) diff --git a/CMakeLists.txt b/CMakeLists.txt index 66b82f37f..645e21deb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,6 +97,7 @@ if(NBL_BUILD_EXAMPLES) add_subdirectory(70_FLIPFluids) add_subdirectory(71_RayTracingPipeline) add_subdirectory(72_CooperativeBinarySearch) + add_subdirectory(73_SpirvKeysTest) # add new examples *before* NBL_GET_ALL_TARGETS invocation, it gathers recursively all targets created so far in this subdirectory NBL_GET_ALL_TARGETS(TARGETS)