Support SPV_KHR_vulkan_memory_model rev2

Support collapsed into one commit:
- Asm/Dis support for SPV_KHR_vulkan_memory_model
- Add Vulkan mem model image operands to switch
- Add TODO for source/validate_image.cpp
- val: Image operands NonPrivateTexelKHR, VolatileTexelKHR have no operands
  This is required for memory model tests to pass SPIR-V validation.
- Round trip tests: Test new flags on OpCopyMemory*
This commit is contained in:
David Neto 2018-06-01 18:28:26 -04:00
parent 21bcb9d8b9
commit 571251c8f8
5 changed files with 171 additions and 15 deletions

View File

@ -55,6 +55,13 @@ bool CheckAllImageOperandsHandled() {
case SpvImageOperandsConstOffsetsMask:
case SpvImageOperandsSampleMask:
case SpvImageOperandsMinLodMask:
// TODO(dneto): Support image operands related to the Vulkan memory model.
// https://gitlab.khronos.org/spirv/spirv-tools/issues/32
case SpvImageOperandsMakeTexelAvailableKHRMask:
case SpvImageOperandsMakeTexelVisibleKHRMask:
case SpvImageOperandsNonPrivateTexelKHRMask:
case SpvImageOperandsVolatileTexelKHRMask:
return true;
}
return false;
@ -210,7 +217,12 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
const SpvOp opcode = inst->opcode();
const size_t num_words = inst->words().size();
size_t expected_num_image_operand_words = spvtools::utils::CountSetBits(mask);
// NonPrivate and Volatile take no operand words.
const uint32_t mask_bits_having_operands =
mask & ~uint32_t(SpvImageOperandsNonPrivateTexelKHRMask |
SpvImageOperandsVolatileTexelKHRMask);
size_t expected_num_image_operand_words =
spvtools::utils::CountSetBits(mask_bits_having_operands);
if (mask & SpvImageOperandsGradMask) {
// Grad uses two words.
++expected_num_image_operand_words;

View File

@ -890,8 +890,8 @@ INSTANTIATE_TEST_CASE_P(
"Invalid function control operand: 31 has invalid mask component 16"},
{"OpLoopMerge %1 %2 !1027",
"Invalid loop control operand: 1027 has invalid mask component 1024"},
{"%2 = OpImageFetch %1 %image %coord !511",
"Invalid image operand: 511 has invalid mask component 256"},
{"%2 = OpImageFetch %1 %image %coord !32770",
"Invalid image operand: 32770 has invalid mask component 32768"},
{"OpSelectionMerge %1 !7",
"Invalid selection control operand: 7 has invalid mask component 4"},
}), );

View File

@ -604,16 +604,18 @@ INSTANTIATE_TEST_CASE_P(
})), );
// See SPIR-V Section 3.27 Scope <id>
INSTANTIATE_TEST_CASE_P(Scope, EnumCapabilityTest,
Combine(Values(SPV_ENV_UNIVERSAL_1_0,
SPV_ENV_UNIVERSAL_1_1),
ValuesIn(std::vector<EnumCapabilityCase>{
CASE0(SCOPE_ID, ScopeCrossDevice),
CASE0(SCOPE_ID, ScopeDevice),
CASE0(SCOPE_ID, ScopeWorkgroup),
CASE0(SCOPE_ID, ScopeSubgroup),
CASE0(SCOPE_ID, ScopeInvocation),
})), );
INSTANTIATE_TEST_CASE_P(
Scope, EnumCapabilityTest,
Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3),
ValuesIn(std::vector<EnumCapabilityCase>{
CASE0(SCOPE_ID, ScopeCrossDevice),
CASE0(SCOPE_ID, ScopeDevice),
CASE0(SCOPE_ID, ScopeWorkgroup),
CASE0(SCOPE_ID, ScopeSubgroup),
CASE0(SCOPE_ID, ScopeInvocation),
CASE1(SCOPE_ID, ScopeQueueFamilyKHR, VulkanMemoryModelKHR),
})), );
// See SPIR-V Section 3.28 Group Operation
INSTANTIATE_TEST_CASE_P(

View File

@ -89,9 +89,10 @@ INSTANTIATE_TEST_CASE_P(
::testing::ValuesIn(std::vector<MaskExpansionCase>{
// No bits means no change.
{SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, 0, {PREFIX0}, {PREFIX0}},
// Unknown bits means no change.
// Unknown bits means no change. Use all bits that aren't in the grammar.
// The last mask enum is 0x20
{SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
0xfffffffc,
0xffffffc0,
{PREFIX1},
{PREFIX1}},
// Volatile has no operands.

View File

@ -510,6 +510,147 @@ INSTANTIATE_TEST_CASE_P(
{SpvCapabilityVariablePointersStorageBuffer})},
})), );
// SPV_KHR_vulkan_memory_model
INSTANTIATE_TEST_CASE_P(
SPV_KHR_vulkan_memory_model, ExtensionRoundTripTest,
// We'll get coverage over operand tables by trying the universal
// environments, and at least one specific environment.
//
// Note: SPV_KHR_vulkan_memory_model adds scope enum value QueueFamilyKHR.
// Scope enums are used in ID defini
Combine(
Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1),
ValuesIn(std::vector<AssemblyCase>{
{"OpCapability VulkanMemoryModelKHR\n",
MakeInstruction(SpvOpCapability,
{SpvCapabilityVulkanMemoryModelKHR})},
{"OpCapability VulkanMemoryModelDeviceScopeKHR\n",
MakeInstruction(SpvOpCapability,
{SpvCapabilityVulkanMemoryModelDeviceScopeKHR})},
{"OpMemoryModel Logical VulkanKHR\n",
MakeInstruction(SpvOpMemoryModel, {SpvAddressingModelLogical,
SpvMemoryModelVulkanKHR})},
{"OpStore %1 %2 MakePointerAvailableKHR %3\n",
MakeInstruction(SpvOpStore,
{1, 2, SpvMemoryAccessMakePointerAvailableKHRMask,
3})},
{"OpStore %1 %2 Volatile|MakePointerAvailableKHR %3\n",
MakeInstruction(SpvOpStore,
{1, 2,
int(SpvMemoryAccessMakePointerAvailableKHRMask) |
int(SpvMemoryAccessVolatileMask),
3})},
{"OpStore %1 %2 Aligned|MakePointerAvailableKHR 4 %3\n",
MakeInstruction(SpvOpStore,
{1, 2,
int(SpvMemoryAccessMakePointerAvailableKHRMask) |
int(SpvMemoryAccessAlignedMask),
4, 3})},
{"OpStore %1 %2 MakePointerAvailableKHR|NonPrivatePointerKHR %3\n",
MakeInstruction(SpvOpStore,
{1, 2,
int(SpvMemoryAccessMakePointerAvailableKHRMask) |
int(SpvMemoryAccessNonPrivatePointerKHRMask),
3})},
{"%2 = OpLoad %1 %3 MakePointerVisibleKHR %4\n",
MakeInstruction(SpvOpLoad,
{1, 2, 3, SpvMemoryAccessMakePointerVisibleKHRMask,
4})},
{"%2 = OpLoad %1 %3 Volatile|MakePointerVisibleKHR %4\n",
MakeInstruction(SpvOpLoad,
{1, 2, 3,
int(SpvMemoryAccessMakePointerVisibleKHRMask) |
int(SpvMemoryAccessVolatileMask),
4})},
{"%2 = OpLoad %1 %3 Aligned|MakePointerVisibleKHR 8 %4\n",
MakeInstruction(SpvOpLoad,
{1, 2, 3,
int(SpvMemoryAccessMakePointerVisibleKHRMask) |
int(SpvMemoryAccessAlignedMask),
8, 4})},
{"%2 = OpLoad %1 %3 MakePointerVisibleKHR|NonPrivatePointerKHR "
"%4\n",
MakeInstruction(SpvOpLoad,
{1, 2, 3,
int(SpvMemoryAccessMakePointerVisibleKHRMask) |
int(SpvMemoryAccessNonPrivatePointerKHRMask),
4})},
{"OpCopyMemory %1 %2 "
"MakePointerAvailableKHR|"
"MakePointerVisibleKHR|"
"NonPrivatePointerKHR "
"%3 %4\n",
MakeInstruction(SpvOpCopyMemory,
{1, 2,
(int(SpvMemoryAccessMakePointerVisibleKHRMask) |
int(SpvMemoryAccessMakePointerAvailableKHRMask) |
int(SpvMemoryAccessNonPrivatePointerKHRMask)),
3, 4})},
{"OpCopyMemorySized %1 %2 %3 "
"MakePointerAvailableKHR|"
"MakePointerVisibleKHR|"
"NonPrivatePointerKHR "
"%4 %5\n",
MakeInstruction(SpvOpCopyMemorySized,
{1, 2, 3,
(int(SpvMemoryAccessMakePointerVisibleKHRMask) |
int(SpvMemoryAccessMakePointerAvailableKHRMask) |
int(SpvMemoryAccessNonPrivatePointerKHRMask)),
4, 5})},
// Image operands
{"OpImageWrite %1 %2 %3 MakeTexelAvailableKHR "
"%4\n",
MakeInstruction(
SpvOpImageWrite,
{1, 2, 3, int(SpvImageOperandsMakeTexelAvailableKHRMask), 4})},
{"OpImageWrite %1 %2 %3 MakeTexelAvailableKHR|NonPrivateTexelKHR "
"%4\n",
MakeInstruction(SpvOpImageWrite,
{1, 2, 3,
int(SpvImageOperandsMakeTexelAvailableKHRMask) |
int(SpvImageOperandsNonPrivateTexelKHRMask),
4})},
{"OpImageWrite %1 %2 %3 "
"MakeTexelAvailableKHR|NonPrivateTexelKHR|VolatileTexelKHR "
"%4\n",
MakeInstruction(SpvOpImageWrite,
{1, 2, 3,
int(SpvImageOperandsMakeTexelAvailableKHRMask) |
int(SpvImageOperandsNonPrivateTexelKHRMask) |
int(SpvImageOperandsVolatileTexelKHRMask),
4})},
{"%2 = OpImageRead %1 %3 %4 MakeTexelVisibleKHR "
"%5\n",
MakeInstruction(SpvOpImageRead,
{1, 2, 3, 4,
int(SpvImageOperandsMakeTexelVisibleKHRMask),
5})},
{"%2 = OpImageRead %1 %3 %4 "
"MakeTexelVisibleKHR|NonPrivateTexelKHR "
"%5\n",
MakeInstruction(SpvOpImageRead,
{1, 2, 3, 4,
int(SpvImageOperandsMakeTexelVisibleKHRMask) |
int(SpvImageOperandsNonPrivateTexelKHRMask),
5})},
{"%2 = OpImageRead %1 %3 %4 "
"MakeTexelVisibleKHR|NonPrivateTexelKHR|VolatileTexelKHR "
"%5\n",
MakeInstruction(SpvOpImageRead,
{1, 2, 3, 4,
int(SpvImageOperandsMakeTexelVisibleKHRMask) |
int(SpvImageOperandsNonPrivateTexelKHRMask) |
int(SpvImageOperandsVolatileTexelKHRMask),
5})},
// Memory semantics ID values are numbers put into a SPIR-V
// constant integer referenced by Id. There is no token for
// them, and so no assembler or disassembler support required.
// Similar for Scope ID.
})), );
// SPV_GOOGLE_decorate_string
INSTANTIATE_TEST_CASE_P(