Add Vulkan 1.1 capability sets

Fixes #1597

* Classifies useable capabilities for Vulkan 1.1
* Updates tests
This commit is contained in:
Alan Baker 2018-06-20 14:35:09 -04:00
parent 8d65c89678
commit e7ace1b280
2 changed files with 263 additions and 32 deletions

View File

@ -44,6 +44,16 @@ bool IsSupportGuaranteedVulkan_1_0(uint32_t capability) {
return false; return false;
} }
bool IsSupportGuaranteedVulkan_1_1(uint32_t capability) {
if (IsSupportGuaranteedVulkan_1_0(capability)) return true;
switch (capability) {
case SpvCapabilityDeviceGroup:
case SpvCapabilityMultiView:
return true;
}
return false;
}
bool IsSupportOptionalVulkan_1_0(uint32_t capability) { bool IsSupportOptionalVulkan_1_0(uint32_t capability) {
switch (capability) { switch (capability) {
case SpvCapabilityGeometry: case SpvCapabilityGeometry:
@ -77,6 +87,34 @@ bool IsSupportOptionalVulkan_1_0(uint32_t capability) {
return false; return false;
} }
bool IsSupportOptionalVulkan_1_1(uint32_t capability) {
if (IsSupportOptionalVulkan_1_0(capability)) return true;
switch (capability) {
case SpvCapabilityGroupNonUniform:
case SpvCapabilityGroupNonUniformVote:
case SpvCapabilityGroupNonUniformArithmetic:
case SpvCapabilityGroupNonUniformBallot:
case SpvCapabilityGroupNonUniformShuffle:
case SpvCapabilityGroupNonUniformShuffleRelative:
case SpvCapabilityGroupNonUniformClustered:
case SpvCapabilityGroupNonUniformQuad:
case SpvCapabilityDrawParameters:
// Alias SpvCapabilityStorageBuffer16BitAccess.
case SpvCapabilityStorageUniformBufferBlock16:
// Alias SpvCapabilityUniformAndStorageBuffer16BitAccess.
case SpvCapabilityStorageUniform16:
case SpvCapabilityStoragePushConstant16:
case SpvCapabilityStorageInputOutput16:
case SpvCapabilityDeviceGroup:
case SpvCapabilityMultiView:
case SpvCapabilityVariablePointersStorageBuffer:
case SpvCapabilityVariablePointers:
return true;
}
return false;
}
bool IsSupportGuaranteedOpenCL_1_2(uint32_t capability, bool embedded_profile) { bool IsSupportGuaranteedOpenCL_1_2(uint32_t capability, bool embedded_profile) {
switch (capability) { switch (capability) {
case SpvCapabilityAddresses: case SpvCapabilityAddresses:
@ -220,6 +258,15 @@ spv_result_t CapabilityPass(ValidationState_t& _,
<< " is not allowed by Vulkan 1.0 specification" << " is not allowed by Vulkan 1.0 specification"
<< " (or requires extension)"; << " (or requires extension)";
} }
} else if (env == SPV_ENV_VULKAN_1_1) {
if (!IsSupportGuaranteedVulkan_1_1(capability) &&
!IsSupportOptionalVulkan_1_1(capability) &&
!IsEnabledByExtension(_, capability)) {
return _.diag(SPV_ERROR_INVALID_CAPABILITY)
<< "Capability " << capability_str()
<< " is not allowed by Vulkan 1.1 specification"
<< " (or requires extension)";
}
} else if (env == SPV_ENV_OPENCL_1_2 || env == SPV_ENV_OPENCL_EMBEDDED_1_2) { } else if (env == SPV_ENV_OPENCL_1_2 || env == SPV_ENV_OPENCL_EMBEDDED_1_2) {
if (!IsSupportGuaranteedOpenCL_1_2(capability, opencl_embedded) && if (!IsSupportGuaranteedOpenCL_1_2(capability, opencl_embedded) &&
!IsSupportOptionalOpenCL_1_2(capability) && !IsSupportOptionalOpenCL_1_2(capability) &&

View File

@ -22,6 +22,7 @@
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include "source/assembly_grammar.h" #include "source/assembly_grammar.h"
#include "spirv_target_env.h"
#include "test_fixture.h" #include "test_fixture.h"
#include "unit_spirv.h" #include "unit_spirv.h"
#include "val_fixtures.h" #include "val_fixtures.h"
@ -109,6 +110,8 @@ using ValidateCapabilityV11 = spvtest::ValidateBase<CapTestParameter>;
using ValidateCapabilityVulkan10 = spvtest::ValidateBase<CapTestParameter>; using ValidateCapabilityVulkan10 = spvtest::ValidateBase<CapTestParameter>;
// Always assembles using OpenGL 4.0. // Always assembles using OpenGL 4.0.
using ValidateCapabilityOpenGL40 = spvtest::ValidateBase<CapTestParameter>; using ValidateCapabilityOpenGL40 = spvtest::ValidateBase<CapTestParameter>;
// Always assembles using Vulkan 1.1.
using ValidateCapabilityVulkan11 = spvtest::ValidateBase<CapTestParameter>;
TEST_F(ValidateCapability, Default) { TEST_F(ValidateCapability, Default) {
const char str[] = R"( const char str[] = R"(
@ -187,7 +190,26 @@ const vector<string>& AllCapabilities() {
"MultiViewport", "MultiViewport",
"SubgroupDispatch", "SubgroupDispatch",
"NamedBarrier", "NamedBarrier",
"PipeStorage"}; "PipeStorage",
"GroupNonUniform",
"GroupNonUniformVote",
"GroupNonUniformArithmetic",
"GroupNonUniformBallot",
"GroupNonUniformShuffle",
"GroupNonUniformShuffleRelative",
"GroupNonUniformClustered",
"GroupNonUniformQuad",
"DrawParameters",
"StorageBuffer16BitAccess",
"StorageUniformBufferBlock16",
"UniformAndStorageBuffer16BitAccess",
"StorageUniform16",
"StoragePushConstant16",
"StorageInputOutput16",
"DeviceGroup",
"MultiView",
"VariablePointersStorageBuffer",
"VariablePointers"};
return *r; return *r;
} }
@ -294,6 +316,66 @@ const vector<string>& AllVulkan10Capabilities() {
return *r; return *r;
} }
const vector<string>& AllVulkan11Capabilities() {
static const auto r = new vector<string>{
"",
"Matrix",
"Shader",
"InputAttachment",
"Sampled1D",
"Image1D",
"SampledBuffer",
"ImageBuffer",
"ImageQuery",
"DerivativeControl",
"Geometry",
"Tessellation",
"Float64",
"Int64",
"Int16",
"TessellationPointSize",
"GeometryPointSize",
"ImageGatherExtended",
"StorageImageMultisample",
"UniformBufferArrayDynamicIndexing",
"SampledImageArrayDynamicIndexing",
"StorageBufferArrayDynamicIndexing",
"StorageImageArrayDynamicIndexing",
"ClipDistance",
"CullDistance",
"ImageCubeArray",
"SampleRateShading",
"SparseResidency",
"MinLod",
"SampledCubeArray",
"ImageMSArray",
"StorageImageExtendedFormats",
"InterpolationFunction",
"StorageImageReadWithoutFormat",
"StorageImageWriteWithoutFormat",
"MultiViewport",
"GroupNonUniform",
"GroupNonUniformVote",
"GroupNonUniformArithmetic",
"GroupNonUniformBallot",
"GroupNonUniformShuffle",
"GroupNonUniformShuffleRelative",
"GroupNonUniformClustered",
"GroupNonUniformQuad",
"DrawParameters",
"StorageBuffer16BitAccess",
"StorageUniformBufferBlock16",
"UniformAndStorageBuffer16BitAccess",
"StorageUniform16",
"StoragePushConstant16",
"StorageInputOutput16",
"DeviceGroup",
"MultiView",
"VariablePointersStorageBuffer",
"VariablePointers"};
return *r;
}
const vector<string>& MatrixDependencies() { const vector<string>& MatrixDependencies() {
static const auto r = new vector<string>{ static const auto r = new vector<string>{
"Matrix", "Matrix",
@ -328,7 +410,11 @@ const vector<string>& MatrixDependencies() {
"GeometryStreams", "GeometryStreams",
"StorageImageReadWithoutFormat", "StorageImageReadWithoutFormat",
"StorageImageWriteWithoutFormat", "StorageImageWriteWithoutFormat",
"MultiViewport"}; "MultiViewport",
"DrawParameters",
"MultiView",
"VariablePointersStorageBuffer",
"VariablePointers"};
return *r; return *r;
} }
@ -365,7 +451,11 @@ const vector<string>& ShaderDependencies() {
"GeometryStreams", "GeometryStreams",
"StorageImageReadWithoutFormat", "StorageImageReadWithoutFormat",
"StorageImageWriteWithoutFormat", "StorageImageWriteWithoutFormat",
"MultiViewport"}; "MultiViewport",
"DrawParameters",
"MultiView",
"VariablePointersStorageBuffer",
"VariablePointers"};
return *r; return *r;
} }
@ -415,6 +505,31 @@ const vector<string>& KernelDependencies() {
return *r; return *r;
} }
const vector<string>& KernelAndGroupNonUniformDependencies() {
static const auto r = new vector<string>{
"Kernel",
"Vector16",
"Float16Buffer",
"ImageBasic",
"ImageReadWrite",
"ImageMipmap",
"Pipes",
"DeviceEnqueue",
"LiteralSampler",
"SubgroupDispatch",
"NamedBarrier",
"PipeStorage",
"GroupNonUniform",
"GroupNonUniformVote",
"GroupNonUniformArithmetic",
"GroupNonUniformBallot",
"GroupNonUniformShuffle",
"GroupNonUniformShuffleRelative",
"GroupNonUniformClustered",
"GroupNonUniformQuad"};
return *r;
}
const vector<string>& AddressesDependencies() { const vector<string>& AddressesDependencies() {
static const auto r = new vector<string>{ static const auto r = new vector<string>{
"Addresses", "Addresses",
@ -1287,7 +1402,7 @@ make_pair(string(kGLSL450MemoryModel) +
"OpEntryPoint Vertex %func \"shader\" \n" + "OpEntryPoint Vertex %func \"shader\" \n" +
"OpDecorate %intt BuiltIn SubgroupSize\n" "OpDecorate %intt BuiltIn SubgroupSize\n"
"%intt = OpTypeInt 32 0\n" + string(kVoidFVoid), "%intt = OpTypeInt 32 0\n" + string(kVoidFVoid),
KernelDependencies()), KernelAndGroupNonUniformDependencies()),
make_pair(string(kGLSL450MemoryModel) + make_pair(string(kGLSL450MemoryModel) +
"OpEntryPoint Vertex %func \"shader\" \n" + "OpEntryPoint Vertex %func \"shader\" \n" +
"OpDecorate %intt BuiltIn SubgroupMaxSize\n" "OpDecorate %intt BuiltIn SubgroupMaxSize\n"
@ -1297,7 +1412,7 @@ make_pair(string(kGLSL450MemoryModel) +
"OpEntryPoint Vertex %func \"shader\" \n" + "OpEntryPoint Vertex %func \"shader\" \n" +
"OpDecorate %intt BuiltIn NumSubgroups\n" "OpDecorate %intt BuiltIn NumSubgroups\n"
"%intt = OpTypeInt 32 0\n" + string(kVoidFVoid), "%intt = OpTypeInt 32 0\n" + string(kVoidFVoid),
KernelDependencies()), KernelAndGroupNonUniformDependencies()),
make_pair(string(kGLSL450MemoryModel) + make_pair(string(kGLSL450MemoryModel) +
"OpEntryPoint Vertex %func \"shader\" \n" + "OpEntryPoint Vertex %func \"shader\" \n" +
"OpDecorate %intt BuiltIn NumEnqueuedSubgroups\n" "OpDecorate %intt BuiltIn NumEnqueuedSubgroups\n"
@ -1307,12 +1422,12 @@ make_pair(string(kGLSL450MemoryModel) +
"OpEntryPoint Vertex %func \"shader\" \n" + "OpEntryPoint Vertex %func \"shader\" \n" +
"OpDecorate %intt BuiltIn SubgroupId\n" "OpDecorate %intt BuiltIn SubgroupId\n"
"%intt = OpTypeInt 32 0\n" + string(kVoidFVoid), "%intt = OpTypeInt 32 0\n" + string(kVoidFVoid),
KernelDependencies()), KernelAndGroupNonUniformDependencies()),
make_pair(string(kGLSL450MemoryModel) + make_pair(string(kGLSL450MemoryModel) +
"OpEntryPoint Vertex %func \"shader\" \n" + "OpEntryPoint Vertex %func \"shader\" \n" +
"OpDecorate %intt BuiltIn SubgroupLocalInvocationId\n" "OpDecorate %intt BuiltIn SubgroupLocalInvocationId\n"
"%intt = OpTypeInt 32 0\n" + string(kVoidFVoid), "%intt = OpTypeInt 32 0\n" + string(kVoidFVoid),
KernelDependencies()), KernelAndGroupNonUniformDependencies()),
make_pair(string(kOpenCLMemoryModel) + make_pair(string(kOpenCLMemoryModel) +
"OpEntryPoint Kernel %func \"compute\" \n" + "OpEntryPoint Kernel %func \"compute\" \n" +
"OpDecorate %intt BuiltIn VertexIndex\n" "OpDecorate %intt BuiltIn VertexIndex\n"
@ -1384,6 +1499,23 @@ make_pair(string(kGLSL450MemoryModel) +
AllSpirV10Capabilities()) AllSpirV10Capabilities())
)),); )),);
INSTANTIATE_TEST_CASE_P(Capabilities, ValidateCapabilityVulkan11,
Combine(
// All capabilities to try.
ValuesIn(AllCapabilities()),
Values(
make_pair(string(kGLSL450MemoryModel) +
"OpEntryPoint Vertex %func \"shader\" \n" +
"OpDecorate %intt BuiltIn PointSize\n"
"%intt = OpTypeInt 32 0\n" + string(kVoidFVoid),
AllVulkan11Capabilities()),
make_pair(string(kGLSL450MemoryModel) +
"OpEntryPoint Vertex %func \"shader\" \n" +
"OpDecorate %intt BuiltIn CullDistance\n"
"%intt = OpTypeInt 32 0\n" + string(kVoidFVoid),
AllVulkan11Capabilities())
)),);
// TODO(umar): Selection Control // TODO(umar): Selection Control
// TODO(umar): Loop Control // TODO(umar): Loop Control
// TODO(umar): Function Control // TODO(umar): Function Control
@ -1460,21 +1592,53 @@ INSTANTIATE_TEST_CASE_P(
// TODO(umar): Instruction capability checks // TODO(umar): Instruction capability checks
// True if capability exists in env. spv_result_t spvCoreOperandTableNameLookup(spv_target_env env,
const spv_operand_table table,
const spv_operand_type_t type,
const char* name,
const size_t nameLength) {
if (!table) return SPV_ERROR_INVALID_TABLE;
if (!name) return SPV_ERROR_INVALID_POINTER;
for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
const auto& group = table->types[typeIndex];
if (type != group.type) continue;
for (uint64_t index = 0; index < group.count; ++index) {
const auto& entry = group.entries[index];
// Check for min version only.
if (spvVersionForTargetEnv(env) >= entry.minVersion &&
nameLength == strlen(entry.name) &&
!strncmp(entry.name, name, nameLength)) {
return SPV_SUCCESS;
}
}
}
return SPV_ERROR_INVALID_LOOKUP;
}
// True if capability exists in core spec of env.
bool Exists(const std::string& capability, spv_target_env env) { bool Exists(const std::string& capability, spv_target_env env) {
spv_operand_desc dummy; ScopedContext sc(env);
return SPV_SUCCESS == libspirv::AssemblyGrammar(ScopedContext(env).context) return SPV_SUCCESS ==
.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY, spvCoreOperandTableNameLookup(env, sc.context->operand_table,
capability.c_str(), SPV_OPERAND_TYPE_CAPABILITY,
capability.size(), &dummy); capability.c_str(), capability.size());
} }
TEST_P(ValidateCapability, Capability) { TEST_P(ValidateCapability, Capability) {
const string capability = Capability(GetParam()); const string capability = Capability(GetParam());
spv_target_env env = spv_target_env env = SPV_ENV_UNIVERSAL_1_0;
(capability.empty() || Exists(capability, SPV_ENV_UNIVERSAL_1_0)) if (!capability.empty()) {
? SPV_ENV_UNIVERSAL_1_0 if (Exists(capability, SPV_ENV_UNIVERSAL_1_0))
: SPV_ENV_UNIVERSAL_1_1; env = SPV_ENV_UNIVERSAL_1_0;
else if (Exists(capability, SPV_ENV_UNIVERSAL_1_1))
env = SPV_ENV_UNIVERSAL_1_1;
else if (Exists(capability, SPV_ENV_UNIVERSAL_1_2))
env = SPV_ENV_UNIVERSAL_1_2;
else
env = SPV_ENV_UNIVERSAL_1_3;
}
const string test_code = MakeAssembly(GetParam()); const string test_code = MakeAssembly(GetParam());
CompileSuccessfully(test_code, env); CompileSuccessfully(test_code, env);
ASSERT_EQ(ExpectedResult(GetParam()), ValidateInstructions(env)) ASSERT_EQ(ExpectedResult(GetParam()), ValidateInstructions(env))
@ -1483,27 +1647,47 @@ TEST_P(ValidateCapability, Capability) {
} }
TEST_P(ValidateCapabilityV11, Capability) { TEST_P(ValidateCapabilityV11, Capability) {
const string test_code = MakeAssembly(GetParam()); const string capability = Capability(GetParam());
CompileSuccessfully(test_code, SPV_ENV_UNIVERSAL_1_1); if (Exists(capability, SPV_ENV_UNIVERSAL_1_1)) {
ASSERT_EQ(ExpectedResult(GetParam()), const string test_code = MakeAssembly(GetParam());
ValidateInstructions(SPV_ENV_UNIVERSAL_1_1)) CompileSuccessfully(test_code, SPV_ENV_UNIVERSAL_1_1);
<< test_code; ASSERT_EQ(ExpectedResult(GetParam()),
ValidateInstructions(SPV_ENV_UNIVERSAL_1_1))
<< test_code;
}
} }
TEST_P(ValidateCapabilityVulkan10, Capability) { TEST_P(ValidateCapabilityVulkan10, Capability) {
const string test_code = MakeAssembly(GetParam()); const string capability = Capability(GetParam());
CompileSuccessfully(test_code, SPV_ENV_VULKAN_1_0); if (Exists(capability, SPV_ENV_VULKAN_1_0)) {
ASSERT_EQ(ExpectedResult(GetParam()), const string test_code = MakeAssembly(GetParam());
ValidateInstructions(SPV_ENV_VULKAN_1_0)) CompileSuccessfully(test_code, SPV_ENV_VULKAN_1_0);
<< test_code; ASSERT_EQ(ExpectedResult(GetParam()),
ValidateInstructions(SPV_ENV_VULKAN_1_0))
<< test_code;
}
}
TEST_P(ValidateCapabilityVulkan11, Capability) {
const string capability = Capability(GetParam());
if (Exists(capability, SPV_ENV_VULKAN_1_1)) {
const string test_code = MakeAssembly(GetParam());
CompileSuccessfully(test_code, SPV_ENV_VULKAN_1_1);
ASSERT_EQ(ExpectedResult(GetParam()),
ValidateInstructions(SPV_ENV_VULKAN_1_1))
<< test_code;
}
} }
TEST_P(ValidateCapabilityOpenGL40, Capability) { TEST_P(ValidateCapabilityOpenGL40, Capability) {
const string test_code = MakeAssembly(GetParam()); const string capability = Capability(GetParam());
CompileSuccessfully(test_code, SPV_ENV_OPENGL_4_0); if (Exists(capability, SPV_ENV_OPENGL_4_0)) {
ASSERT_EQ(ExpectedResult(GetParam()), const string test_code = MakeAssembly(GetParam());
ValidateInstructions(SPV_ENV_OPENGL_4_0)) CompileSuccessfully(test_code, SPV_ENV_OPENGL_4_0);
<< test_code; ASSERT_EQ(ExpectedResult(GetParam()),
ValidateInstructions(SPV_ENV_OPENGL_4_0))
<< test_code;
}
} }
TEST_F(ValidateCapability, SemanticsIdIsAnIdNotALiteral) { TEST_F(ValidateCapability, SemanticsIdIsAnIdNotALiteral) {