diff --git a/docs/amber_script.md b/docs/amber_script.md index 264b85c7b..d774b14b9 100644 --- a/docs/amber_script.md +++ b/docs/amber_script.md @@ -38,6 +38,10 @@ with: * `VariablePointerFeatures.variablePointers` * `VariablePointerFeatures.variablePointersStorageBuffer` * `Float16Int8Features.shaderFloat16` + * `Float16Int8Features.shaderInt8` + * `Storage8BitFeatures.storageBuffer8BitAccess` + * `Storage8BitFeatures.uniformAndStorageBuffer8BitAccess` + * `Storage8BitFeatures.storagePushConstant8` Extensions can be enabled with the `DEVICE_EXTENSION` and `INSTANCE_EXTENSION` commands. diff --git a/samples/config_helper_vulkan.cc b/samples/config_helper_vulkan.cc index 69ab51f08..13d7f89d9 100644 --- a/samples/config_helper_vulkan.cc +++ b/samples/config_helper_vulkan.cc @@ -47,6 +47,13 @@ const char kVariablePointers[] = "VariablePointerFeatures.variablePointers"; const char kVariablePointersStorageBuffer[] = "VariablePointerFeatures.variablePointersStorageBuffer"; const char kFloat16Int8_Float16[] = "Float16Int8Features.shaderFloat16"; +const char kFloat16Int8_Int8[] = "Float16Int8Features.shaderInt8"; +const char k8BitStorage_Storage[] = + "Storage8BitFeatures.storageBuffer8BitAccess"; +const char k8BitStorage_UniformAndStorage[] = + "Storage8BitFeatures.uniformAndStorageBuffer8BitAccess"; +const char k8BitStorage_PushConstant[] = + "Storage8BitFeatures.storagePushConstant8"; const char kExtensionForValidationLayer[] = "VK_EXT_debug_report"; @@ -600,7 +607,8 @@ ConfigHelperVulkan::ConfigHelperVulkan() : available_features_(VkPhysicalDeviceFeatures()), available_features2_(VkPhysicalDeviceFeatures2KHR()), variable_pointers_feature_(VkPhysicalDeviceVariablePointerFeaturesKHR()), - float16_int8_feature_(VkPhysicalDeviceFloat16Int8FeaturesKHR()) {} + float16_int8_feature_(VkPhysicalDeviceFloat16Int8FeaturesKHR()), + int8_storage_feature_(VkPhysicalDevice8BitStorageFeaturesKHR()) {} ConfigHelperVulkan::~ConfigHelperVulkan() { if (vulkan_device_) @@ -778,6 +786,8 @@ amber::Result ConfigHelperVulkan::CheckVulkanPhysicalDeviceRequirements( for (const auto& ext : available_device_extensions_) { if (ext == "VK_KHR_shader_float16_int8") supports_shader_float16_int8_ = true; + else if (ext == "VK_KHR_8bit_storage") + supports_shader_int8_storage_ = true; } vulkan_queue_family_index_ = ChooseQueueFamilyIndex(physical_device); @@ -886,17 +896,29 @@ amber::Result ConfigHelperVulkan::CreateDeviceWithFeatures1( amber::Result ConfigHelperVulkan::CreateDeviceWithFeatures2( const std::vector& required_features, VkDeviceCreateInfo* info) { + variable_pointers_feature_.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR; + variable_pointers_feature_.pNext = nullptr; + float16_int8_feature_.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR; float16_int8_feature_.pNext = nullptr; - variable_pointers_feature_.sType = - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR; + int8_storage_feature_.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR; + int8_storage_feature_.pNext = nullptr; - if (supports_shader_float16_int8_) - variable_pointers_feature_.pNext = &float16_int8_feature_; - else - variable_pointers_feature_.pNext = nullptr; + void** next_ptr = &variable_pointers_feature_.pNext; + + if (supports_shader_float16_int8_) { + *next_ptr = &float16_int8_feature_; + next_ptr = &float16_int8_feature_.pNext; + } + + if (supports_shader_int8_storage_) { + *next_ptr = &int8_storage_feature_; + next_ptr = &int8_storage_feature_.pNext; + } available_features2_.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; available_features2_.pNext = &variable_pointers_feature_; @@ -915,6 +937,14 @@ amber::Result ConfigHelperVulkan::CreateDeviceWithFeatures2( variable_pointers_feature_.variablePointersStorageBuffer = VK_TRUE; else if (feature == kFloat16Int8_Float16) float16_int8_feature_.shaderFloat16 = VK_TRUE; + else if (feature == kFloat16Int8_Int8) + float16_int8_feature_.shaderInt8 = VK_TRUE; + else if (feature == k8BitStorage_Storage) + int8_storage_feature_.storageBuffer8BitAccess = VK_TRUE; + else if (feature == k8BitStorage_UniformAndStorage) + int8_storage_feature_.uniformAndStorageBuffer8BitAccess = VK_TRUE; + else if (feature == k8BitStorage_PushConstant) + int8_storage_feature_.storagePushConstant8 = VK_TRUE; } VkPhysicalDeviceFeatures required_vulkan_features = diff --git a/samples/config_helper_vulkan.h b/samples/config_helper_vulkan.h index b5d0b09d1..b5344a9b6 100644 --- a/samples/config_helper_vulkan.h +++ b/samples/config_helper_vulkan.h @@ -111,10 +111,12 @@ class ConfigHelperVulkan : public ConfigHelperImpl { bool supports_get_physical_device_properties2_ = false; bool supports_shader_float16_int8_ = false; + bool supports_shader_int8_storage_ = false; VkPhysicalDeviceFeatures available_features_; VkPhysicalDeviceFeatures2KHR available_features2_; VkPhysicalDeviceVariablePointerFeaturesKHR variable_pointers_feature_; VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8_feature_; + VkPhysicalDevice8BitStorageFeaturesKHR int8_storage_feature_; }; } // namespace sample diff --git a/src/amberscript/parser_device_feature_test.cc b/src/amberscript/parser_device_feature_test.cc index 6bd2d716c..1ac33fcc0 100644 --- a/src/amberscript/parser_device_feature_test.cc +++ b/src/amberscript/parser_device_feature_test.cc @@ -24,7 +24,11 @@ TEST_F(AmberScriptParserTest, DeviceFeature) { std::string in = R"( DEVICE_FEATURE vertexPipelineStoresAndAtomics DEVICE_FEATURE VariablePointerFeatures.variablePointersStorageBuffer -DEVICE_FEATURE Float16Int8Features.shaderFloat16)"; +DEVICE_FEATURE Float16Int8Features.shaderFloat16 +DEVICE_FEATURE Float16Int8Features.shaderInt8 +DEVICE_FEATURE Storage8BitFeatures.storageBuffer8BitAccess +DEVICE_FEATURE Storage8BitFeatures.uniformAndStorageBuffer8BitAccess +DEVICE_FEATURE Storage8BitFeatures.storagePushConstant8)"; Parser parser; Result r = parser.Parse(in); @@ -32,11 +36,16 @@ DEVICE_FEATURE Float16Int8Features.shaderFloat16)"; auto script = parser.GetScript(); const auto& features = script->GetRequiredFeatures(); - ASSERT_EQ(3U, features.size()); + ASSERT_EQ(7U, features.size()); EXPECT_EQ("vertexPipelineStoresAndAtomics", features[0]); EXPECT_EQ("VariablePointerFeatures.variablePointersStorageBuffer", features[1]); EXPECT_EQ("Float16Int8Features.shaderFloat16", features[2]); + EXPECT_EQ("Float16Int8Features.shaderInt8", features[3]); + EXPECT_EQ("Storage8BitFeatures.storageBuffer8BitAccess", features[4]); + EXPECT_EQ("Storage8BitFeatures.uniformAndStorageBuffer8BitAccess", + features[5]); + EXPECT_EQ("Storage8BitFeatures.storagePushConstant8", features[6]); } TEST_F(AmberScriptParserTest, DeviceFeatureMissingFeature) { diff --git a/src/script.cc b/src/script.cc index 318e30bde..f314a3e0e 100644 --- a/src/script.cc +++ b/src/script.cc @@ -101,7 +101,11 @@ bool Script::IsKnownFeature(const std::string& name) const { name == "variableMultisampleRate" || name == "inheritedQueries" || name == "VariablePointerFeatures.variablePointers" || name == "VariablePointerFeatures.variablePointersStorageBuffer" || - name == "Float16Int8Features.shaderFloat16"; + name == "Float16Int8Features.shaderFloat16" || + name == "Float16Int8Features.shaderInt8" || + name == "Storage8BitFeatures.storageBuffer8BitAccess" || + name == "Storage8BitFeatures.uniformAndStorageBuffer8BitAccess" || + name == "Storage8BitFeatures.storagePushConstant8"; } type::Type* Script::ParseType(const std::string& str) { diff --git a/src/vulkan/device.cc b/src/vulkan/device.cc index 5cf30f215..7a11258d1 100644 --- a/src/vulkan/device.cc +++ b/src/vulkan/device.cc @@ -33,6 +33,13 @@ const char kVariablePointers[] = "VariablePointerFeatures.variablePointers"; const char kVariablePointersStorageBuffer[] = "VariablePointerFeatures.variablePointersStorageBuffer"; const char kFloat16Int8_Float16[] = "Float16Int8Features.shaderFloat16"; +const char kFloat16Int8_Int8[] = "Float16Int8Features.shaderInt8"; +const char k8BitStorage_Storage[] = + "Storage8BitFeatures.storageBuffer8BitAccess"; +const char k8BitStorage_UniformAndStorage[] = + "Storage8BitFeatures.uniformAndStorageBuffer8BitAccess"; +const char k8BitStorage_PushConstant[] = + "Storage8BitFeatures.storagePushConstant8"; struct BaseOutStructure { VkStructureType sType; @@ -396,6 +403,7 @@ Result Device::Initialize( VkPhysicalDeviceVariablePointerFeaturesKHR* var_ptrs = nullptr; VkPhysicalDeviceFloat16Int8FeaturesKHR* float16_ptrs = nullptr; + VkPhysicalDevice8BitStorageFeaturesKHR* storage8_ptrs = nullptr; void* ptr = available_features2.pNext; while (ptr != nullptr) { BaseOutStructure* s = static_cast(ptr); @@ -407,6 +415,10 @@ Result Device::Initialize( VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR) { float16_ptrs = static_cast(ptr); + } else if (s->sType == + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR) { + storage8_ptrs = + static_cast(ptr); } ptr = s->pNext; } @@ -436,14 +448,40 @@ Result Device::Initialize( "Missing variable pointers storage buffer feature"); } - if (feature == kFloat16Int8_Float16) { - if (float16_ptrs == nullptr) { - return amber::Result( - "Shader float 16 requested but feature not returned"); - } - if (float16_ptrs->shaderFloat16 != VK_TRUE) { - return amber::Result("Missing float16 feature"); - } + if ((feature == kFloat16Int8_Float16 || feature == kFloat16Int8_Int8) && + float16_ptrs == nullptr) { + return amber::Result( + "Shader float16/int8 requested but feature not returned"); + } + + if (feature == kFloat16Int8_Float16 && + float16_ptrs->shaderFloat16 != VK_TRUE) { + return amber::Result("Missing float16 feature"); + } + + if (feature == kFloat16Int8_Int8 && float16_ptrs->shaderInt8 != VK_TRUE) { + return amber::Result("Missing int8 feature"); + } + + if ((feature == k8BitStorage_UniformAndStorage || + feature == k8BitStorage_Storage || + feature == k8BitStorage_PushConstant) && + storage8_ptrs == nullptr) { + return amber::Result( + "Shader 8-bit storage requested but feature not returned"); + } + + if (feature == k8BitStorage_Storage && + storage8_ptrs->storageBuffer8BitAccess != VK_TRUE) { + return amber::Result("Missing 8-bit storage access"); + } + if (feature == k8BitStorage_UniformAndStorage && + storage8_ptrs->uniformAndStorageBuffer8BitAccess != VK_TRUE) { + return amber::Result("Missing 8-bit uniform and storage access"); + } + if (feature == k8BitStorage_PushConstant && + storage8_ptrs->storagePushConstant8 != VK_TRUE) { + return amber::Result("Missing 8-bit push constant access"); } } diff --git a/tests/cases/int8.amber b/tests/cases/int8.amber new file mode 100644 index 000000000..31d4403de --- /dev/null +++ b/tests/cases/int8.amber @@ -0,0 +1,53 @@ +#!amber +# Copyright 2020 The Amber Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +INSTANCE_EXTENSION VK_KHR_get_physical_device_properties2 +DEVICE_EXTENSION VK_KHR_shader_float16_int8 +DEVICE_EXTENSION VK_KHR_storage_buffer_storage_class +DEVICE_EXTENSION VK_KHR_8bit_storage +DEVICE_FEATURE Float16Int8Features.shaderInt8 +DEVICE_FEATURE Storage8BitFeatures.uniformAndStorageBuffer8BitAccess +DEVICE_FEATURE Storage8BitFeatures.storagePushConstant8 + +SHADER compute comp_shader GLSL +#version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require + +layout(set=0, binding=0) buffer Buf { + int8_t value; +} data; + +layout(push_constant) uniform PushConstantsBlock { + int8_t factor; +} pushConstants; + +void main() { + data.value = data.value * pushConstants.factor; +} +END + +BUFFER buf DATA_TYPE int8 DATA 63 END +BUFFER pushc DATA_TYPE int8 DATA 2 END + +PIPELINE compute pipeline + ATTACH comp_shader + + BIND BUFFER buf AS storage DESCRIPTOR_SET 0 BINDING 0 + BIND BUFFER pushc AS push_constant +END + +RUN pipeline 1 1 1 + +EXPECT buf IDX 0 EQ 126 diff --git a/tests/run_tests.py b/tests/run_tests.py index ca70f5e5e..63edf75fe 100755 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -78,6 +78,7 @@ "draw_triangle_list_in_r8g8b8a8_snorm_color_frame.vkscript", # No supporting device for Float16Int8Features "float16.amber", + "int8.amber", # SEGV: github.com/google/amber/issues/725 "multiple_ssbo_update_with_graphics_pipeline.vkscript", "multiple_ssbo_with_sparse_descriptor_set_in_compute_pipeline_less_than_4.vkscript",