Add SPV_EXT_shader_image_int64 (#3852)
* Add SPV_EXT_shader_image_atomic_int64
* Added 64-bit image tests
Co-authored-by: Arkadiusz Sarwa <arkadiusz.sarwa@amd.com>
diff --git a/source/val/validate_atomics.cpp b/source/val/validate_atomics.cpp
index df7973f..3f1f561 100644
--- a/source/val/validate_atomics.cpp
+++ b/source/val/validate_atomics.cpp
@@ -1,4 +1,6 @@
// Copyright (c) 2017 Google Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
+// reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -151,7 +153,9 @@
}
if (spvIsVulkanEnv(_.context()->target_env) &&
- _.GetBitWidth(result_type) != 32) {
+ (_.GetBitWidth(result_type) != 32 &&
+ (_.GetBitWidth(result_type) != 64 ||
+ !_.HasCapability(SpvCapabilityInt64ImageEXT)))) {
switch (opcode) {
case SpvOpAtomicSMin:
case SpvOpAtomicUMin:
diff --git a/source/val/validate_image.cpp b/source/val/validate_image.cpp
index 8a2bdf1..299a3ef 100644
--- a/source/val/validate_image.cpp
+++ b/source/val/validate_image.cpp
@@ -1,4 +1,6 @@
// Copyright (c) 2017 Google Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
+// reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -737,7 +739,9 @@
if (spvIsVulkanEnv(_.context()->target_env)) {
if ((!_.IsFloatScalarType(info.sampled_type) &&
!_.IsIntScalarType(info.sampled_type)) ||
- 32 != _.GetBitWidth(info.sampled_type)) {
+ (32 != _.GetBitWidth(info.sampled_type) &&
+ (64 != _.GetBitWidth(info.sampled_type) ||
+ !_.HasCapability(SpvCapabilityInt64ImageEXT)))) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< "Expected Sampled Type to be a 32-bit int or float "
"scalar type for Vulkan environment";
diff --git a/test/enum_string_mapping_test.cpp b/test/enum_string_mapping_test.cpp
index 184ae4f..9bbd8ca 100644
--- a/test/enum_string_mapping_test.cpp
+++ b/test/enum_string_mapping_test.cpp
@@ -1,4 +1,6 @@
// Copyright (c) 2017 Google Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
+// reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -180,6 +182,7 @@
{SpvCapabilityAtomicFloat32AddEXT, "AtomicFloat32AddEXT"},
{SpvCapabilityAtomicFloat64AddEXT, "AtomicFloat64AddEXT"},
{SpvCapabilityMultiView, "MultiView"},
+ {SpvCapabilityInt64ImageEXT, "Int64ImageEXT"},
{SpvCapabilitySampleMaskOverrideCoverageNV,
"SampleMaskOverrideCoverageNV"},
{SpvCapabilityGeometryShaderPassthroughNV,
diff --git a/test/val/val_image_test.cpp b/test/val/val_image_test.cpp
index 1a6e79c..2e84a29 100644
--- a/test/val/val_image_test.cpp
+++ b/test/val/val_image_test.cpp
@@ -1,4 +1,6 @@
// Copyright (c) 2017 Google Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
+// reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -37,7 +39,8 @@
const std::string& execution_model = "Fragment",
const std::string& execution_mode = "",
const spv_target_env env = SPV_ENV_UNIVERSAL_1_0,
- const std::string& memory_model = "GLSL450") {
+ const std::string& memory_model = "GLSL450",
+ const std::string& declarations = "") {
std::ostringstream ss;
ss << R"(
OpCapability Shader
@@ -163,6 +166,7 @@
%u32_4 = OpConstant %u32 4
%u64_0 = OpConstant %u64 0
+%u64_1 = OpConstant %u64 1
%u32vec2arr4 = OpTypeArray %u32vec2 %u32_4
%u32vec2arr3 = OpTypeArray %u32vec2 %u32_3
@@ -316,6 +320,8 @@
)";
}
+ ss << declarations;
+
ss << R"(
%main = OpFunction %void None %func
%main_entry = OpLabel
@@ -737,7 +743,7 @@
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 140[%140] cannot be a "
+ EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 141[%141] cannot be a "
"type"));
}
@@ -5071,6 +5077,102 @@
// No negative tests for ZeroExtend since we don't truly know the
// texel format.
+// Tests for 64-bit images
+static const std::string capabilities_and_extensions_image64 = R"(
+OpCapability Int64ImageEXT
+OpExtension "SPV_EXT_shader_image_int64"
+)";
+static const std::string declarations_image64 = R"(
+%type_image_u64_buffer_0002_r64ui = OpTypeImage %u64 Buffer 0 0 0 2 R64ui
+%ptr_Image_u64 = OpTypePointer Image %u64
+%ptr_image_u64_buffer_0002_r64ui = OpTypePointer Private %type_image_u64_buffer_0002_r64ui
+%private_image_u64_buffer_0002_r64ui = OpVariable %ptr_image_u64_buffer_0002_r64ui Private
+)";
+
+TEST_F(ValidateImage, Image64MissingCapability) {
+ CompileSuccessfully(GenerateShaderCode("", "", "Fragment", "",
+ SPV_ENV_UNIVERSAL_1_3, "GLSL450",
+ declarations_image64)
+ .c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions());
+}
+
+TEST_F(ValidateImage, Image64MissingExtension) {
+ const std::string extra = R"(
+OpCapability Int64ImageEXT
+)";
+
+ CompileSuccessfully(GenerateShaderCode("", extra, "Fragment", "",
+ SPV_ENV_UNIVERSAL_1_3, "GLSL450",
+ declarations_image64)
+ .c_str());
+ ASSERT_EQ(SPV_ERROR_MISSING_EXTENSION, ValidateInstructions());
+}
+
+TEST_F(ValidateImage, ImageTexelPointer64Success) {
+ const std::string body = R"(
+%texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
+%sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body,
+ capabilities_and_extensions_image64,
+ "Fragment", "", SPV_ENV_UNIVERSAL_1_3,
+ "GLSL450", declarations_image64)
+ .c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateImage, ImageTexelPointer64ResultTypeNotPointer) {
+ const std::string body = R"(
+%texel_ptr = OpImageTexelPointer %type_image_u64_buffer_0002_r64ui %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
+%sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body,
+ capabilities_and_extensions_image64,
+ "Fragment", "", SPV_ENV_UNIVERSAL_1_3,
+ "GLSL450", declarations_image64)
+ .c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Expected Result Type to be OpTypePointer"));
+}
+
+TEST_F(ValidateImage, ImageTexelPointer64ResultTypeNotImageClass) {
+ const std::string body = R"(
+%texel_ptr = OpImageTexelPointer %ptr_image_f32_cube_0101 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
+%sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body,
+ capabilities_and_extensions_image64,
+ "Fragment", "", SPV_ENV_UNIVERSAL_1_3,
+ "GLSL450", declarations_image64)
+ .c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Expected Result Type to be OpTypePointer whose "
+ "Storage Class operand is Image"));
+}
+
+TEST_F(ValidateImage, ImageTexelPointer64SampleNotZeroForImageWithMSZero) {
+ const std::string body = R"(
+%texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_1
+%sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body,
+ capabilities_and_extensions_image64,
+ "Fragment", "", SPV_ENV_UNIVERSAL_1_3,
+ "GLSL450", declarations_image64)
+ .c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Expected Sample for Image with MS 0 to be a valid "
+ "<id> for the value 0"));
+}
+
} // namespace
} // namespace val
} // namespace spvtools