mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-25 13:00:04 +00:00
Add spvParseVulkanEnv (#3142)
This new API lets clients request a minimal spv_target_env value that supports a given Vulkan and SPIR-V version, by a generic numbering scheme (as already defined by Vulkan and SPIR-V specs). This breaks a formal source dependency from Glslang to SPIRV-Tools. When a new API is rolled out, such as Vulkan 1.2, Glslang currently needs to reference a specific SPIRV-Tools enum by name.
This commit is contained in:
parent
dd37d73c5e
commit
bb236c326d
@ -473,6 +473,19 @@ SPIRV_TOOLS_EXPORT const char* spvTargetEnvDescription(spv_target_env env);
|
|||||||
// false and sets *env to SPV_ENV_UNIVERSAL_1_0.
|
// false and sets *env to SPV_ENV_UNIVERSAL_1_0.
|
||||||
SPIRV_TOOLS_EXPORT bool spvParseTargetEnv(const char* s, spv_target_env* env);
|
SPIRV_TOOLS_EXPORT bool spvParseTargetEnv(const char* s, spv_target_env* env);
|
||||||
|
|
||||||
|
// Determines the target env value with the least features but which enables
|
||||||
|
// the given Vulkan and SPIR-V versions. If such a target is supported, returns
|
||||||
|
// true and writes the value to |env|, otherwise returns false.
|
||||||
|
//
|
||||||
|
// The Vulkan version is given as an unsigned 32-bit number as specified in
|
||||||
|
// Vulkan section "29.2.1 Version Numbers": the major version number appears
|
||||||
|
// in bits 22 to 21, and the minor version is in bits 12 to 21. The SPIR-V
|
||||||
|
// version is given in the SPIR-V version header word: major version in bits
|
||||||
|
// 16 to 23, and minor version in bits 8 to 15.
|
||||||
|
SPIRV_TOOLS_EXPORT bool spvParseVulkanEnv(uint32_t vulkan_ver,
|
||||||
|
uint32_t spirv_ver,
|
||||||
|
spv_target_env* env);
|
||||||
|
|
||||||
// Creates a context object. Returns null if env is invalid.
|
// Creates a context object. Returns null if env is invalid.
|
||||||
SPIRV_TOOLS_EXPORT spv_context spvContextCreate(spv_target_env env);
|
SPIRV_TOOLS_EXPORT spv_context spvContextCreate(spv_target_env env);
|
||||||
|
|
||||||
|
@ -153,6 +153,34 @@ bool spvParseTargetEnv(const char* s, spv_target_env* env) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VULKAN_VER(MAJOR, MINOR) ((MAJOR << 22) | (MINOR << 12))
|
||||||
|
#define SPIRV_VER(MAJOR, MINOR) ((MAJOR << 16) | (MINOR << 8))
|
||||||
|
|
||||||
|
struct VulkanEnv {
|
||||||
|
spv_target_env vulkan_env;
|
||||||
|
uint32_t vulkan_ver;
|
||||||
|
uint32_t spirv_ver;
|
||||||
|
};
|
||||||
|
// Maps each Vulkan target environment enum to the Vulkan version, and the
|
||||||
|
// maximum supported SPIR-V version for that Vulkan environment.
|
||||||
|
// Keep this ordered from least capable to most capable.
|
||||||
|
static const VulkanEnv ordered_vulkan_envs[] = {
|
||||||
|
{SPV_ENV_VULKAN_1_0, VULKAN_VER(1, 0), SPIRV_VER(1, 0)},
|
||||||
|
{SPV_ENV_VULKAN_1_1, VULKAN_VER(1, 1), SPIRV_VER(1, 3)},
|
||||||
|
{SPV_ENV_VULKAN_1_1_SPIRV_1_4, VULKAN_VER(1, 1), SPIRV_VER(1, 4)},
|
||||||
|
{SPV_ENV_VULKAN_1_2, VULKAN_VER(1, 2), SPIRV_VER(1, 5)}};
|
||||||
|
|
||||||
|
bool spvParseVulkanEnv(uint32_t vulkan_ver, uint32_t spirv_ver,
|
||||||
|
spv_target_env* env) {
|
||||||
|
for (auto triple : ordered_vulkan_envs) {
|
||||||
|
if (triple.vulkan_ver >= vulkan_ver && triple.spirv_ver >= spirv_ver) {
|
||||||
|
*env = triple.vulkan_env;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool spvIsVulkanEnv(spv_target_env env) {
|
bool spvIsVulkanEnv(spv_target_env env) {
|
||||||
switch (env) {
|
switch (env) {
|
||||||
case SPV_ENV_UNIVERSAL_1_0:
|
case SPV_ENV_UNIVERSAL_1_0:
|
||||||
|
@ -63,11 +63,13 @@ struct ParseCase {
|
|||||||
|
|
||||||
using TargetParseTest = ::testing::TestWithParam<ParseCase>;
|
using TargetParseTest = ::testing::TestWithParam<ParseCase>;
|
||||||
|
|
||||||
TEST_P(TargetParseTest, InvalidTargetEnvProducesNull) {
|
TEST_P(TargetParseTest, Samples) {
|
||||||
spv_target_env env;
|
spv_target_env env;
|
||||||
bool parsed = spvParseTargetEnv(GetParam().input, &env);
|
bool parsed = spvParseTargetEnv(GetParam().input, &env);
|
||||||
EXPECT_THAT(parsed, Eq(GetParam().success));
|
EXPECT_THAT(parsed, Eq(GetParam().success));
|
||||||
EXPECT_THAT(env, Eq(GetParam().env));
|
if (parsed) {
|
||||||
|
EXPECT_THAT(env, Eq(GetParam().env));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
@ -103,5 +105,61 @@ INSTANTIATE_TEST_SUITE_P(
|
|||||||
{"abc", false, SPV_ENV_UNIVERSAL_1_0},
|
{"abc", false, SPV_ENV_UNIVERSAL_1_0},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// A test case for parsing an environment string.
|
||||||
|
struct ParseVulkanCase {
|
||||||
|
uint32_t vulkan;
|
||||||
|
uint32_t spirv;
|
||||||
|
bool success; // Expect to successfully parse?
|
||||||
|
spv_target_env env; // The parsed environment, if successful.
|
||||||
|
};
|
||||||
|
|
||||||
|
using TargetParseVulkanTest = ::testing::TestWithParam<ParseVulkanCase>;
|
||||||
|
|
||||||
|
TEST_P(TargetParseVulkanTest, Samples) {
|
||||||
|
spv_target_env env;
|
||||||
|
bool parsed = spvParseVulkanEnv(GetParam().vulkan, GetParam().spirv, &env);
|
||||||
|
EXPECT_THAT(parsed, Eq(GetParam().success));
|
||||||
|
if (parsed) {
|
||||||
|
EXPECT_THAT(env, Eq(GetParam().env));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VK(MAJ, MIN) ((MAJ << 22) | (MIN << 12))
|
||||||
|
#define SPV(MAJ, MIN) ((MAJ << 16) | (MIN << 8))
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
TargetVulkanParsing, TargetParseVulkanTest,
|
||||||
|
ValuesIn(std::vector<ParseVulkanCase>{
|
||||||
|
// Vulkan 1.0 cases
|
||||||
|
{VK(1, 0), SPV(1, 0), true, SPV_ENV_VULKAN_1_0},
|
||||||
|
{VK(1, 0), SPV(1, 1), true, SPV_ENV_VULKAN_1_1},
|
||||||
|
{VK(1, 0), SPV(1, 2), true, SPV_ENV_VULKAN_1_1},
|
||||||
|
{VK(1, 0), SPV(1, 3), true, SPV_ENV_VULKAN_1_1},
|
||||||
|
{VK(1, 0), SPV(1, 4), true, SPV_ENV_VULKAN_1_1_SPIRV_1_4},
|
||||||
|
{VK(1, 0), SPV(1, 5), true, SPV_ENV_VULKAN_1_2},
|
||||||
|
{VK(1, 0), SPV(1, 6), false, SPV_ENV_UNIVERSAL_1_0},
|
||||||
|
// Vulkan 1.1 cases
|
||||||
|
{VK(1, 1), SPV(1, 0), true, SPV_ENV_VULKAN_1_1},
|
||||||
|
{VK(1, 1), SPV(1, 1), true, SPV_ENV_VULKAN_1_1},
|
||||||
|
{VK(1, 1), SPV(1, 2), true, SPV_ENV_VULKAN_1_1},
|
||||||
|
{VK(1, 1), SPV(1, 3), true, SPV_ENV_VULKAN_1_1},
|
||||||
|
{VK(1, 1), SPV(1, 4), true, SPV_ENV_VULKAN_1_1_SPIRV_1_4},
|
||||||
|
{VK(1, 1), SPV(1, 5), true, SPV_ENV_VULKAN_1_2},
|
||||||
|
{VK(1, 1), SPV(1, 6), false, SPV_ENV_UNIVERSAL_1_0},
|
||||||
|
// Vulkan 1.2 cases
|
||||||
|
{VK(1, 2), SPV(1, 0), true, SPV_ENV_VULKAN_1_2},
|
||||||
|
{VK(1, 2), SPV(1, 1), true, SPV_ENV_VULKAN_1_2},
|
||||||
|
{VK(1, 2), SPV(1, 2), true, SPV_ENV_VULKAN_1_2},
|
||||||
|
{VK(1, 2), SPV(1, 3), true, SPV_ENV_VULKAN_1_2},
|
||||||
|
{VK(1, 2), SPV(1, 4), true, SPV_ENV_VULKAN_1_2},
|
||||||
|
{VK(1, 2), SPV(1, 5), true, SPV_ENV_VULKAN_1_2},
|
||||||
|
{VK(1, 2), SPV(1, 6), false, SPV_ENV_UNIVERSAL_1_0},
|
||||||
|
// Vulkan 1.3 cases
|
||||||
|
{VK(1, 3), SPV(1, 0), false, SPV_ENV_UNIVERSAL_1_0},
|
||||||
|
// Vulkan 2.0 cases
|
||||||
|
{VK(2, 0), SPV(1, 0), false, SPV_ENV_UNIVERSAL_1_0},
|
||||||
|
// Vulkan 99.0 cases
|
||||||
|
{VK(99, 0), SPV(1, 0), false, SPV_ENV_UNIVERSAL_1_0},
|
||||||
|
}));
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace spvtools
|
} // namespace spvtools
|
||||||
|
Loading…
Reference in New Issue
Block a user