Skip to content

Commit 768b7cf

Browse files
committed
more properties, validation, logs and args for NBL_CREATE_NSC_COMPILE_RULES, update examples_tests
1 parent 172d9b3 commit 768b7cf

File tree

2 files changed

+162
-26
lines changed

2 files changed

+162
-26
lines changed

cmake/common.cmake

Lines changed: 161 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,8 @@ function(NBL_PARSE_REQUIRED PREFIX)
12381238
endforeach()
12391239
endfunction()
12401240

1241+
# TODO: could create them in the function as <TARGET>_<PROPERTY> properties
1242+
12411243
define_property(SOURCE PROPERTY NBL_SPIRV_REGISTERED_INPUT
12421244
BRIEF_DOCS "Absolute path to input shader which will be glued with device permutation config caps auto-gen file using #include directive, used as part of NSC compile rule to produce SPIRV output"
12431245
)
@@ -1247,13 +1249,30 @@ define_property(SOURCE PROPERTY NBL_SPIRV_PERMUTATION_CONFIG
12471249
FULL_DOCS "The file is auto-generated at configuration time, contains DeviceConfigCaps struct with permuted device caps after which #include directive glues it with an input shader"
12481250
)
12491251

1252+
define_property(SOURCE PROPERTY NBL_SPIRV_BINARY_DIR
1253+
BRIEF_DOCS "a <SPIRV output> = NBL_SPIRV_BINARY_DIR/NBL_SPIRV_ACCESS_KEY"
1254+
)
1255+
define_property(SOURCE PROPERTY NBL_SPIRV_ACCESS_KEY
1256+
BRIEF_DOCS "a <SPIRV output> = NBL_SPIRV_BINARY_DIR/NBL_SPIRV_ACCESS_KEY"
1257+
)
1258+
1259+
define_property(TARGET PROPERTY NBL_CANONICAL_IDENTIFIERS
1260+
BRIEF_DOCS "List of identifiers composed as NBL_SPIRV_BINARY_DIR/KEY"
1261+
FULL_DOCS "For a given NBL_SPIRV_BINARY_DIR we define a set of canonical KEYs, each unique given which at runtime one can get SPIRV key to access <SPIRV output> by the canonical key which may contain special permutation part in character of <key>(.<name>=<value>)(.<name>=<value>)(...)"
1262+
)
1263+
12501264
define_property(TARGET PROPERTY NBL_SPIRV_OUTPUTS
1251-
BRIEF_DOCS "Absolute paths to SPIRV outputs, part of NSC compile rules"
1265+
BRIEF_DOCS "Absolute paths to all <SPIRV output>s which are part of NSC compile rules"
12521266
)
12531267

1254-
# NBL_SPIRV_OUTPUT = NBL_SPIRV_BINARY_DIR/NBL_SPIRV_ACCESS_KEY
1255-
define_property(SOURCE PROPERTY NBL_SPIRV_BINARY_DIR)
1256-
define_property(SOURCE PROPERTY NBL_SPIRV_ACCESS_KEY)
1268+
define_property(TARGET PROPERTY NBL_HEADER_PATH
1269+
BRIEF_DOCS "Relative path for auto-gen include file with key getters"
1270+
)
1271+
define_property(TARGET PROPERTY NBL_HEADER_GENERATED_RULE)
1272+
1273+
define_property(TARGET PROPERTY NBL_HEADER_CONTENT
1274+
BRIEF_DOCS "Contains NBL_HEADER_PATH's content"
1275+
)
12571276

12581277
function(NBL_CREATE_NSC_COMPILE_RULES)
12591278
set(COMMENT "this code has been autogenerated with Nabla CMake NBL_CREATE_HLSL_COMPILE_RULES utility")
@@ -1301,14 +1320,67 @@ struct DeviceConfigCaps
13011320
)
13021321
endif()
13031322

1304-
set(REQUIRED_SINGLE_ARGS TARGET BINARY_DIR OUTPUT_VAR INPUTS)
1323+
set(REQUIRED_SINGLE_ARGS TARGET BINARY_DIR OUTPUT_VAR INPUTS INCLUDE NAMESPACE)
13051324
cmake_parse_arguments(IMPL "" "${REQUIRED_SINGLE_ARGS}" "COMMON_OPTIONS" ${ARGV})
13061325
NBL_PARSE_REQUIRED(IMPL ${REQUIRED_SINGLE_ARGS})
13071326

13081327
if(NOT TARGET ${IMPL_TARGET})
13091328
add_library(${IMPL_TARGET} INTERFACE)
13101329
endif()
13111330

1331+
if(IS_ABSOLUTE "${IMPL_INCLUDE}")
1332+
message(FATAL_ERROR "INCLUDE argument must be relative path")
1333+
endif()
1334+
1335+
set_target_properties(${IMPL_TARGET} PROPERTIES NBL_HEADER_PATH "${IMPL_INCLUDE}")
1336+
1337+
get_target_property(HEADER_RULE_GENERATED ${IMPL_TARGET} NBL_HEADER_GENERATED_RULE)
1338+
if(NOT HEADER_RULE_GENERATED)
1339+
set(INCLUDE_DIR "$<TARGET_PROPERTY:${IMPL_TARGET},BINARY_DIR>/${IMPL_TARGET}/.cmake/include")
1340+
set(INCLUDE_FILE "${INCLUDE_DIR}/$<TARGET_PROPERTY:${IMPL_TARGET},NBL_HEADER_PATH>")
1341+
set(INCLUDE_CONTENT $<TARGET_PROPERTY:${IMPL_TARGET},NBL_HEADER_CONTENT>)
1342+
1343+
file(GENERATE OUTPUT ${INCLUDE_FILE}
1344+
CONTENT ${INCLUDE_CONTENT}
1345+
TARGET ${IMPL_TARGET}
1346+
)
1347+
1348+
target_include_directories(${IMPL_TARGET} INTERFACE ${INCLUDE_DIR})
1349+
set_target_properties(${IMPL_TARGET} PROPERTIES NBL_HEADER_GENERATED_RULE ON)
1350+
1351+
set(HEADER_ITEM_VIEW [=[
1352+
#include "nabla.h"
1353+
1354+
]=])
1355+
set_property(TARGET ${IMPL_TARGET} APPEND_STRING PROPERTY NBL_HEADER_CONTENT "${HEADER_ITEM_VIEW}")
1356+
endif()
1357+
1358+
string(MAKE_C_IDENTIFIER "${IMPL_TARGET}_${IMPL_NAMESPACE}" NS_IMPL_KEYS_PROPERTY)
1359+
get_property(NS_IMPL_KEYS_PROPERTY_DEFINED
1360+
TARGET ${IMPL_TARGET}
1361+
PROPERTY "${NS_IMPL_KEYS_PROPERTY}"
1362+
DEFINED
1363+
)
1364+
if(NOT NS_IMPL_KEYS_PROPERTY_DEFINED)
1365+
set(HEADER_ITEM_VIEW [=[
1366+
namespace @IMPL_NAMESPACE@ {
1367+
template<nbl::core::StringLiteral Key>
1368+
inline const nbl::core::string get_spirv_key(const nbl::video::SPhysicalDeviceLimits& limits, const nbl::video::SPhysicalDeviceFeatures& features);
1369+
1370+
template<nbl::core::StringLiteral Key>
1371+
inline const nbl::core::string get_spirv_key(const nbl::video::ILogicalDevice* device)
1372+
{
1373+
return get_spirv_key<Key>(device->getPhysicalDevice()->getLimits(), device->getEnabledFeatures());
1374+
}
1375+
}
1376+
1377+
]=])
1378+
string(CONFIGURE "${HEADER_ITEM_VIEW}" HEADER_ITEM_EVAL @ONLY)
1379+
set_property(TARGET ${IMPL_TARGET} APPEND_STRING PROPERTY NBL_HEADER_CONTENT "${HEADER_ITEM_EVAL}")
1380+
define_property(TARGET PROPERTY "${NS_IMPL_KEYS_PROPERTY}")
1381+
endif()
1382+
1383+
13121384
string(JSON JSON_LENGTH LENGTH "${IMPL_INPUTS}")
13131385
math(EXPR LAST_INDEX "${JSON_LENGTH} - 1")
13141386

@@ -1349,21 +1421,55 @@ struct DeviceConfigCaps
13491421
endif()
13501422
endif()
13511423

1424+
function(ERROR_WHILE_PARSING_ITEM)
1425+
string(JSON ITEM GET "${IMPL_INPUTS}" ${INDEX})
1426+
message(FATAL_ERROR
1427+
"While parsing ${IMPL_TARGET}'s NSC compile rule\n${ITEM}\n"
1428+
${ARGV}
1429+
)
1430+
endfunction()
1431+
13521432
set(CAP_NAMES "")
13531433
set(CAP_TYPES "")
13541434
if(HAS_CAPS)
13551435
math(EXPR LAST_CAP "${CAPS_LENGTH} - 1")
13561436
foreach(CAP_IDX RANGE 0 ${LAST_CAP})
13571437
string(JSON CAP_NAME GET "${IMPL_INPUTS}" ${INDEX} CAPS ${CAP_IDX} name)
13581438
string(JSON CAP_TYPE GET "${IMPL_INPUTS}" ${INDEX} CAPS ${CAP_IDX} type)
1359-
string(JSON CAP_VALUES_LENGTH LENGTH "${IMPL_INPUTS}" ${INDEX} CAPS ${CAP_IDX} values)
13601439

1361-
set(VALUES "")
1362-
math(EXPR LAST_VAL "${CAP_VALUES_LENGTH} - 1")
1363-
foreach(VAL_IDX RANGE 0 ${LAST_VAL})
1364-
string(JSON VALUE GET "${IMPL_INPUTS}" ${INDEX} CAPS ${CAP_IDX} values ${VAL_IDX})
1365-
list(APPEND VALUES "${VALUE}")
1366-
endforeach()
1440+
if(NOT CAP_TYPE MATCHES "^(bool|uint16_t|uint32_t|uint64_t)$")
1441+
ERROR_WHILE_PARSING_ITEM(
1442+
"Invalid CAP type \"${CAP_TYPE}\" for ${CAP_NAME}\n"
1443+
"Allowed types are: bool, uint16_t, uint32_t, uint64_t"
1444+
)
1445+
endif()
1446+
1447+
string(JSON CAP_VALUES_LENGTH LENGTH "${IMPL_INPUTS}" ${INDEX} CAPS ${CAP_IDX} values)
1448+
1449+
set(VALUES "")
1450+
math(EXPR LAST_VAL "${CAP_VALUES_LENGTH} - 1")
1451+
foreach(VAL_IDX RANGE 0 ${LAST_VAL})
1452+
string(JSON VALUE GET "${IMPL_INPUTS}" ${INDEX} CAPS ${CAP_IDX} values ${VAL_IDX})
1453+
string(JSON VAL_TYPE TYPE "${IMPL_INPUTS}" ${INDEX} CAPS ${CAP_IDX} values ${VAL_IDX})
1454+
1455+
if(NOT VAL_TYPE STREQUAL "NUMBER")
1456+
ERROR_WHILE_PARSING_ITEM(
1457+
"Invalid CAP value \"${VALUE}\" for CAP \"${CAP_NAME}\" of type ${CAP_TYPE}\n"
1458+
"Use numbers for uint*_t and 0/1 for bools."
1459+
)
1460+
endif()
1461+
1462+
if(CAP_TYPE STREQUAL "bool")
1463+
if(NOT VALUE MATCHES "^[01]$")
1464+
ERROR_WHILE_PARSING_ITEM(
1465+
"Invalid bool value \"${VALUE}\" for ${CAP_NAME}\n"
1466+
"Boolean CAPs can only have values 0 or 1."
1467+
)
1468+
endif()
1469+
endif()
1470+
1471+
list(APPEND VALUES "${VALUE}")
1472+
endforeach()
13671473

13681474
set(CAP_VALUES_${CAP_IDX} "${VALUES}")
13691475
list(APPEND CAP_NAMES "${CAP_NAME}")
@@ -1378,9 +1484,47 @@ struct DeviceConfigCaps
13781484
set(TARGET_INPUT "${CMAKE_CURRENT_SOURCE_DIR}/${TARGET_INPUT}")
13791485
endif()
13801486

1487+
get_target_property(CANONICAL_IDENTIFIERS ${IMPL_TARGET} NBL_CANONICAL_IDENTIFIERS)
1488+
1489+
set(NEW_CANONICAL_IDENTIFIER "${IMPL_BINARY_DIR}/${BASE_KEY}")
1490+
if(CANONICAL_IDENTIFIERS)
1491+
list(FIND CANONICAL_IDENTIFIERS "${NEW_CANONICAL_IDENTIFIER}" FOUND)
1492+
1493+
if(NOT FOUND STREQUAL -1)
1494+
string(JSON ITEM GET "${IMPL_INPUTS}" ${INDEX})
1495+
message(FATAL_ERROR "While parsing ${IMPL_TARGET}'s NSC compile rule\n${ITEM}\nwith binary directory \"${IMPL_BINARY_DIR}\",\ncanonical key \"${BASE_KEY}\" already defined!")
1496+
endif()
1497+
endif()
1498+
1499+
set_property(TARGET ${IMPL_TARGET} APPEND PROPERTY NBL_CANONICAL_IDENTIFIERS "${NEW_CANONICAL_IDENTIFIER}")
1500+
1501+
set(HEADER_ITEM_VIEW [=[
1502+
namespace @IMPL_NAMESPACE@ {
1503+
template<>
1504+
inline const nbl::core::string get_spirv_key<NBL_CORE_UNIQUE_STRING_LITERAL_TYPE("@BASE_KEY@")>
1505+
(const nbl::video::SPhysicalDeviceLimits& limits, const nbl::video::SPhysicalDeviceFeatures& features)
1506+
{
1507+
nbl::core::string retval = "@BASE_KEY@";
1508+
@RETVAL_EVAL@
1509+
retval += ".spv";
1510+
return retval;
1511+
}
1512+
}
1513+
1514+
]=])
1515+
unset(RETVAL_EVAL)
1516+
foreach(CAP ${CAP_NAMES})
1517+
string(CONFIGURE [=[
1518+
retval += ".@CAP@_" + std::to_string(limits.@CAP@);
1519+
]=] RETVALUE_VIEW @ONLY)
1520+
string(APPEND RETVAL_EVAL "${RETVALUE_VIEW}")
1521+
endforeach(CAP)
1522+
string(CONFIGURE "${HEADER_ITEM_VIEW}" HEADER_ITEM_EVAL @ONLY)
1523+
set_property(TARGET ${IMPL_TARGET} APPEND_STRING PROPERTY NBL_HEADER_CONTENT "${HEADER_ITEM_EVAL}")
1524+
13811525
function(GENERATE_KEYS PREFIX CAP_INDEX CAPS_EVAL_PART)
13821526
if(NUM_CAPS EQUAL 0 OR CAP_INDEX EQUAL ${NUM_CAPS})
1383-
set(FINAL_KEY "${BASE_KEY}${PREFIX}")
1527+
set(FINAL_KEY "${BASE_KEY}${PREFIX}.spv") # always add ext even if its already there to make sure asset loader always is able to load as IShader
13841528

13851529
set(TARGET_OUTPUT "${IMPL_BINARY_DIR}/${FINAL_KEY}")
13861530
set(CONFIG_FILE "${TARGET_OUTPUT}.config")
@@ -1420,7 +1564,6 @@ struct DeviceConfigCaps
14201564
)
14211565

14221566
set_property(TARGET ${IMPL_TARGET} APPEND PROPERTY NBL_SPIRV_OUTPUTS "${TARGET_OUTPUT}")
1423-
14241567
return()
14251568
endif()
14261569

@@ -1430,7 +1573,7 @@ struct DeviceConfigCaps
14301573
set(VALUES "${${VAR_NAME}}")
14311574

14321575
foreach(V IN LISTS VALUES)
1433-
set(NEW_PREFIX "${PREFIX}.${CURRENT_CAP}=${V}")
1576+
set(NEW_PREFIX "${PREFIX}.${CURRENT_CAP}_${V}")
14341577
set(NEW_EVAL "${CAPS_EVAL_PART}NBL_CONSTEXPR_STATIC_INLINE ${CURRENT_TYPE} ${CURRENT_CAP} = (${CURRENT_TYPE}) ${V}; // got permuted\n")
14351578
math(EXPR NEXT_INDEX "${CAP_INDEX} + 1")
14361579
GENERATE_KEYS("${NEW_PREFIX}" "${NEXT_INDEX}" "${NEW_EVAL}")
@@ -1440,6 +1583,7 @@ struct DeviceConfigCaps
14401583
GENERATE_KEYS("" 0 "")
14411584
endforeach()
14421585

1586+
unset(KEYS)
14431587
get_target_property(SPIRVs ${IMPL_TARGET} NBL_SPIRV_OUTPUTS)
14441588
foreach(SPIRV ${SPIRVs})
14451589
get_source_file_property(CONFIG ${SPIRV} NBL_SPIRV_PERMUTATION_CONFIG)
@@ -1449,15 +1593,6 @@ struct DeviceConfigCaps
14491593
list(APPEND CONFIGS ${CONFIG})
14501594
list(APPEND INPUTS ${INPUT})
14511595
list(APPEND KEYS ${ACCESS_KEY})
1452-
1453-
if(NBL_LOG_VERBOSE)
1454-
get_source_file_property(BINARY_DIR ${SPIRV} NBL_SPIRV_BINARY_DIR)
1455-
message(STATUS "[${IMPL_TARGET}'s SPIRV]: ${SPIRV}")
1456-
message(STATUS "-- BINARY_DIR: ${BINARY_DIR}")
1457-
message(STATUS "-- ACCESS_KEY: ${ACCESS_KEY}")
1458-
message(STATUS "-- CONFIG: ${CONFIG}")
1459-
message(STATUS "-- INPUT: ${INPUT}")
1460-
endif()
14611596
endforeach()
14621597

14631598
set(RTE "NSC Rules")
@@ -1499,8 +1634,9 @@ function(NBL_CREATE_RESOURCE_ARCHIVE)
14991634

15001635
ADD_CUSTOM_BUILTIN_RESOURCES(${IMPL_TARGET} NBL_RESOURCES_TO_EMBED "${_BUNDLE_SEARCH_DIRECTORY_}" "${_BUNDLE_ARCHIVE_ABSOLUTE_PATH_}" "${_BUILTIN_RESOURCES_NAMESPACE_}" "${_OUTPUT_DIRECTORY_HEADER_}" "${_OUTPUT_DIRECTORY_SOURCE_}" "${_LINK_MODE_}")
15011636
else()
1502-
add_library(${IMPL_TARGET} INTERFACE)
1637+
add_library(${IMPL_TARGET} INTERFACE) # (***)
15031638
endif()
15041639

1640+
# TODO (***): actually I better have this in meta target created by NBL_CREATE_NSC_COMPILE_RULES, then I kill its INTERFACE when builtins are off
15051641
target_compile_definitions(${IMPL_TARGET} INTERFACE ${IMPL_MOUNT_POINT_DEFINE}="${_BUNDLE_SEARCH_DIRECTORY_}")
15061642
endfunction()

0 commit comments

Comments
 (0)