1 // Copyright 2018 The Amber Authors.
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 "src/script.h"
16
17 #include <utility>
18
19 #include "gtest/gtest.h"
20 #include "src/make_unique.h"
21 #include "src/shader.h"
22
23 namespace amber {
24
25 using ScriptTest = testing::Test;
26
TEST_F(ScriptTest,GetShaderInfo)27 TEST_F(ScriptTest, GetShaderInfo) {
28 Script s;
29
30 auto p = MakeUnique<Pipeline>(PipelineType::kGraphics);
31 p->SetName("my_pipeline");
32 auto pipeline = p.get();
33
34 Result r = s.AddPipeline(std::move(p));
35 ASSERT_TRUE(r.IsSuccess()) << r.Error();
36
37 auto shader = MakeUnique<Shader>(kShaderTypeVertex);
38 r = pipeline->AddShader(shader.get(), ShaderType::kShaderTypeVertex);
39 ASSERT_TRUE(r.IsSuccess()) << r.Error();
40
41 pipeline->SetShaderOptimizations(shader.get(), {"opt1", "opt2"});
42
43 shader->SetName("Shader1");
44 shader->SetFormat(kShaderFormatGlsl);
45 shader->SetData("This is my shader data");
46 s.AddShader(std::move(shader));
47
48 shader = MakeUnique<Shader>(kShaderTypeFragment);
49 shader->SetName("Shader2");
50 shader->SetFormat(kShaderFormatSpirvAsm);
51 shader->SetData("More shader data");
52 s.AddShader(std::move(shader));
53
54 auto info = s.GetShaderInfo();
55 ASSERT_EQ(2U, info.size());
56
57 EXPECT_EQ("my_pipeline-Shader1", info[0].shader_name);
58 EXPECT_EQ(kShaderFormatGlsl, info[0].format);
59 EXPECT_EQ(kShaderTypeVertex, info[0].type);
60 EXPECT_EQ("This is my shader data", info[0].shader_source);
61 ASSERT_EQ(2u, info[0].optimizations.size());
62 EXPECT_EQ("opt1", info[0].optimizations[0]);
63 EXPECT_EQ("opt2", info[0].optimizations[1]);
64
65 EXPECT_EQ("Shader2", info[1].shader_name);
66 EXPECT_EQ(kShaderFormatSpirvAsm, info[1].format);
67 EXPECT_EQ(kShaderTypeFragment, info[1].type);
68 EXPECT_EQ("More shader data", info[1].shader_source);
69 EXPECT_TRUE(info[1].optimizations.empty());
70 }
71
TEST_F(ScriptTest,GetShaderInfoNoShaders)72 TEST_F(ScriptTest, GetShaderInfoNoShaders) {
73 Script s;
74 auto info = s.GetShaderInfo();
75 EXPECT_TRUE(info.empty());
76 }
77
TEST_F(ScriptTest,AddShader)78 TEST_F(ScriptTest, AddShader) {
79 auto shader = MakeUnique<Shader>(kShaderTypeVertex);
80 shader->SetName("My Shader");
81
82 Script s;
83 Result r = s.AddShader(std::move(shader));
84 ASSERT_TRUE(r.IsSuccess()) << r.Error();
85 }
86
TEST_F(ScriptTest,AddDuplicateShader)87 TEST_F(ScriptTest, AddDuplicateShader) {
88 auto shader1 = MakeUnique<Shader>(kShaderTypeVertex);
89 shader1->SetName("My Shader");
90
91 Script s;
92 Result r = s.AddShader(std::move(shader1));
93 ASSERT_TRUE(r.IsSuccess()) << r.Error();
94
95 auto shader2 = MakeUnique<Shader>(kShaderTypeFragment);
96 shader2->SetName("My Shader");
97
98 r = s.AddShader(std::move(shader2));
99 ASSERT_FALSE(r.IsSuccess());
100 EXPECT_EQ("duplicate shader name provided", r.Error());
101 }
102
TEST_F(ScriptTest,GetShader)103 TEST_F(ScriptTest, GetShader) {
104 auto shader = MakeUnique<Shader>(kShaderTypeVertex);
105 shader->SetName("My Shader");
106
107 auto* ptr = shader.get();
108
109 Script s;
110 Result r = s.AddShader(std::move(shader));
111 ASSERT_TRUE(r.IsSuccess()) << r.Error();
112
113 EXPECT_EQ(ptr, s.GetShader("My Shader"));
114 }
115
TEST_F(ScriptTest,GetMissingShader)116 TEST_F(ScriptTest, GetMissingShader) {
117 Script s;
118 EXPECT_TRUE(s.GetShader("My Shader") == nullptr);
119 }
120
TEST_F(ScriptTest,GetShadersEmpty)121 TEST_F(ScriptTest, GetShadersEmpty) {
122 Script s;
123 const auto& shaders = s.GetShaders();
124 EXPECT_TRUE(shaders.empty());
125 }
126
TEST_F(ScriptTest,GetShaders)127 TEST_F(ScriptTest, GetShaders) {
128 auto shader1 = MakeUnique<Shader>(kShaderTypeVertex);
129 shader1->SetName("My Shader");
130
131 const auto* ptr1 = shader1.get();
132
133 Script s;
134 Result r = s.AddShader(std::move(shader1));
135 ASSERT_TRUE(r.IsSuccess()) << r.Error();
136
137 auto shader2 = MakeUnique<Shader>(kShaderTypeFragment);
138 shader2->SetName("My Fragment");
139
140 const auto* ptr2 = shader2.get();
141
142 r = s.AddShader(std::move(shader2));
143 ASSERT_TRUE(r.IsSuccess()) << r.Error();
144
145 const auto& shaders = s.GetShaders();
146 ASSERT_EQ(2U, shaders.size());
147 EXPECT_EQ(ptr1, shaders[0].get());
148 EXPECT_EQ(ptr2, shaders[1].get());
149 }
150
TEST_F(ScriptTest,AddPipeline)151 TEST_F(ScriptTest, AddPipeline) {
152 auto pipeline = MakeUnique<Pipeline>(PipelineType::kCompute);
153 pipeline->SetName("my_pipeline");
154
155 Script s;
156 Result r = s.AddPipeline(std::move(pipeline));
157 ASSERT_TRUE(r.IsSuccess()) << r.Error();
158 }
159
TEST_F(ScriptTest,AddDuplicatePipeline)160 TEST_F(ScriptTest, AddDuplicatePipeline) {
161 auto pipeline1 = MakeUnique<Pipeline>(PipelineType::kCompute);
162 pipeline1->SetName("my_pipeline");
163
164 Script s;
165 Result r = s.AddPipeline(std::move(pipeline1));
166 ASSERT_TRUE(r.IsSuccess()) << r.Error();
167
168 auto pipeline2 = MakeUnique<Pipeline>(PipelineType::kGraphics);
169 pipeline2->SetName("my_pipeline");
170 r = s.AddPipeline(std::move(pipeline2));
171 ASSERT_FALSE(r.IsSuccess());
172 EXPECT_EQ("duplicate pipeline name provided", r.Error());
173 }
174
TEST_F(ScriptTest,GetPipeline)175 TEST_F(ScriptTest, GetPipeline) {
176 auto pipeline = MakeUnique<Pipeline>(PipelineType::kCompute);
177 pipeline->SetName("my_pipeline");
178
179 const auto* ptr = pipeline.get();
180
181 Script s;
182 Result r = s.AddPipeline(std::move(pipeline));
183 ASSERT_TRUE(r.IsSuccess()) << r.Error();
184
185 EXPECT_EQ(ptr, s.GetPipeline("my_pipeline"));
186 }
187
TEST_F(ScriptTest,GetMissingPipeline)188 TEST_F(ScriptTest, GetMissingPipeline) {
189 Script s;
190 EXPECT_TRUE(s.GetPipeline("my_pipeline") == nullptr);
191 }
192
TEST_F(ScriptTest,GetPipelinesEmpty)193 TEST_F(ScriptTest, GetPipelinesEmpty) {
194 Script s;
195 const auto& pipelines = s.GetPipelines();
196 EXPECT_TRUE(pipelines.empty());
197 }
198
TEST_F(ScriptTest,GetPipelines)199 TEST_F(ScriptTest, GetPipelines) {
200 auto pipeline1 = MakeUnique<Pipeline>(PipelineType::kCompute);
201 pipeline1->SetName("my_pipeline1");
202
203 const auto* ptr1 = pipeline1.get();
204
205 Script s;
206 Result r = s.AddPipeline(std::move(pipeline1));
207 ASSERT_TRUE(r.IsSuccess()) << r.Error();
208
209 auto pipeline2 = MakeUnique<Pipeline>(PipelineType::kGraphics);
210 pipeline2->SetName("my_pipeline2");
211
212 const auto* ptr2 = pipeline2.get();
213
214 r = s.AddPipeline(std::move(pipeline2));
215 ASSERT_TRUE(r.IsSuccess()) << r.Error();
216
217 const auto& pipelines = s.GetPipelines();
218 ASSERT_EQ(2U, pipelines.size());
219 EXPECT_EQ(ptr1, pipelines[0].get());
220 EXPECT_EQ(ptr2, pipelines[1].get());
221 }
222
TEST_F(ScriptTest,AddBuffer)223 TEST_F(ScriptTest, AddBuffer) {
224 auto buffer = MakeUnique<Buffer>();
225 buffer->SetName("my_buffer");
226
227 Script s;
228 Result r = s.AddBuffer(std::move(buffer));
229 ASSERT_TRUE(r.IsSuccess()) << r.Error();
230 }
231
TEST_F(ScriptTest,AddDuplicateBuffer)232 TEST_F(ScriptTest, AddDuplicateBuffer) {
233 auto buffer1 = MakeUnique<Buffer>();
234 buffer1->SetName("my_buffer");
235
236 Script s;
237 Result r = s.AddBuffer(std::move(buffer1));
238 ASSERT_TRUE(r.IsSuccess()) << r.Error();
239
240 auto buffer2 = MakeUnique<Buffer>();
241 buffer2->SetName("my_buffer");
242
243 r = s.AddBuffer(std::move(buffer2));
244 ASSERT_FALSE(r.IsSuccess());
245 EXPECT_EQ("duplicate buffer name provided", r.Error());
246 }
247
TEST_F(ScriptTest,GetBuffer)248 TEST_F(ScriptTest, GetBuffer) {
249 auto buffer = MakeUnique<Buffer>();
250 buffer->SetName("my_buffer");
251
252 const auto* ptr = buffer.get();
253
254 Script s;
255 Result r = s.AddBuffer(std::move(buffer));
256 ASSERT_TRUE(r.IsSuccess()) << r.Error();
257
258 EXPECT_EQ(ptr, s.GetBuffer("my_buffer"));
259 }
260
TEST_F(ScriptTest,GetMissingBuffer)261 TEST_F(ScriptTest, GetMissingBuffer) {
262 Script s;
263 EXPECT_TRUE(s.GetBuffer("my_buffer") == nullptr);
264 }
265
TEST_F(ScriptTest,GetBuffersEmpty)266 TEST_F(ScriptTest, GetBuffersEmpty) {
267 Script s;
268 const auto& buffers = s.GetBuffers();
269 EXPECT_TRUE(buffers.empty());
270 }
271
TEST_F(ScriptTest,GetBuffers)272 TEST_F(ScriptTest, GetBuffers) {
273 auto buffer1 = MakeUnique<Buffer>();
274 buffer1->SetName("my_buffer1");
275
276 const auto* ptr1 = buffer1.get();
277
278 Script s;
279 Result r = s.AddBuffer(std::move(buffer1));
280 ASSERT_TRUE(r.IsSuccess()) << r.Error();
281
282 auto buffer2 = MakeUnique<Buffer>();
283 buffer2->SetName("my_buffer2");
284
285 const auto* ptr2 = buffer2.get();
286
287 r = s.AddBuffer(std::move(buffer2));
288 ASSERT_TRUE(r.IsSuccess()) << r.Error();
289
290 const auto& buffers = s.GetBuffers();
291 ASSERT_EQ(2U, buffers.size());
292 EXPECT_EQ(ptr1, buffers[0].get());
293 EXPECT_EQ(ptr2, buffers[1].get());
294 }
295
TEST_F(ScriptTest,IdentifiesDeviceExtensions)296 TEST_F(ScriptTest, IdentifiesDeviceExtensions) {
297 Script s;
298 s.AddRequiredExtension("VK_KHR_16bit_storage");
299 EXPECT_TRUE(s.GetRequiredInstanceExtensions().empty());
300 ASSERT_EQ(1U, s.GetRequiredDeviceExtensions().size());
301 EXPECT_EQ("VK_KHR_16bit_storage", s.GetRequiredDeviceExtensions()[0]);
302 }
303
TEST_F(ScriptTest,IdentifesInstanceExt_VK_KHR_get_physical_device_properties2)304 TEST_F(ScriptTest,
305 IdentifesInstanceExt_VK_KHR_get_physical_device_properties2) {
306 Script s;
307 s.AddRequiredExtension("VK_KHR_get_physical_device_properties2");
308 EXPECT_TRUE(s.GetRequiredDeviceExtensions().empty());
309 ASSERT_EQ(1U, s.GetRequiredInstanceExtensions().size());
310 EXPECT_EQ("VK_KHR_get_physical_device_properties2",
311 s.GetRequiredInstanceExtensions()[0]);
312 }
313
TEST_F(ScriptTest,AddType)314 TEST_F(ScriptTest, AddType) {
315 Script s;
316 Result r = s.AddType("my_type", type::Number::Float(32));
317 ASSERT_TRUE(r.IsSuccess()) << r.Error();
318 }
319
TEST_F(ScriptTest,AddDuplicateType)320 TEST_F(ScriptTest, AddDuplicateType) {
321 Script s;
322 Result r = s.AddType("my_type", type::Number::Uint(8));
323 ASSERT_TRUE(r.IsSuccess()) << r.Error();
324
325 r = s.AddType("my_type", type::Number::Uint(8));
326 ASSERT_FALSE(r.IsSuccess());
327 EXPECT_EQ("duplicate type name provided", r.Error());
328 }
329
TEST_F(ScriptTest,GetType)330 TEST_F(ScriptTest, GetType) {
331 auto type = type::Number::Uint(8);
332 auto* ptr = type.get();
333
334 Script s;
335 Result r = s.AddType("my_type", std::move(type));
336 ASSERT_TRUE(r.IsSuccess()) << r.Error();
337
338 EXPECT_TRUE(ptr->Equal(s.GetType("my_type")));
339 }
340
TEST_F(ScriptTest,GetMissingType)341 TEST_F(ScriptTest, GetMissingType) {
342 Script s;
343 EXPECT_TRUE(s.GetPipeline("my_type") == nullptr);
344 }
345
346 } // namespace amber
347