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