1// Copyright (c) 2017 Google Inc. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include <algorithm> 16#include <memory> 17 18#include "gtest/gtest.h" 19#include "source/opt/build_module.h" 20#include "source/opt/ir_context.h" 21 22namespace spvtools { 23namespace opt { 24namespace { 25 26using FeatureManagerTest = ::testing::Test; 27 28TEST_F(FeatureManagerTest, MissingExtension) { 29 const std::string text = R"( 30OpCapability Shader 31OpMemoryModel Logical GLSL450 32 )"; 33 34 std::unique_ptr<IRContext> context = 35 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 36 ASSERT_NE(context, nullptr); 37 38 EXPECT_FALSE(context->get_feature_mgr()->HasExtension( 39 Extension::kSPV_KHR_variable_pointers)); 40} 41 42TEST_F(FeatureManagerTest, OneExtension) { 43 const std::string text = R"( 44OpCapability Shader 45OpMemoryModel Logical GLSL450 46OpExtension "SPV_KHR_variable_pointers" 47 )"; 48 49 std::unique_ptr<IRContext> context = 50 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 51 ASSERT_NE(context, nullptr); 52 53 EXPECT_TRUE(context->get_feature_mgr()->HasExtension( 54 Extension::kSPV_KHR_variable_pointers)); 55} 56 57TEST_F(FeatureManagerTest, NotADifferentExtension) { 58 const std::string text = R"( 59OpCapability Shader 60OpMemoryModel Logical GLSL450 61OpExtension "SPV_KHR_variable_pointers" 62 )"; 63 64 std::unique_ptr<IRContext> context = 65 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 66 ASSERT_NE(context, nullptr); 67 68 EXPECT_FALSE(context->get_feature_mgr()->HasExtension( 69 Extension::kSPV_KHR_storage_buffer_storage_class)); 70} 71 72TEST_F(FeatureManagerTest, TwoExtensions) { 73 const std::string text = R"( 74OpCapability Shader 75OpMemoryModel Logical GLSL450 76OpExtension "SPV_KHR_variable_pointers" 77OpExtension "SPV_KHR_storage_buffer_storage_class" 78 )"; 79 80 std::unique_ptr<IRContext> context = 81 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 82 ASSERT_NE(context, nullptr); 83 84 EXPECT_TRUE(context->get_feature_mgr()->HasExtension( 85 Extension::kSPV_KHR_variable_pointers)); 86 EXPECT_TRUE(context->get_feature_mgr()->HasExtension( 87 Extension::kSPV_KHR_storage_buffer_storage_class)); 88} 89 90TEST_F(FeatureManagerTest, GetExtensionsReturnsExtensions) { 91 const std::string text = R"( 92OpCapability Shader 93OpMemoryModel Logical GLSL450 94OpExtension "SPV_KHR_variable_pointers" 95OpExtension "SPV_KHR_storage_buffer_storage_class" 96 )"; 97 98 std::unique_ptr<IRContext> context = 99 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 100 ASSERT_NE(context, nullptr); 101 102 const auto& extensions = context->get_feature_mgr()->GetExtensions(); 103 EXPECT_EQ(extensions.size(), 2); 104 EXPECT_TRUE(extensions.contains(Extension::kSPV_KHR_variable_pointers)); 105 EXPECT_TRUE( 106 extensions.contains(Extension::kSPV_KHR_storage_buffer_storage_class)); 107} 108 109// Test capability checks. 110TEST_F(FeatureManagerTest, ExplicitlyPresent1) { 111 const std::string text = R"( 112OpCapability Shader 113OpMemoryModel Logical GLSL450 114 )"; 115 116 std::unique_ptr<IRContext> context = 117 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 118 ASSERT_NE(context, nullptr); 119 120 EXPECT_TRUE( 121 context->get_feature_mgr()->HasCapability(spv::Capability::Shader)); 122 EXPECT_FALSE( 123 context->get_feature_mgr()->HasCapability(spv::Capability::Kernel)); 124} 125 126TEST_F(FeatureManagerTest, ExplicitlyPresent2) { 127 const std::string text = R"( 128OpCapability Kernel 129OpMemoryModel Logical GLSL450 130 )"; 131 132 std::unique_ptr<IRContext> context = 133 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 134 ASSERT_NE(context, nullptr); 135 136 EXPECT_FALSE( 137 context->get_feature_mgr()->HasCapability(spv::Capability::Shader)); 138 EXPECT_TRUE( 139 context->get_feature_mgr()->HasCapability(spv::Capability::Kernel)); 140} 141 142TEST_F(FeatureManagerTest, ImplicitlyPresent) { 143 const std::string text = R"( 144OpCapability Tessellation 145OpMemoryModel Logical GLSL450 146 )"; 147 148 std::unique_ptr<IRContext> context = 149 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 150 ASSERT_NE(context, nullptr); 151 152 // Check multiple levels of indirection. Tessellation implies Shader, which 153 // implies Matrix. 154 EXPECT_TRUE( 155 context->get_feature_mgr()->HasCapability(spv::Capability::Tessellation)); 156 EXPECT_TRUE( 157 context->get_feature_mgr()->HasCapability(spv::Capability::Shader)); 158 EXPECT_TRUE( 159 context->get_feature_mgr()->HasCapability(spv::Capability::Matrix)); 160 EXPECT_FALSE( 161 context->get_feature_mgr()->HasCapability(spv::Capability::Kernel)); 162} 163 164TEST_F(FeatureManagerTest, GetCapabilitiesReturnsImplicitCapabilities) { 165 const std::string text = R"( 166OpCapability Tessellation 167OpMemoryModel Logical GLSL450 168 )"; 169 170 std::unique_ptr<IRContext> context = 171 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 172 ASSERT_NE(context, nullptr); 173 174 const auto& capabilities = context->get_feature_mgr()->GetCapabilities(); 175 // Tesselation implies Shader, which implies Matrix. 176 EXPECT_EQ(capabilities.size(), 3); 177 EXPECT_TRUE(capabilities.contains(spv::Capability::Tessellation)); 178 EXPECT_TRUE(capabilities.contains(spv::Capability::Shader)); 179 EXPECT_TRUE(capabilities.contains(spv::Capability::Matrix)); 180} 181 182} // namespace 183} // namespace opt 184} // namespace spvtools 185