blob: 4d6f3660b7c15089d6812829a57b879c3bff6cd7 [file] [log] [blame]
dan sinclair70d430c2018-09-28 16:12:38 -04001// 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/amberscript/pipeline.h"
16#include "gtest/gtest.h"
17
18namespace amber {
19namespace amberscript {
20namespace {
21
22struct ShaderTypeData {
23 ShaderType type;
24};
25
26} // namespace
27
28using AmberScriptPipelineTest = testing::Test;
29
30TEST_F(AmberScriptPipelineTest, AddShader) {
31 Shader v(ShaderType::kVertex);
32 Shader f(ShaderType::kFragment);
33
34 Pipeline p(PipelineType::kGraphics);
35 Result r = p.AddShader(&v);
36 ASSERT_TRUE(r.IsSuccess()) << r.Error();
37
38 r = p.AddShader(&f);
39 ASSERT_TRUE(r.IsSuccess()) << r.Error();
40
41 const auto& shaders = p.GetShaders();
42 EXPECT_EQ(2U, shaders.size());
43
44 EXPECT_EQ(&v, shaders[0].GetShader());
45 EXPECT_EQ(&f, shaders[1].GetShader());
46}
47
48TEST_F(AmberScriptPipelineTest, MissingShader) {
49 Pipeline p(PipelineType::kGraphics);
50 Result r = p.AddShader(nullptr);
51 ASSERT_FALSE(r.IsSuccess());
52 EXPECT_EQ("shader can not be null when attached to pipeline", r.Error());
53}
54
55TEST_F(AmberScriptPipelineTest, DuplicateShaders) {
56 Shader v(ShaderType::kVertex);
57 Shader f(ShaderType::kFragment);
58
59 Pipeline p(PipelineType::kGraphics);
60 Result r = p.AddShader(&v);
61 ASSERT_TRUE(r.IsSuccess()) << r.Error();
62
63 r = p.AddShader(&f);
64 ASSERT_TRUE(r.IsSuccess()) << r.Error();
65
66 r = p.AddShader(&v);
67 ASSERT_FALSE(r.IsSuccess());
68 EXPECT_EQ("can not add duplicate shader to pipeline", r.Error());
69}
70
71TEST_F(AmberScriptPipelineTest, DuplicateShaderType) {
72 Shader v(ShaderType::kVertex);
73 Shader f(ShaderType::kVertex);
74
75 Pipeline p(PipelineType::kGraphics);
76 Result r = p.AddShader(&v);
77 ASSERT_TRUE(r.IsSuccess()) << r.Error();
78
79 r = p.AddShader(&f);
80 ASSERT_FALSE(r.IsSuccess());
81 EXPECT_EQ("can not add duplicate shader type to pipeline", r.Error());
82}
83
84using AmberScriptPipelineComputePipelineTest =
85 testing::TestWithParam<ShaderTypeData>;
86TEST_P(AmberScriptPipelineComputePipelineTest,
87 SettingGraphicsShaderToComputePipeline) {
88 const auto test_data = GetParam();
89
90 Shader s(test_data.type);
91
92 Pipeline p(PipelineType::kCompute);
93 Result r = p.AddShader(&s);
94 ASSERT_FALSE(r.IsSuccess());
95 EXPECT_EQ("only compute shaders allowed in a compute pipeline", r.Error());
96}
97INSTANTIATE_TEST_CASE_P(
98 AmberScriptPipelineComputePipelineTests,
99 AmberScriptPipelineComputePipelineTest,
100 testing::Values(ShaderTypeData{ShaderType::kVertex},
101 ShaderTypeData{ShaderType::kFragment},
102 ShaderTypeData{ShaderType::kGeometry},
103 ShaderTypeData{ShaderType::kTessellationEvaluation},
104 ShaderTypeData{ShaderType::kTessellationControl}), );
105
106TEST_F(AmberScriptPipelineTest, SettingComputeShaderToGraphicsPipeline) {
107 Shader c(ShaderType::kCompute);
108
109 Pipeline p(PipelineType::kGraphics);
110 Result r = p.AddShader(&c);
111 ASSERT_FALSE(r.IsSuccess());
112 EXPECT_EQ("can not add a compute shader to a graphics pipeline", r.Error());
113}
114
115TEST_F(AmberScriptPipelineTest, SetShaderOptimizations) {
116 Shader v(ShaderType::kVertex);
117 Shader f(ShaderType::kFragment);
118
119 Pipeline p(PipelineType::kGraphics);
120 Result r = p.AddShader(&v);
121 ASSERT_TRUE(r.IsSuccess()) << r.Error();
122
123 r = p.AddShader(&f);
124 ASSERT_TRUE(r.IsSuccess()) << r.Error();
125
126 std::vector<std::string> first = {"First", "Second"};
127 std::vector<std::string> second = {"Third", "Forth"};
128
129 r = p.SetShaderOptimizations(&f, first);
130 ASSERT_TRUE(r.IsSuccess()) << r.Error();
131
132 r = p.SetShaderOptimizations(&v, second);
133 ASSERT_TRUE(r.IsSuccess()) << r.Error();
134
135 const auto& shaders = p.GetShaders();
136 EXPECT_EQ(2U, shaders.size());
137 EXPECT_EQ(second, shaders[0].GetShaderOptimizations());
138 EXPECT_EQ(first, shaders[1].GetShaderOptimizations());
139}
140
141TEST_F(AmberScriptPipelineTest, DuplicateShaderOptimizations) {
142 Shader v(ShaderType::kVertex);
143
144 Pipeline p(PipelineType::kGraphics);
145 Result r = p.AddShader(&v);
146 ASSERT_TRUE(r.IsSuccess()) << r.Error();
147
148 std::vector<std::string> data = {"One", "One"};
149 r = p.SetShaderOptimizations(&v, data);
150 ASSERT_FALSE(r.IsSuccess());
151 EXPECT_EQ("duplicate optimization flag (One) set on shader", r.Error());
152}
153
154TEST_F(AmberScriptPipelineTest, SetOptimizationForMissingShader) {
155 Pipeline p(PipelineType::kGraphics);
156 Result r = p.SetShaderOptimizations(nullptr, {"One", "Two"});
157 ASSERT_FALSE(r.IsSuccess());
158 EXPECT_EQ("invalid shader specified for optimizations", r.Error());
159}
160
161TEST_F(AmberScriptPipelineTest, SetOptimizationForInvalidShader) {
162 Shader v(ShaderType::kVertex);
163 v.SetName("my_shader");
164
165 Pipeline p(PipelineType::kGraphics);
166 Result r = p.SetShaderOptimizations(&v, {"One", "Two"});
167 ASSERT_FALSE(r.IsSuccess());
168 EXPECT_EQ("unknown shader specified for optimizations: my_shader", r.Error());
169}
170
171TEST_F(AmberScriptPipelineTest,
172 GraphicsPipelineRequiresVertexAndFragmentShader) {
173 Shader v(ShaderType::kVertex);
174 Shader f(ShaderType::kFragment);
175 Shader g(ShaderType::kGeometry);
176
177 Pipeline p(PipelineType::kGraphics);
178 Result r = p.AddShader(&v);
179 EXPECT_TRUE(r.IsSuccess()) << r.Error();
180
181 r = p.AddShader(&g);
182 EXPECT_TRUE(r.IsSuccess()) << r.Error();
183
184 r = p.AddShader(&f);
185 EXPECT_TRUE(r.IsSuccess()) << r.Error();
186
187 r = p.Validate();
188 EXPECT_TRUE(r.IsSuccess()) << r.Error();
189}
190
191TEST_F(AmberScriptPipelineTest, GraphicsPipelineMissingFragmentShader) {
192 Shader v(ShaderType::kVertex);
193 Shader g(ShaderType::kGeometry);
194
195 Pipeline p(PipelineType::kGraphics);
196 Result r = p.AddShader(&v);
197 EXPECT_TRUE(r.IsSuccess()) << r.Error();
198
199 r = p.AddShader(&g);
200 EXPECT_TRUE(r.IsSuccess()) << r.Error();
201
202 r = p.Validate();
203 EXPECT_FALSE(r.IsSuccess()) << r.Error();
204 EXPECT_EQ("graphics pipeline requires a fragment shader", r.Error());
205}
206
207TEST_F(AmberScriptPipelineTest, GraphicsPipelineMissingVertexShader) {
208 Shader f(ShaderType::kFragment);
209 Shader g(ShaderType::kGeometry);
210
211 Pipeline p(PipelineType::kGraphics);
212 Result r = p.AddShader(&g);
213 EXPECT_TRUE(r.IsSuccess()) << r.Error();
214
215 r = p.AddShader(&f);
216 EXPECT_TRUE(r.IsSuccess()) << r.Error();
217
218 r = p.Validate();
219 EXPECT_FALSE(r.IsSuccess()) << r.Error();
220 EXPECT_EQ("graphics pipeline requires a vertex shader", r.Error());
221}
222
223TEST_F(AmberScriptPipelineTest,
224 GraphicsPipelineMissingVertexAndFragmentShader) {
225 Shader g(ShaderType::kGeometry);
226
227 Pipeline p(PipelineType::kGraphics);
228 Result r = p.AddShader(&g);
229 EXPECT_TRUE(r.IsSuccess()) << r.Error();
230
231 r = p.Validate();
232 EXPECT_FALSE(r.IsSuccess()) << r.Error();
233 EXPECT_EQ("graphics pipeline requires vertex and fragment shaders",
234 r.Error());
235}
236
237TEST_F(AmberScriptPipelineTest, GraphicsPipelineWihoutShaders) {
238 Pipeline p(PipelineType::kGraphics);
239 Result r = p.Validate();
240 EXPECT_FALSE(r.IsSuccess()) << r.Error();
241 EXPECT_EQ("graphics pipeline requires vertex and fragment shaders",
242 r.Error());
243}
244
245TEST_F(AmberScriptPipelineTest, ComputePipelineRequiresComputeShader) {
246 Shader c(ShaderType::kCompute);
247
248 Pipeline p(PipelineType::kCompute);
249 Result r = p.AddShader(&c);
250 EXPECT_TRUE(r.IsSuccess()) << r.Error();
251
252 r = p.Validate();
253 EXPECT_TRUE(r.IsSuccess()) << r.Error();
254}
255
256TEST_F(AmberScriptPipelineTest, ComputePipelineWithoutShader) {
257 Pipeline p(PipelineType::kCompute);
258 Result r = p.Validate();
259 EXPECT_FALSE(r.IsSuccess()) << r.Error();
260 EXPECT_EQ("compute pipeline requires a compute shader", r.Error());
261}
262
263TEST_F(AmberScriptPipelineTest, SetEntryPointForMissingShader) {
264 Shader c(ShaderType::kCompute);
265 c.SetName("my_shader");
266
267 Pipeline p(PipelineType::kCompute);
268 Result r = p.SetShaderEntryPoint(&c, "test");
269 EXPECT_FALSE(r.IsSuccess());
270 EXPECT_EQ("unknown shader specified for entry point: my_shader", r.Error());
271}
272
273TEST_F(AmberScriptPipelineTest, SetEntryPointForNullShader) {
274 Pipeline p(PipelineType::kCompute);
275 Result r = p.SetShaderEntryPoint(nullptr, "test");
276 EXPECT_FALSE(r.IsSuccess());
277 EXPECT_EQ("invalid shader specified for entry point", r.Error());
278}
279
280TEST_F(AmberScriptPipelineTest, SetBlankEntryPoint) {
281 Shader c(ShaderType::kCompute);
282 Pipeline p(PipelineType::kCompute);
283 Result r = p.AddShader(&c);
284 ASSERT_TRUE(r.IsSuccess()) << r.Error();
285
286 r = p.SetShaderEntryPoint(&c, "");
287 EXPECT_FALSE(r.IsSuccess());
288 EXPECT_EQ("entry point should not be blank", r.Error());
289}
290
291TEST_F(AmberScriptPipelineTest, ShaderDefaultEntryPoint) {
292 Shader c(ShaderType::kCompute);
293 Pipeline p(PipelineType::kCompute);
294 Result r = p.AddShader(&c);
295 ASSERT_TRUE(r.IsSuccess()) << r.Error();
296
297 const auto& shaders = p.GetShaders();
298 ASSERT_EQ(1U, shaders.size());
299 EXPECT_EQ("main", shaders[0].GetEntryPoint());
300}
301
302TEST_F(AmberScriptPipelineTest, SetShaderEntryPoint) {
303 Shader c(ShaderType::kCompute);
304 Pipeline p(PipelineType::kCompute);
305 Result r = p.AddShader(&c);
306 ASSERT_TRUE(r.IsSuccess()) << r.Error();
307
308 r = p.SetShaderEntryPoint(&c, "my_main");
309 ASSERT_TRUE(r.IsSuccess()) << r.Error();
310
311 const auto& shaders = p.GetShaders();
312 ASSERT_EQ(1U, shaders.size());
313 EXPECT_EQ("my_main", shaders[0].GetEntryPoint());
314}
315
316TEST_F(AmberScriptPipelineTest, SetEntryPointMulitpleTimes) {
317 Shader c(ShaderType::kCompute);
318 Pipeline p(PipelineType::kCompute);
319 Result r = p.AddShader(&c);
320 ASSERT_TRUE(r.IsSuccess()) << r.Error();
321
322 r = p.SetShaderEntryPoint(&c, "my_main");
323 ASSERT_TRUE(r.IsSuccess()) << r.Error();
324
325 r = p.SetShaderEntryPoint(&c, "another_main");
326 EXPECT_FALSE(r.IsSuccess());
327 EXPECT_EQ("multiple entry points given for the same shader", r.Error());
328}
329
330} // namespace amberscript
331} // namespace amber