1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 Valve Corporation.
6 * Copyright (c) 2019 The Khronos Group Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief VK_EXT_blend_operation_advanced tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktPipelineBlendOperationAdvancedTests.hpp"
26 #include "vktPipelineImageUtil.hpp"
27 #include "vktPipelineReferenceRenderer.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkObjUtil.hpp"
36
37 #include "tcuTestLog.hpp"
38 #include "tcuImageCompare.hpp"
39
40 namespace vkt
41 {
42 namespace pipeline
43 {
44
45 using namespace vk;
46
47 namespace
48 {
49 using tcu::Vec3;
50 using tcu::Vec4;
51
52 const deUint32 widthArea = 32u;
53 const deUint32 heightArea = 32u;
54
55 static const float A1 = 0.750f; // Between 1 and 0.5
56 static const float A2 = 0.375f; // Between 0.5 and 0.25
57 static const float A3 = 0.125f; // Between 0.25 and 0.0
58
59 const Vec4 srcColors[] = {
60 // Test that pre-multiplied is converted correctly.
61 // Should not test invalid premultiplied colours (1, 1, 1, 0).
62 { 1.000f, 0.750f, 0.500f, 1.00f },
63 { 0.250f, 0.125f, 0.000f, 1.00f },
64
65 // Test clamping.
66 { 1.000f, 0.750f, 0.500f, 1.00f },
67 { 0.250f, 0.125f, 0.000f, 1.00f },
68 { 1.000f, 0.750f, 0.500f, 1.00f },
69 { 0.250f, 0.125f, 0.000f, 1.00f },
70
71 // Combinations that test other branches of blend equations.
72 { 1.000f, 0.750f, 0.500f, 1.00f },
73 { 0.250f, 0.125f, 0.000f, 1.00f },
74 { 1.000f, 0.750f, 0.500f, 1.00f },
75 { 0.250f, 0.125f, 0.000f, 1.00f },
76 { 1.000f, 0.750f, 0.500f, 1.00f },
77 { 0.250f, 0.125f, 0.000f, 1.00f },
78 { 1.000f, 0.750f, 0.500f, 1.00f },
79 { 0.250f, 0.125f, 0.000f, 1.00f },
80 { 1.000f, 0.750f, 0.500f, 1.00f },
81 { 0.250f, 0.125f, 0.000f, 1.00f },
82
83 // Above block with few different pre-multiplied alpha values.
84 { 1.000f * A1, 0.750f * A1, 0.500f * A1, 1.00f * A1},
85 { 0.250f * A1, 0.125f * A1, 0.000f * A1, 1.00f * A1},
86 { 1.000f * A1, 0.750f * A1, 0.500f * A1, 1.00f * A1},
87 { 0.250f * A1, 0.125f * A1, 0.000f * A1, 1.00f * A1},
88 { 1.000f * A1, 0.750f * A1, 0.500f * A1, 1.00f * A1},
89 { 0.250f * A1, 0.125f * A1, 0.000f * A1, 1.00f * A1},
90 { 1.000f * A1, 0.750f * A1, 0.500f * A1, 1.00f * A1},
91 { 0.250f * A1, 0.125f * A1, 0.000f * A1, 1.00f * A1},
92 { 1.000f * A1, 0.750f * A1, 0.500f * A1, 1.00f * A1},
93 { 0.250f * A1, 0.125f * A1, 0.000f * A1, 1.00f * A1},
94
95 { 1.000f * A2, 0.750f * A2, 0.500f * A2, 1.00f * A2},
96 { 0.250f * A2, 0.125f * A2, 0.000f * A2, 1.00f * A2},
97 { 1.000f * A2, 0.750f * A2, 0.500f * A2, 1.00f * A2},
98 { 0.250f * A2, 0.125f * A2, 0.000f * A2, 1.00f * A2},
99 { 1.000f * A2, 0.750f * A2, 0.500f * A2, 1.00f * A2},
100 { 0.250f * A2, 0.125f * A2, 0.000f * A2, 1.00f * A2},
101 { 1.000f * A2, 0.750f * A2, 0.500f * A2, 1.00f * A2},
102 { 0.250f * A2, 0.125f * A2, 0.000f * A2, 1.00f * A2},
103 { 1.000f * A2, 0.750f * A2, 0.500f * A2, 1.00f * A2},
104 { 0.250f * A2, 0.125f * A2, 0.000f * A2, 1.00f * A2},
105
106 { 1.000f * A3, 0.750f * A3, 0.500f * A3, 1.00f * A3},
107 { 0.250f * A3, 0.125f * A3, 0.000f * A3, 1.00f * A3},
108 { 1.000f * A3, 0.750f * A3, 0.500f * A3, 1.00f * A3},
109 { 0.250f * A3, 0.125f * A3, 0.000f * A3, 1.00f * A3},
110 { 1.000f * A3, 0.750f * A3, 0.500f * A3, 1.00f * A3},
111 { 0.250f * A3, 0.125f * A3, 0.000f * A3, 1.00f * A3},
112 { 1.000f * A3, 0.750f * A3, 0.500f * A3, 1.00f * A3},
113 { 0.250f * A3, 0.125f * A3, 0.000f * A3, 1.00f * A3},
114 { 1.000f * A3, 0.750f * A3, 0.500f * A3, 1.00f * A3},
115 { 0.250f * A3, 0.125f * A3, 0.000f * A3, 1.00f * A3},
116
117 // Add some source colors with alpha component that is different than the respective destination color
118 { 0.750f, 0.750f, 0.500f, 0.750f },
119 { 0.250f, 0.500f, 0.500f, 0.750f },
120 { 0.250f, 0.125f, 0.000f, 0.500f },
121 { 0.250f, 0.250f, 0.500f, 0.500f },
122 { 0.250f, 0.125f, 0.000f, 0.250f },
123 { 0.125f, 0.125f, 0.125f, 0.250f }};
124
125 const Vec4 dstColors[] = {
126 // Test that pre-multiplied is converted correctly.
127 // Should not test invalid premultiplied colours (1, 1, 1, 0).
128 { 0.000f, 0.000f, 0.000f, 0.00f },
129 { 0.000f, 0.000f, 0.000f, 0.00f },
130
131 // Test clamping.
132 { -0.125f, -0.125f, -0.125f, 1.00f },
133 { -0.125f, -0.125f, -0.125f, 1.00f },
134 { 1.125f, 1.125f, 1.125f, 1.00f },
135 { 1.125f, 1.125f, 1.125f, 1.00f },
136
137 // Combinations that test other branches of blend equations.
138 { 1.000f, 1.000f, 1.000f, 1.00f },
139 { 1.000f, 1.000f, 1.000f, 1.00f },
140 { 0.500f, 0.500f, 0.500f, 1.00f },
141 { 0.500f, 0.500f, 0.500f, 1.00f },
142 { 0.250f, 0.250f, 0.250f, 1.00f },
143 { 0.250f, 0.250f, 0.250f, 1.00f },
144 { 0.125f, 0.125f, 0.125f, 1.00f },
145 { 0.125f, 0.125f, 0.125f, 1.00f },
146 { 0.000f, 0.000f, 0.000f, 1.00f },
147 { 0.000f, 0.000f, 0.000f, 1.00f },
148
149 // Above block with few different pre-multiplied alpha values.
150 { 1.000f * A1, 1.000f * A1, 1.000f * A1, 1.00f * A1},
151 { 1.000f * A1, 1.000f * A1, 1.000f * A1, 1.00f * A1},
152 { 0.500f * A1, 0.500f * A1, 0.500f * A1, 1.00f * A1},
153 { 0.500f * A1, 0.500f * A1, 0.500f * A1, 1.00f * A1},
154 { 0.250f * A1, 0.250f * A1, 0.250f * A1, 1.00f * A1},
155 { 0.250f * A1, 0.250f * A1, 0.250f * A1, 1.00f * A1},
156 { 0.125f * A1, 0.125f * A1, 0.125f * A1, 1.00f * A1},
157 { 0.125f * A1, 0.125f * A1, 0.125f * A1, 1.00f * A1},
158 { 0.000f * A1, 0.000f * A1, 0.000f * A1, 1.00f * A1},
159 { 0.000f * A1, 0.000f * A1, 0.000f * A1, 1.00f * A1},
160
161 { 1.000f * A2, 1.000f * A2, 1.000f * A2, 1.00f * A2},
162 { 1.000f * A2, 1.000f * A2, 1.000f * A2, 1.00f * A2},
163 { 0.500f * A2, 0.500f * A2, 0.500f * A2, 1.00f * A2},
164 { 0.500f * A2, 0.500f * A2, 0.500f * A2, 1.00f * A2},
165 { 0.250f * A2, 0.250f * A2, 0.250f * A2, 1.00f * A2},
166 { 0.250f * A2, 0.250f * A2, 0.250f * A2, 1.00f * A2},
167 { 0.125f * A2, 0.125f * A2, 0.125f * A2, 1.00f * A2},
168 { 0.125f * A2, 0.125f * A2, 0.125f * A2, 1.00f * A2},
169 { 0.000f * A2, 0.000f * A2, 0.000f * A2, 1.00f * A2},
170 { 0.000f * A2, 0.000f * A2, 0.000f * A2, 1.00f * A2},
171
172 { 1.000f * A3, 1.000f * A3, 1.000f * A3, 1.00f * A3},
173 { 1.000f * A3, 1.000f * A3, 1.000f * A3, 1.00f * A3},
174 { 0.500f * A3, 0.500f * A3, 0.500f * A3, 1.00f * A3},
175 { 0.500f * A3, 0.500f * A3, 0.500f * A3, 1.00f * A3},
176 { 0.250f * A3, 0.250f * A3, 0.250f * A3, 1.00f * A3 },
177 { 0.250f * A3, 0.250f * A3, 0.250f * A3, 1.00f * A3 },
178 { 0.125f * A3, 0.125f * A3, 0.125f * A3, 1.00f * A3 },
179 { 0.125f * A3, 0.125f * A3, 0.125f * A3, 1.00f * A3 },
180 { 0.000f * A3, 0.000f * A3, 0.000f * A3, 1.00f * A3 },
181 { 0.000f * A3, 0.000f * A3, 0.000f * A3, 1.00f * A3 },
182
183 // Add some source colors with alpha component that is different than the respective source color
184 { 1.000f, 1.000f, 1.000f, 1.000f },
185 { 0.250f, 0.250f, 0.250f, 0.500f },
186 { 0.500f, 0.500f, 0.500f, 0.750f },
187 { 0.250f, 0.250f, 0.250f, 0.250f },
188 { 0.250f, 0.250f, 0.250f, 0.500f },
189 { 0.125f, 0.125f, 0.125f, 0.125f }};
190
191 const Vec4 clearColorVec4 (1.0f, 1.0f, 1.0f, 1.0f);
192
193 enum TestMode
194 {
195 TEST_MODE_GENERIC = 0,
196 TEST_MODE_COHERENT = 1,
197 };
198
199 struct BlendOperationAdvancedParam
200 {
201 TestMode testMode;
202 deUint32 testNumber;
203 std::vector<VkBlendOp> blendOps;
204 deBool coherentOperations;
205 deBool independentBlend;
206 deUint32 colorAttachmentsCount;
207 VkBool32 premultipliedSrcColor;
208 VkBool32 premultipliedDstColor;
209 VkBlendOverlapEXT overlap;
210 };
211
212 // helper functions
generateTestName(struct BlendOperationAdvancedParam param)213 const std::string generateTestName (struct BlendOperationAdvancedParam param)
214 {
215 std::ostringstream result;
216
217 result << ((param.testMode == TEST_MODE_COHERENT && !param.coherentOperations) ? "barrier_" : "");
218 result << "color_attachments_" << param.colorAttachmentsCount;
219 result << "_" << de::toLower(getBlendOverlapEXTStr(param.overlap).toString().substr(3));
220 result << (!param.premultipliedSrcColor ? "_nonpremultipliedsrc" : "");
221 result << (!param.premultipliedDstColor ? "_nonpremultiplieddst" : "");
222 result << "_" << param.testNumber;
223 return result.str();
224 }
225
generateTestDescription()226 const std::string generateTestDescription ()
227 {
228 std::string result("Test advanced blend operations");
229 return result;
230 }
231
calculateWeightingFactors(BlendOperationAdvancedParam param,float alphaSrc,float alphaDst)232 Vec3 calculateWeightingFactors(BlendOperationAdvancedParam param,
233 float alphaSrc, float alphaDst)
234 {
235 Vec3 p = Vec3(0.0f, 0.0f, 0.0f);
236 switch(param.overlap)
237 {
238 case VK_BLEND_OVERLAP_UNCORRELATED_EXT:
239 p.x() = alphaSrc * alphaDst;
240 p.y() = alphaSrc * (1.0f - alphaDst);
241 p.z() = alphaDst * (1.0f - alphaSrc);
242 break;
243 case VK_BLEND_OVERLAP_CONJOINT_EXT:
244 p.x() = deFloatMin(alphaSrc, alphaDst);
245 p.y() = deFloatMax(alphaSrc - alphaDst, 0.0f);
246 p.z() = deFloatMax(alphaDst - alphaSrc, 0.0f);
247 break;
248 case VK_BLEND_OVERLAP_DISJOINT_EXT:
249 p.x() = deFloatMax(alphaSrc + alphaDst - 1.0f, 0.0f);
250 p.y() = deFloatMin(alphaSrc, 1.0f - alphaDst);
251 p.z() = deFloatMin(alphaDst, 1.0f - alphaSrc);
252 break;
253 default:
254 DE_FATAL("Unsupported Advanced Blend Overlap Mode");
255 };
256 return p;
257 }
258
calculateXYZFactors(VkBlendOp op)259 Vec3 calculateXYZFactors(VkBlendOp op)
260 {
261 Vec3 xyz = Vec3(0.0f, 0.0f, 0.0f);
262 switch (op)
263 {
264 case VK_BLEND_OP_ZERO_EXT:
265 xyz = Vec3(0.0f, 0.0f, 0.0f);
266 break;
267
268 case VK_BLEND_OP_DST_ATOP_EXT:
269 case VK_BLEND_OP_SRC_EXT:
270 xyz = Vec3(1.0f, 1.0f, 0.0f);
271 break;
272
273 case VK_BLEND_OP_DST_EXT:
274 xyz = Vec3(1.0f, 0.0f, 1.0f);
275 break;
276
277 case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
278 case VK_BLEND_OP_HSL_COLOR_EXT:
279 case VK_BLEND_OP_HSL_SATURATION_EXT:
280 case VK_BLEND_OP_HSL_HUE_EXT:
281 case VK_BLEND_OP_HARDMIX_EXT:
282 case VK_BLEND_OP_PINLIGHT_EXT:
283 case VK_BLEND_OP_LINEARLIGHT_EXT:
284 case VK_BLEND_OP_VIVIDLIGHT_EXT:
285 case VK_BLEND_OP_LINEARBURN_EXT:
286 case VK_BLEND_OP_LINEARDODGE_EXT:
287 case VK_BLEND_OP_EXCLUSION_EXT:
288 case VK_BLEND_OP_DIFFERENCE_EXT:
289 case VK_BLEND_OP_SOFTLIGHT_EXT:
290 case VK_BLEND_OP_HARDLIGHT_EXT:
291 case VK_BLEND_OP_COLORBURN_EXT:
292 case VK_BLEND_OP_COLORDODGE_EXT:
293 case VK_BLEND_OP_LIGHTEN_EXT:
294 case VK_BLEND_OP_DARKEN_EXT:
295 case VK_BLEND_OP_OVERLAY_EXT:
296 case VK_BLEND_OP_SCREEN_EXT:
297 case VK_BLEND_OP_MULTIPLY_EXT:
298 case VK_BLEND_OP_SRC_OVER_EXT:
299 case VK_BLEND_OP_DST_OVER_EXT:
300 xyz = Vec3(1.0f, 1.0f, 1.0f);
301 break;
302
303 case VK_BLEND_OP_SRC_IN_EXT:
304 case VK_BLEND_OP_DST_IN_EXT:
305 xyz = Vec3(1.0f, 0.0f, 0.0f);
306 break;
307
308 case VK_BLEND_OP_SRC_OUT_EXT:
309 xyz = Vec3(0.0f, 1.0f, 0.0f);
310 break;
311
312 case VK_BLEND_OP_DST_OUT_EXT:
313 xyz = Vec3(0.0f, 0.0f, 1.0f);
314 break;
315
316 case VK_BLEND_OP_INVERT_RGB_EXT:
317 case VK_BLEND_OP_INVERT_EXT:
318 case VK_BLEND_OP_SRC_ATOP_EXT:
319 xyz = Vec3(1.0f, 0.0f, 1.0f);
320 break;
321
322 case VK_BLEND_OP_XOR_EXT:
323 xyz = Vec3(0.0f, 1.0f, 1.0f);
324 break;
325
326 default:
327 DE_FATAL("Unsupported f/X/Y/Z Advanced Blend Operations Mode");
328 };
329
330 return xyz;
331 }
332
blendOpOverlay(float src,float dst)333 float blendOpOverlay(float src, float dst)
334 {
335 if (dst <= 0.5f)
336 return (2.0f * src * dst);
337 else
338 return (1.0f - (2.0f * (1.0f - src) * (1.0f - dst)));
339 }
340
blendOpColorDodge(float src,float dst)341 float blendOpColorDodge(float src, float dst)
342 {
343 if (dst <= 0.0f)
344 return 0.0f;
345 else if (src < 1.0f)
346 return deFloatMin(1.0f, (dst / (1.0f - src)));
347 else
348 return 1.0f;
349 }
350
blendOpColorBurn(float src,float dst)351 float blendOpColorBurn(float src, float dst)
352 {
353 if (dst >= 1.0f)
354 return 1.0f;
355 else if (src > 0.0f)
356 return 1.0f - deFloatMin(1.0f, (1.0f - dst) / src);
357 else
358 return 0.0f;
359 }
360
blendOpHardlight(float src,float dst)361 float blendOpHardlight(float src, float dst)
362 {
363 if (src <= 0.5f)
364 return 2.0f * src * dst;
365 else
366 return 1.0f - (2.0f * (1.0f - src) * (1.0f - dst));
367 }
368
blendOpSoftlight(float src,float dst)369 float blendOpSoftlight(float src, float dst)
370 {
371 if (src <= 0.5f)
372 return dst - ((1.0f - (2.0f * src)) * dst * (1.0f - dst));
373 else if (dst <= 0.25f)
374 return dst + (((2.0f * src) - 1.0f) * dst * ((((16.0f * dst) - 12.0f) * dst) + 3.0f));
375 else
376 return dst + (((2.0f * src) - 1.0f) * (deFloatSqrt(dst) - dst));
377 }
378
blendOpLinearDodge(float src,float dst)379 float blendOpLinearDodge(float src, float dst)
380 {
381 if ((src + dst) <= 1.0f)
382 return src + dst;
383 else
384 return 1.0f;
385 }
386
blendOpLinearBurn(float src,float dst)387 float blendOpLinearBurn(float src, float dst)
388 {
389 if ((src + dst) > 1.0f)
390 return src + dst - 1.0f;
391 else
392 return 0.0f;
393 }
394
blendOpVividLight(float src,float dst)395 float blendOpVividLight(float src, float dst)
396 {
397 if (src <= 0.0f)
398 return 0.0f;
399 if (src < 0.5f)
400 return 1.0f - (deFloatMin(1.0f, (1.0f - dst) / (2.0f * src)));
401 if (src < 1.0f)
402 return deFloatMin(1.0f, dst / (2.0f * (1.0f - src)));
403 else
404 return 1.0f;
405 }
406
blendOpLinearLight(float src,float dst)407 float blendOpLinearLight(float src, float dst)
408 {
409 if ((2.0f * src + dst) > 2.0f)
410 return 1.0f;
411 if ((2.0f * src + dst) <= 1.0f)
412 return 0.0f;
413 return (2.0f * src) + dst - 1.0f;
414 }
415
blendOpPinLight(float src,float dst)416 float blendOpPinLight(float src, float dst)
417 {
418 if (((2.0f * src - 1.0f) > dst) && src < 0.5f)
419 return 0.0f;
420 if (((2.0f * src - 1.0f) > dst) && src >= 0.5f)
421 return 2.0f * src - 1.0f;
422 if (((2.0f * src - 1.0f) <= dst) && src < (0.5f * dst))
423 return 2.0f * src;
424 if (((2.0f * src - 1.0f) <= dst) && src >= (0.5f * dst))
425 return dst;
426 return 0.0f;
427 }
428
blendOpHardmix(float src,float dst)429 float blendOpHardmix(float src, float dst)
430 {
431 if ((src + dst) < 1.0f)
432 return 0.0f;
433 else
434 return 1.0f;
435 }
436
minv3(Vec3 c)437 float minv3(Vec3 c)
438 {
439 return deFloatMin(deFloatMin(c.x(), c.y()), c.z());
440 }
441
maxv3(Vec3 c)442 float maxv3(Vec3 c)
443 {
444 return deFloatMax(deFloatMax(c.x(), c.y()), c.z());
445 }
446
lumv3(Vec3 c)447 float lumv3(Vec3 c)
448 {
449 return dot(c, Vec3(0.3f, 0.59f, 0.11f));
450 }
451
satv3(Vec3 c)452 float satv3(Vec3 c)
453 {
454 return maxv3(c) - minv3(c);
455 }
456
457 // If any color components are outside [0,1], adjust the color to
458 // get the components in range.
clipColor(Vec3 color)459 Vec3 clipColor(Vec3 color)
460 {
461 float lum = lumv3(color);
462 float mincol = minv3(color);
463 float maxcol = maxv3(color);
464
465 if (mincol < 0.0)
466 {
467 color = lum + ((color - lum) * lum) / (lum - mincol);
468 }
469 if (maxcol > 1.0)
470 {
471 color = lum + ((color - lum) * (1.0f - lum)) / (maxcol - lum);
472 }
473 return color;
474 }
475
476 // Take the base RGB color <cbase> and override its luminosity
477 // with that of the RGB color <clum>.
setLum(Vec3 cbase,Vec3 clum)478 Vec3 setLum(Vec3 cbase, Vec3 clum)
479 {
480 float lbase = lumv3(cbase);
481 float llum = lumv3(clum);
482 float ldiff = llum - lbase;
483
484 Vec3 color = cbase + Vec3(ldiff);
485 return clipColor(color);
486 }
487
488 // Take the base RGB color <cbase> and override its saturation with
489 // that of the RGB color <csat>. The override the luminosity of the
490 // result with that of the RGB color <clum>.
setLumSat(Vec3 cbase,Vec3 csat,Vec3 clum)491 Vec3 setLumSat(Vec3 cbase, Vec3 csat, Vec3 clum)
492 {
493 float minbase = minv3(cbase);
494 float sbase = satv3(cbase);
495 float ssat = satv3(csat);
496 Vec3 color;
497
498 if (sbase > 0)
499 {
500 // Equivalent (modulo rounding errors) to setting the
501 // smallest (R,G,B) component to 0, the largest to <ssat>,
502 // and interpolating the "middle" component based on its
503 // original value relative to the smallest/largest.
504 color = (cbase - minbase) * ssat / sbase;
505 } else {
506 color = Vec3(0.0f);
507 }
508 return setLum(color, clum);
509 }
510
calculateFFunction(VkBlendOp op,Vec3 src,Vec3 dst)511 Vec3 calculateFFunction(VkBlendOp op,
512 Vec3 src, Vec3 dst)
513 {
514 Vec3 f = Vec3(0.0f, 0.0f, 0.0f);
515
516 switch (op)
517 {
518 case VK_BLEND_OP_XOR_EXT:
519 case VK_BLEND_OP_SRC_OUT_EXT:
520 case VK_BLEND_OP_DST_OUT_EXT:
521 case VK_BLEND_OP_ZERO_EXT:
522 f = Vec3(0.0f, 0.0f, 0.0f);
523 break;
524
525 case VK_BLEND_OP_SRC_ATOP_EXT:
526 case VK_BLEND_OP_SRC_IN_EXT:
527 case VK_BLEND_OP_SRC_OVER_EXT:
528 case VK_BLEND_OP_SRC_EXT:
529 f = src;
530 break;
531
532 case VK_BLEND_OP_DST_ATOP_EXT:
533 case VK_BLEND_OP_DST_IN_EXT:
534 case VK_BLEND_OP_DST_OVER_EXT:
535 case VK_BLEND_OP_DST_EXT:
536 f = dst;
537 break;
538
539 case VK_BLEND_OP_MULTIPLY_EXT:
540 f = src * dst;
541 break;
542
543 case VK_BLEND_OP_SCREEN_EXT:
544 f = src + dst - (src*dst);
545 break;
546
547 case VK_BLEND_OP_OVERLAY_EXT:
548 f.x() = blendOpOverlay(src.x(), dst.x());
549 f.y() = blendOpOverlay(src.y(), dst.y());
550 f.z() = blendOpOverlay(src.z(), dst.z());
551 break;
552
553 case VK_BLEND_OP_DARKEN_EXT:
554 f.x() = deFloatMin(src.x(), dst.x());
555 f.y() = deFloatMin(src.y(), dst.y());
556 f.z() = deFloatMin(src.z(), dst.z());
557 break;
558
559 case VK_BLEND_OP_LIGHTEN_EXT:
560 f.x() = deFloatMax(src.x(), dst.x());
561 f.y() = deFloatMax(src.y(), dst.y());
562 f.z() = deFloatMax(src.z(), dst.z());
563 break;
564
565 case VK_BLEND_OP_COLORDODGE_EXT:
566 f.x() = blendOpColorDodge(src.x(), dst.x());
567 f.y() = blendOpColorDodge(src.y(), dst.y());
568 f.z() = blendOpColorDodge(src.z(), dst.z());
569 break;
570
571 case VK_BLEND_OP_COLORBURN_EXT:
572 f.x() = blendOpColorBurn(src.x(), dst.x());
573 f.y() = blendOpColorBurn(src.y(), dst.y());
574 f.z() = blendOpColorBurn(src.z(), dst.z());
575 break;
576
577 case VK_BLEND_OP_HARDLIGHT_EXT:
578 f.x() = blendOpHardlight(src.x(), dst.x());
579 f.y() = blendOpHardlight(src.y(), dst.y());
580 f.z() = blendOpHardlight(src.z(), dst.z());
581 break;
582
583 case VK_BLEND_OP_SOFTLIGHT_EXT:
584 f.x() = blendOpSoftlight(src.x(), dst.x());
585 f.y() = blendOpSoftlight(src.y(), dst.y());
586 f.z() = blendOpSoftlight(src.z(), dst.z());
587 break;
588
589 case VK_BLEND_OP_DIFFERENCE_EXT:
590 f.x() = deFloatAbs(dst.x() - src.x());
591 f.y() = deFloatAbs(dst.y() - src.y());
592 f.z() = deFloatAbs(dst.z() - src.z());
593 break;
594
595
596 case VK_BLEND_OP_EXCLUSION_EXT:
597 f = src + dst - (2.0f * src * dst);
598 break;
599
600 case VK_BLEND_OP_INVERT_EXT:
601 f = 1.0f - dst;
602 break;
603
604 case VK_BLEND_OP_INVERT_RGB_EXT:
605 f = src * (1.0f - dst);
606 break;
607
608 case VK_BLEND_OP_LINEARDODGE_EXT:
609 f.x() = blendOpLinearDodge(src.x(), dst.x());
610 f.y() = blendOpLinearDodge(src.y(), dst.y());
611 f.z() = blendOpLinearDodge(src.z(), dst.z());
612 break;
613
614 case VK_BLEND_OP_LINEARBURN_EXT:
615 f.x() = blendOpLinearBurn(src.x(), dst.x());
616 f.y() = blendOpLinearBurn(src.y(), dst.y());
617 f.z() = blendOpLinearBurn(src.z(), dst.z());
618 break;
619
620 case VK_BLEND_OP_VIVIDLIGHT_EXT:
621 f.x() = blendOpVividLight(src.x(), dst.x());
622 f.y() = blendOpVividLight(src.y(), dst.y());
623 f.z() = blendOpVividLight(src.z(), dst.z());
624 break;
625
626 case VK_BLEND_OP_LINEARLIGHT_EXT:
627 f.x() = blendOpLinearLight(src.x(), dst.x());
628 f.y() = blendOpLinearLight(src.y(), dst.y());
629 f.z() = blendOpLinearLight(src.z(), dst.z());
630 break;
631
632 case VK_BLEND_OP_PINLIGHT_EXT:
633 f.x() = blendOpPinLight(src.x(), dst.x());
634 f.y() = blendOpPinLight(src.y(), dst.y());
635 f.z() = blendOpPinLight(src.z(), dst.z());
636 break;
637
638 case VK_BLEND_OP_HARDMIX_EXT:
639 f.x() = blendOpHardmix(src.x(), dst.x());
640 f.y() = blendOpHardmix(src.y(), dst.y());
641 f.z() = blendOpHardmix(src.z(), dst.z());
642 break;
643
644 case VK_BLEND_OP_HSL_HUE_EXT:
645 f = setLumSat(src, dst, dst);
646 break;
647
648 case VK_BLEND_OP_HSL_SATURATION_EXT:
649 f = setLumSat(dst, src, dst);
650 break;
651
652 case VK_BLEND_OP_HSL_COLOR_EXT:
653 f = setLum(src, dst);
654 break;
655
656 case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
657 f = setLum(dst, src);
658 break;
659
660 default:
661 DE_FATAL("Unsupported f/X/Y/Z Advanced Blend Operations Mode");
662 };
663
664 return f;
665 }
666
additionalRGBBlendOperations(VkBlendOp op,Vec4 src,Vec4 dst)667 Vec4 additionalRGBBlendOperations(VkBlendOp op,
668 Vec4 src, Vec4 dst)
669 {
670 Vec4 res = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
671
672 switch (op)
673 {
674 case VK_BLEND_OP_PLUS_EXT:
675 res = src + dst;
676 break;
677
678 case VK_BLEND_OP_PLUS_CLAMPED_EXT:
679 res.x() = deFloatMin(1.0f, src.x() + dst.x());
680 res.y() = deFloatMin(1.0f, src.y() + dst.y());
681 res.z() = deFloatMin(1.0f, src.z() + dst.z());
682 res.w() = deFloatMin(1.0f, src.w() + dst.w());
683 break;
684
685 case VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT:
686 res.x() = deFloatMin(deFloatMin(1.0f, src.w() + dst.w()), src.x() + dst.x());
687 res.y() = deFloatMin(deFloatMin(1.0f, src.w() + dst.w()), src.y() + dst.y());
688 res.z() = deFloatMin(deFloatMin(1.0f, src.w() + dst.w()), src.z() + dst.z());
689 res.w() = deFloatMin(1.0f, src.w() + dst.w());
690 break;
691
692 case VK_BLEND_OP_PLUS_DARKER_EXT:
693 res.x() = deFloatMax(0.0f, deFloatMin(1.0f, src.w() + dst.w()) - ((src.w() - src.x()) + (dst.w() - dst.x())));
694 res.y() = deFloatMax(0.0f, deFloatMin(1.0f, src.w() + dst.w()) - ((src.w() - src.y()) + (dst.w() - dst.y())));
695 res.z() = deFloatMax(0.0f, deFloatMin(1.0f, src.w() + dst.w()) - ((src.w() - src.z()) + (dst.w() - dst.z())));
696 res.w() = deFloatMin(1.0f, src.w() + dst.w());
697 break;
698
699 case VK_BLEND_OP_MINUS_EXT:
700 res = dst - src;
701 break;
702
703 case VK_BLEND_OP_MINUS_CLAMPED_EXT:
704 res.x() = deFloatMax(0.0f, dst.x() - src.x());
705 res.y() = deFloatMax(0.0f, dst.y() - src.y());
706 res.z() = deFloatMax(0.0f, dst.z() - src.z());
707 res.w() = deFloatMax(0.0f, dst.w() - src.w());
708 break;
709
710 case VK_BLEND_OP_CONTRAST_EXT:
711 res.x() = (dst.w() / 2.0f) + 2.0f * (dst.x() - (dst.w() / 2.0f)) * (src.x() - (src.w() / 2.0f));
712 res.y() = (dst.w() / 2.0f) + 2.0f * (dst.y() - (dst.w() / 2.0f)) * (src.y() - (src.w() / 2.0f));
713 res.z() = (dst.w() / 2.0f) + 2.0f * (dst.z() - (dst.w() / 2.0f)) * (src.z() - (src.w() / 2.0f));
714 res.w() = dst.w();
715 break;
716
717 case VK_BLEND_OP_INVERT_OVG_EXT:
718 res.x() = src.w() * (1.0f - dst.x()) + (1.0f - src.w()) * dst.x();
719 res.y() = src.w() * (1.0f - dst.y()) + (1.0f - src.w()) * dst.y();
720 res.z() = src.w() * (1.0f - dst.z()) + (1.0f - src.w()) * dst.z();
721 res.w() = src.w() + dst.w() - src.w() * dst.w();
722 break;
723
724 case VK_BLEND_OP_RED_EXT:
725 res = dst;
726 res.x() = src.x();
727 break;
728
729 case VK_BLEND_OP_GREEN_EXT:
730 res = dst;
731 res.y() = src.y();
732 break;
733
734 case VK_BLEND_OP_BLUE_EXT:
735 res = dst;
736 res.z() = src.z();
737 break;
738
739 default:
740 DE_FATAL("Unsupported blend operation");
741 };
742 return res;
743 }
744
calculateFinalColor(BlendOperationAdvancedParam param,VkBlendOp op,Vec4 source,Vec4 destination)745 Vec4 calculateFinalColor(BlendOperationAdvancedParam param, VkBlendOp op,
746 Vec4 source, Vec4 destination)
747 {
748 Vec4 result = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
749 Vec3 srcColor = source.xyz();
750 Vec3 dstColor = destination.xyz();
751
752 // Calculate weighting factors
753 Vec3 p = calculateWeightingFactors(param, source.w(), destination.w());
754
755 if (op > VK_BLEND_OP_MAX && op < VK_BLEND_OP_PLUS_EXT)
756 {
757 {
758 // If srcPremultiplied is set to VK_TRUE, the fragment color components
759 // are considered to have been premultiplied by the A component prior to
760 // blending. The base source color (Rs',Gs',Bs') is obtained by dividing
761 // through by the A component.
762 if (param.premultipliedSrcColor)
763 {
764 if (source.w() != 0.0f)
765 srcColor = srcColor / source.w();
766 else
767 srcColor = Vec3(0.0f, 0.0f, 0.0f);
768 }
769 // If dstPremultiplied is set to VK_TRUE, the destination components are
770 // considered to have been premultiplied by the A component prior to
771 // blending. The base destination color (Rd',Gd',Bd') is obtained by dividing
772 // through by the A component.
773 if (param.premultipliedDstColor)
774 {
775 if (destination.w() != 0.0f)
776 dstColor = dstColor / destination.w();
777 else
778 dstColor = Vec3(0.0f, 0.0f, 0.0f);
779 }
780 }
781
782 // Calculate X, Y, Z terms of the equation
783 Vec3 xyz = calculateXYZFactors(op);
784 Vec3 fSrcDst = calculateFFunction(op, srcColor, dstColor);
785
786 result.x() = fSrcDst.x() * p.x() + xyz.y() * srcColor.x() * p.y() + xyz.z() * dstColor.x() * p.z();
787 result.y() = fSrcDst.y() * p.x() + xyz.y() * srcColor.y() * p.y() + xyz.z() * dstColor.y() * p.z();
788 result.z() = fSrcDst.z() * p.x() + xyz.y() * srcColor.z() * p.y() + xyz.z() * dstColor.z() * p.z();
789 result.w() = xyz.x() * p.x() + xyz.y() * p.y() + xyz.z() * p.z();
790 }
791 else if (op >= VK_BLEND_OP_PLUS_EXT && op < VK_BLEND_OP_MAX_ENUM)
792 {
793 // Premultiply colors for additional RGB blend operations. The formula is different than the rest of operations.
794 {
795 if (!param.premultipliedSrcColor)
796 {
797 srcColor = srcColor * source.w();
798 }
799
800 if (!param.premultipliedDstColor)
801 {
802 dstColor = dstColor * destination.w();
803 }
804
805 }
806 Vec4 src = Vec4(srcColor.x(), srcColor.y(), srcColor.z(), source.w());
807 Vec4 dst = Vec4(dstColor.x(), dstColor.y(), dstColor.z(), destination.w());
808 result = additionalRGBBlendOperations(op, src, dst);
809 }
810 else
811 {
812 DE_FATAL("Unsupported Blend Operation");
813 }
814 return result;
815 }
816
getCoordinates(deUint32 index,deInt32 & x,deInt32 & y)817 static inline void getCoordinates (deUint32 index, deInt32 &x, deInt32 &y)
818 {
819 x = index % widthArea;
820 y = index / heightArea;
821 }
822
createPoints(void)823 static inline std::vector<Vec4> createPoints (void)
824 {
825 std::vector<Vec4> vertices;
826 vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
827 vertices.push_back(Vec4( 1.0f, 1.0f, 0.0f, 1.0f));
828 vertices.push_back(Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
829 vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
830 vertices.push_back(Vec4( 1.0f, 1.0f, 0.0f, 1.0f));
831 vertices.push_back(Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
832 return vertices;
833 }
834
835 template <class Test>
newTestCase(tcu::TestContext & testContext,const BlendOperationAdvancedParam testParam)836 vkt::TestCase* newTestCase (tcu::TestContext& testContext,
837 const BlendOperationAdvancedParam testParam)
838 {
839 return new Test(testContext,
840 generateTestName(testParam).c_str(),
841 generateTestDescription().c_str(),
842 testParam);
843 }
844
makeTestRenderPass(BlendOperationAdvancedParam param,const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,VkAttachmentLoadOp colorLoadOp=VK_ATTACHMENT_LOAD_OP_CLEAR)845 Move<VkRenderPass> makeTestRenderPass (BlendOperationAdvancedParam param,
846 const DeviceInterface& vk,
847 const VkDevice device,
848 const VkFormat colorFormat,
849 VkAttachmentLoadOp colorLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR)
850 {
851 const VkAttachmentDescription colorAttachmentDescription =
852 {
853 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
854 colorFormat, // VkFormat format
855 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
856 colorLoadOp, // VkAttachmentLoadOp loadOp
857 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
858 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
859 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
860 (colorLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD) ?
861 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL :
862 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
863 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
864 };
865
866 std::vector<VkAttachmentDescription> attachmentDescriptions;
867 std::vector<VkAttachmentReference> colorAttachmentRefs;
868
869
870 for (deUint32 i = 0; i < param.colorAttachmentsCount; i++)
871 {
872 attachmentDescriptions.push_back(colorAttachmentDescription);
873 const VkAttachmentReference colorAttachmentRef =
874 {
875 i, // deUint32 attachment
876 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout
877 };
878
879 colorAttachmentRefs.push_back(colorAttachmentRef);
880 }
881
882 const VkSubpassDescription subpassDescription =
883 {
884 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
885 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
886 0u, // deUint32 inputAttachmentCount
887 DE_NULL, // const VkAttachmentReference* pInputAttachments
888 param.colorAttachmentsCount, // deUint32 colorAttachmentCount
889 colorAttachmentRefs.data(), // const VkAttachmentReference* pColorAttachments
890 DE_NULL, // const VkAttachmentReference* pResolveAttachments
891 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
892 0u, // deUint32 preserveAttachmentCount
893 DE_NULL // const deUint32* pPreserveAttachments
894 };
895
896 const VkRenderPassCreateInfo renderPassInfo =
897 {
898 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
899 DE_NULL, // const void* pNext
900 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
901 (deUint32)attachmentDescriptions.size(), // deUint32 attachmentCount
902 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments
903 1u, // deUint32 subpassCount
904 &subpassDescription, // const VkSubpassDescription* pSubpasses
905 0u, // deUint32 dependencyCount
906 DE_NULL // const VkSubpassDependency* pDependencies
907 };
908
909 return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
910 }
911
createBufferAndBindMemory(Context & context,VkDeviceSize size,VkBufferUsageFlags usage,de::MovePtr<Allocation> * pAlloc)912 Move<VkBuffer> createBufferAndBindMemory (Context& context, VkDeviceSize size, VkBufferUsageFlags usage, de::MovePtr<Allocation>* pAlloc)
913 {
914 const DeviceInterface& vk = context.getDeviceInterface();
915 const VkDevice vkDevice = context.getDevice();
916 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
917
918 const VkBufferCreateInfo vertexBufferParams =
919 {
920 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
921 DE_NULL, // const void* pNext;
922 0u, // VkBufferCreateFlags flags;
923 size, // VkDeviceSize size;
924 usage, // VkBufferUsageFlags usage;
925 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
926 1u, // deUint32 queueFamilyCount;
927 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
928 };
929
930 Move<VkBuffer> vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
931
932 *pAlloc = context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
933 VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));
934
935 return vertexBuffer;
936 }
937
createImage2DAndBindMemory(Context & context,VkFormat format,deUint32 width,deUint32 height,VkImageUsageFlags usage,VkSampleCountFlagBits sampleCount,de::details::MovePtr<Allocation> * pAlloc)938 Move<VkImage> createImage2DAndBindMemory (Context& context,
939 VkFormat format,
940 deUint32 width,
941 deUint32 height,
942 VkImageUsageFlags usage,
943 VkSampleCountFlagBits sampleCount,
944 de::details::MovePtr<Allocation>* pAlloc)
945 {
946 const DeviceInterface& vk = context.getDeviceInterface();
947 const VkDevice vkDevice = context.getDevice();
948 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
949
950 const VkImageCreateInfo colorImageParams =
951 {
952 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
953 DE_NULL, // const void* pNext;
954 0u, // VkImageCreateFlags flags;
955 VK_IMAGE_TYPE_2D, // VkImageType imageType;
956 format, // VkFormat format;
957 { width, height, 1u }, // VkExtent3D extent;
958 1u, // deUint32 mipLevels;
959 1u, // deUint32 arraySize;
960 sampleCount, // deUint32 samples;
961 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
962 usage, // VkImageUsageFlags usage;
963 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
964 1u, // deUint32 queueFamilyCount;
965 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
966 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
967 };
968
969 Move<VkImage> image = createImage(vk, vkDevice, &colorImageParams);
970
971 *pAlloc = context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any);
972 VK_CHECK(vk.bindImageMemory(vkDevice, *image, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));
973
974 return image;
975 }
976
977 // Test Classes
978 class BlendOperationAdvancedTestInstance : public vkt::TestInstance
979 {
980 public:
981 BlendOperationAdvancedTestInstance (Context& context,
982 const BlendOperationAdvancedParam param);
983 virtual ~BlendOperationAdvancedTestInstance (void);
984 virtual tcu::TestStatus iterate (void);
985 protected:
986 void prepareRenderPass (VkFramebuffer framebuffer, VkPipeline pipeline) const;
987 void prepareCommandBuffer (void) const;
988 void buildPipeline (VkBool32 premultiplySrc, VkBool32 premultiplyDst);
989 void bindShaderStage (VkShaderStageFlagBits stage,
990 const char* sourceName,
991 const char* entryName);
992 deBool verifyTestResult (void);
993 protected:
994 const BlendOperationAdvancedParam m_param;
995 const tcu::UVec2 m_renderSize;
996 const VkFormat m_colorFormat;
997 Move<VkPipelineLayout> m_pipelineLayout;
998
999 Move<VkBuffer> m_vertexBuffer;
1000 de::MovePtr<Allocation> m_vertexBufferMemory;
1001 std::vector<Vec4> m_vertices;
1002
1003 Move<VkRenderPass> m_renderPass;
1004 Move<VkCommandPool> m_cmdPool;
1005 Move<VkCommandBuffer> m_cmdBuffer;
1006 std::vector<Move<VkImage>> m_colorImages;
1007 std::vector<Move<VkImageView>> m_colorAttachmentViews;
1008 std::vector<de::MovePtr<Allocation>> m_colorImageAllocs;
1009 std::vector<VkImageMemoryBarrier> m_imageLayoutBarriers;
1010 Move<VkFramebuffer> m_framebuffer;
1011 Move<VkPipeline> m_pipeline;
1012
1013 Move<VkShaderModule> m_shaderModules[2];
1014 deUint32 m_shaderStageCount;
1015 VkPipelineShaderStageCreateInfo m_shaderStageInfo[2];
1016 };
1017
bindShaderStage(VkShaderStageFlagBits stage,const char * sourceName,const char * entryName)1018 void BlendOperationAdvancedTestInstance::bindShaderStage (VkShaderStageFlagBits stage,
1019 const char* sourceName,
1020 const char* entryName)
1021 {
1022 const DeviceInterface& vk = m_context.getDeviceInterface();
1023 const VkDevice vkDevice = m_context.getDevice();
1024
1025 // Create shader module
1026 deUint32* code = (deUint32*)m_context.getBinaryCollection().get(sourceName).getBinary();
1027 deUint32 codeSize = (deUint32)m_context.getBinaryCollection().get(sourceName).getSize();
1028
1029 const VkShaderModuleCreateInfo moduleCreateInfo =
1030 {
1031 VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType;
1032 DE_NULL, // const void* pNext;
1033 0u, // VkShaderModuleCreateFlags flags;
1034 codeSize, // deUintptr codeSize;
1035 code, // const deUint32* pCode;
1036 };
1037
1038 m_shaderModules[m_shaderStageCount] = createShaderModule(vk, vkDevice, &moduleCreateInfo);
1039
1040 // Prepare shader stage info
1041 m_shaderStageInfo[m_shaderStageCount].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1042 m_shaderStageInfo[m_shaderStageCount].pNext = DE_NULL;
1043 m_shaderStageInfo[m_shaderStageCount].flags = 0u;
1044 m_shaderStageInfo[m_shaderStageCount].stage = stage;
1045 m_shaderStageInfo[m_shaderStageCount].module = *m_shaderModules[m_shaderStageCount];
1046 m_shaderStageInfo[m_shaderStageCount].pName = entryName;
1047 m_shaderStageInfo[m_shaderStageCount].pSpecializationInfo = DE_NULL;
1048
1049 m_shaderStageCount++;
1050 }
1051
buildPipeline(VkBool32 srcPremultiplied,VkBool32 dstPremultiplied)1052 void BlendOperationAdvancedTestInstance::buildPipeline (VkBool32 srcPremultiplied,
1053 VkBool32 dstPremultiplied)
1054 {
1055 const DeviceInterface& vk = m_context.getDeviceInterface();
1056 const VkDevice vkDevice = m_context.getDevice();
1057
1058 // Create pipeline
1059 const VkVertexInputBindingDescription vertexInputBindingDescription =
1060 {
1061 0u, // deUint32 binding;
1062 sizeof(Vec4), // deUint32 strideInBytes;
1063 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
1064 };
1065
1066 const VkVertexInputAttributeDescription vertexInputAttributeDescription =
1067 {
1068 0u, // deUint32 location;
1069 0u, // deUint32 binding;
1070 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1071 0u // deUint32 offsetInBytes;
1072 };
1073
1074 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1075 {
1076 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1077 DE_NULL, // const void* pNext;
1078 0u, // VkPipelineVertexInputStateCreateFlags flags;
1079 1u, // deUint32 vertexBindingDescriptionCount;
1080 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1081 1u, // deUint32 vertexAttributeDescriptionCount;
1082 &vertexInputAttributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1083 };
1084
1085 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
1086 {
1087 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
1088 DE_NULL, // const void* pNext;
1089 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
1090 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
1091 VK_FALSE, // VkBool32 primitiveRestartEnable;
1092 };
1093
1094 const VkRect2D scissor = makeRect2D(m_renderSize);
1095 VkViewport viewport = makeViewport(m_renderSize);
1096
1097 const VkPipelineViewportStateCreateInfo viewportStateParams =
1098 {
1099 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
1100 DE_NULL, // const void* pNext;
1101 0u, // VkPipelineViewportStateCreateFlags flags;
1102 1u, // deUint32 viewportCount;
1103 &viewport, // const VkViewport* pViewports;
1104 1u, // deUint32 scissorCount;
1105 &scissor // const VkRect2D* pScissors;
1106 };
1107
1108 const VkPipelineRasterizationStateCreateInfo rasterStateParams =
1109 {
1110 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
1111 DE_NULL, // const void* pNext;
1112 0u, // VkPipelineRasterizationStateCreateFlags flags;
1113 VK_FALSE, // VkBool32 depthClampEnable;
1114 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
1115 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
1116 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
1117 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
1118 VK_FALSE, // VkBool32 depthBiasEnable;
1119 0.0f, // float depthBiasConstantFactor;
1120 0.0f, // float depthBiasClamp;
1121 0.0f, // float depthBiasSlopeFactor;
1122 1.0f, // float lineWidth;
1123 };
1124
1125 const VkPipelineColorBlendAdvancedStateCreateInfoEXT blendAdvancedStateParams =
1126 {
1127 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT, // VkStructureType sType;
1128 DE_NULL, // const void* pNext;
1129 srcPremultiplied, // VkBool32 srcPremultiplied;
1130 dstPremultiplied, // VkBool32 dstPremultiplied;
1131 m_param.overlap, // VkBlendOverlapEXT blendOverlap;
1132 };
1133
1134 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates;
1135
1136 for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
1137 {
1138 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1139 {
1140 VK_TRUE, // VkBool32 blendEnable;
1141 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
1142 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstColorBlendFactor;
1143 m_param.blendOps[i], // VkBlendOp colorBlendOp;
1144 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
1145 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor;
1146 m_param.blendOps[i], // VkBlendOp alphaBlendOp;
1147 VK_COLOR_COMPONENT_R_BIT |
1148 VK_COLOR_COMPONENT_G_BIT |
1149 VK_COLOR_COMPONENT_B_BIT |
1150 VK_COLOR_COMPONENT_A_BIT // VkColorComponentFlags colorWriteMask;
1151 };
1152 colorBlendAttachmentStates.emplace_back(colorBlendAttachmentState);
1153 }
1154
1155 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1156 {
1157 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1158 &blendAdvancedStateParams, // const void* pNext;
1159 0u, // VkPipelineColorBlendStateCreateFlags flags;
1160 VK_FALSE, // VkBool32 logicOpEnable;
1161 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
1162 (deUint32)colorBlendAttachmentStates.size(), // deUint32 attachmentCount;
1163 colorBlendAttachmentStates.data(), // const VkPipelineColorBlendAttachmentState* pAttachments;
1164 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4];
1165 };
1166
1167 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1168 {
1169 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1170 DE_NULL, // const void* pNext;
1171 0u, // VkPipelineMultisampleStateCreateFlags flags;
1172 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
1173 VK_FALSE, // VkBool32 sampleShadingEnable;
1174 0.0f, // float minSampleShading;
1175 DE_NULL, // const VkSampleMask* pSampleMask;
1176 VK_FALSE, // VkBool32 alphaToCoverageEnable;
1177 VK_FALSE, // VkBool32 alphaToOneEnable;
1178 };
1179
1180 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
1181 {
1182 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
1183 DE_NULL, // const void* pNext;
1184 0u, // VkPipelineDepthStencilStateCreateFlags flags;
1185 VK_FALSE, // VkBool32 depthTestEnable;
1186 VK_FALSE, // VkBool32 depthWriteEnable;
1187 VK_COMPARE_OP_NEVER, // VkCompareOp depthCompareOp;
1188 VK_FALSE, // VkBool32 depthBoundsTestEnable;
1189 VK_FALSE, // VkBool32 stencilTestEnable;
1190 // VkStencilOpState front;
1191 {
1192 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
1193 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
1194 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
1195 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
1196 0u, // deUint32 compareMask;
1197 0u, // deUint32 writeMask;
1198 0u, // deUint32 reference;
1199 },
1200 // VkStencilOpState back;
1201 {
1202 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
1203 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
1204 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
1205 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
1206 0u, // deUint32 compareMask;
1207 0u, // deUint32 writeMask;
1208 0u, // deUint32 reference;
1209 },
1210 0.0f, // float minDepthBounds;
1211 1.0f, // float maxDepthBounds;
1212 };
1213
1214 const VkDynamicState dynamicState = VK_DYNAMIC_STATE_SCISSOR;
1215 const VkPipelineDynamicStateCreateInfo dynamicStateParams =
1216 {
1217 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
1218 DE_NULL, // const void* pNext;
1219 0u, // VkPipelineDynamicStateCreateFlags flags;
1220 1u, // uint32_t dynamicStateCount;
1221 &dynamicState // const VkDynamicState* pDynamicStates;
1222 };
1223
1224 const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
1225 {
1226 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
1227 DE_NULL, // const void* pNext;
1228 0u, // VkPipelineCreateFlags flags;
1229 m_shaderStageCount, // deUint32 stageCount;
1230 m_shaderStageInfo, // const VkPipelineShaderStageCreateInfo* pStages;
1231 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
1232 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
1233 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
1234 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
1235 &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterState;
1236 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
1237 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
1238 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
1239 &dynamicStateParams, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
1240 *m_pipelineLayout, // VkPipelineLayout layout;
1241 *m_renderPass, // VkRenderPass renderPass;
1242 0u, // deUint32 subpass;
1243 DE_NULL, // VkPipeline basePipelineHandle;
1244 0u, // deInt32 basePipelineIndex;
1245 };
1246
1247 m_pipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
1248 }
1249
prepareRenderPass(VkFramebuffer framebuffer,VkPipeline pipeline) const1250 void BlendOperationAdvancedTestInstance::prepareRenderPass (VkFramebuffer framebuffer, VkPipeline pipeline) const
1251 {
1252 const DeviceInterface& vk = m_context.getDeviceInterface();
1253
1254 std::vector<VkClearValue> attachmentClearValues;
1255
1256 for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
1257 attachmentClearValues.emplace_back(makeClearValueColor(clearColorVec4));
1258
1259 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
1260 m_param.colorAttachmentsCount, attachmentClearValues.data());
1261 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
1262 VkDeviceSize offsets = 0u;
1263 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets);
1264
1265 // Draw all colors
1266 deUint32 skippedColors = 0u;
1267 for (deUint32 color = 0; color < DE_LENGTH_OF_ARRAY(srcColors); color++)
1268 {
1269 // Skip ill-formed colors when we have non-premultiplied destination colors.
1270 if (m_param.premultipliedDstColor == VK_FALSE)
1271 {
1272 deBool skipColor = false;
1273 for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
1274 {
1275 Vec4 calculatedColor = calculateFinalColor(m_param, m_param.blendOps[i], srcColors[color], dstColors[color]);
1276 if (calculatedColor.w() <= 0.0f && calculatedColor != Vec4(0.0f))
1277 {
1278 // Skip ill-formed colors, because the spec says the result is undefined.
1279 skippedColors++;
1280 skipColor = true;
1281 break;
1282 }
1283 }
1284 if (skipColor)
1285 continue;
1286 }
1287
1288 deInt32 x = 0;
1289 deInt32 y = 0;
1290 getCoordinates(color, x, y);
1291
1292 // Set source color as push constant
1293 vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(Vec4), &srcColors[color]);
1294
1295 VkRect2D scissor = makeRect2D(x, y, 1u, 1u);
1296 vk.cmdSetScissor(*m_cmdBuffer, 0u, 1u, &scissor);
1297
1298 // To set destination color, we do clear attachment restricting the area to the respective pixel of each color attachment.
1299 {
1300 // Set destination color as push constant.
1301 std::vector<VkClearAttachment> attachments;
1302 VkClearValue clearValue = vk::makeClearValueColorVec4(dstColors[color]);
1303
1304 for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
1305 {
1306 VkClearAttachment attachment =
1307 {
1308 VK_IMAGE_ASPECT_COLOR_BIT,
1309 i,
1310 clearValue
1311 };
1312 attachments.emplace_back(attachment);
1313 }
1314
1315 const VkClearRect rect =
1316 {
1317 scissor,
1318 0u,
1319 1u
1320 };
1321 vk.cmdClearAttachments(*m_cmdBuffer, (deUint32)attachments.size(), attachments.data(), 1u, &rect);
1322 }
1323
1324 // Draw
1325 vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1u, 0u, 0u);
1326 }
1327
1328 // If we break this assert, then we are not testing anything in this test.
1329 DE_ASSERT(skippedColors < DE_LENGTH_OF_ARRAY(srcColors));
1330
1331 // Log number of skipped colors
1332 if (skippedColors != 0u)
1333 {
1334 tcu::TestLog& log = m_context.getTestContext().getLog();
1335 log << tcu::TestLog::Message << "Skipped " << skippedColors << " out of " << DE_LENGTH_OF_ARRAY(srcColors) << " color cases due to ill-formed colors" << tcu::TestLog::EndMessage;
1336 }
1337 endRenderPass(vk, *m_cmdBuffer);
1338 }
1339
prepareCommandBuffer() const1340 void BlendOperationAdvancedTestInstance::prepareCommandBuffer () const
1341 {
1342 const DeviceInterface& vk = m_context.getDeviceInterface();
1343
1344
1345 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1346
1347 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0,
1348 0u, DE_NULL, 0u, DE_NULL, (deUint32)m_imageLayoutBarriers.size(), m_imageLayoutBarriers.data());
1349
1350 prepareRenderPass(*m_framebuffer, *m_pipeline);
1351
1352 endCommandBuffer(vk, *m_cmdBuffer);
1353 }
1354
BlendOperationAdvancedTestInstance(Context & context,const BlendOperationAdvancedParam param)1355 BlendOperationAdvancedTestInstance::BlendOperationAdvancedTestInstance (Context& context,
1356 const BlendOperationAdvancedParam param)
1357 : TestInstance (context)
1358 , m_param (param)
1359 , m_renderSize (tcu::UVec2(widthArea, heightArea))
1360 , m_colorFormat (VK_FORMAT_R16G16B16A16_SFLOAT)
1361 , m_shaderStageCount (0)
1362 {
1363 const DeviceInterface& vk = m_context.getDeviceInterface();
1364 const VkDevice vkDevice = m_context.getDevice();
1365 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1366
1367 // Create vertex buffer and upload data
1368 {
1369 // Load vertices into vertex buffer
1370 m_vertices = createPoints();
1371 DE_ASSERT((deUint32)m_vertices.size() == 6);
1372
1373 m_vertexBuffer = createBufferAndBindMemory(m_context, m_vertices.size() * sizeof(Vec4), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &m_vertexBufferMemory);
1374 deMemcpy(m_vertexBufferMemory->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vec4));
1375 flushAlloc(vk, vkDevice, *m_vertexBufferMemory);
1376 }
1377
1378 // Create render pass
1379 m_renderPass = makeTestRenderPass(param, vk, vkDevice, m_colorFormat);
1380
1381 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
1382
1383 // Create color images
1384 for (deUint32 i = 0; i < param.colorAttachmentsCount; i++)
1385 {
1386 de::MovePtr<Allocation> colorImageAlloc;
1387 m_colorImageAllocs.emplace_back(colorImageAlloc);
1388
1389 Move<VkImage> colorImage = createImage2DAndBindMemory(m_context,
1390 m_colorFormat,
1391 m_renderSize.x(),
1392 m_renderSize.y(),
1393 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
1394 VK_SAMPLE_COUNT_1_BIT,
1395 &m_colorImageAllocs.back());
1396 m_colorImages.emplace_back(colorImage);
1397
1398 // Set up image layout transition barriers
1399 {
1400 VkImageMemoryBarrier colorImageBarrier =
1401 {
1402 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1403 DE_NULL, // const void* pNext;
1404 0u, // VkAccessFlags srcAccessMask;
1405 (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1406 VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT), // VkAccessFlags dstAccessMask;
1407 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1408 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1409 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1410 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1411 *m_colorImages.back(), // VkImage image;
1412 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
1413 };
1414
1415 m_imageLayoutBarriers.emplace_back(colorImageBarrier);
1416 }
1417
1418 // Create color attachment view
1419 {
1420 VkImageViewCreateInfo colorAttachmentViewParams =
1421 {
1422 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1423 DE_NULL, // const void* pNext;
1424 0u, // VkImageViewCreateFlags flags;
1425 *m_colorImages.back(), // VkImage image;
1426 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
1427 m_colorFormat, // VkFormat format;
1428 componentMappingRGBA, // VkComponentMapping components;
1429 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
1430 };
1431
1432 m_colorAttachmentViews.emplace_back(createImageView(vk, vkDevice, &colorAttachmentViewParams));
1433 }
1434 }
1435
1436 // Create framebuffer
1437 {
1438 std::vector<VkImageView> imageViews;
1439
1440 for (auto& movePtr : m_colorAttachmentViews)
1441 imageViews.push_back(movePtr.get());
1442
1443 const VkFramebufferCreateInfo framebufferParams =
1444 {
1445 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
1446 DE_NULL, // const void* pNext;
1447 0u, // VkFramebufferCreateFlags flags;
1448 *m_renderPass, // VkRenderPass renderPass;
1449 (deUint32)imageViews.size(), // deUint32 attachmentCount;
1450 imageViews.data(), // const VkImageView* pAttachments;
1451 (deUint32)m_renderSize.x(), // deUint32 width;
1452 (deUint32)m_renderSize.y(), // deUint32 height;
1453 1u, // deUint32 layers;
1454 };
1455
1456 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
1457 }
1458
1459 // Bind shader stages
1460 {
1461 bindShaderStage(VK_SHADER_STAGE_VERTEX_BIT, "vert", "main");
1462 bindShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, "frag", "main");
1463 }
1464
1465
1466 // Create pipeline layout
1467 {
1468 const VkPushConstantRange pushConstantRange =
1469 {
1470 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags
1471 0, // deUint32 offset
1472 sizeof(Vec4) // deUint32 size
1473 };
1474
1475 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1476 {
1477 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1478 DE_NULL, // const void* pNext;
1479 0u, // VkPipelineLayoutCreateFlags flags;
1480 0u, // deUint32 setLayoutCount;
1481 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
1482 1u, // deUint32 pushConstantRangeCount;
1483 &pushConstantRange // const VkPushConstantRange* pPushConstantRanges;
1484 };
1485
1486 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1487 }
1488
1489 // Create pipeline
1490 buildPipeline(m_param.premultipliedSrcColor, m_param.premultipliedDstColor);
1491
1492 // Create command pool
1493 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1494
1495 // Create command buffer
1496 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1497 }
1498
~BlendOperationAdvancedTestInstance(void)1499 BlendOperationAdvancedTestInstance::~BlendOperationAdvancedTestInstance (void)
1500 {
1501 }
1502
iterate(void)1503 tcu::TestStatus BlendOperationAdvancedTestInstance::iterate (void)
1504 {
1505 const DeviceInterface& vk = m_context.getDeviceInterface();
1506 const VkDevice vkDevice = m_context.getDevice();
1507 const VkQueue queue = m_context.getUniversalQueue();
1508 tcu::TestLog& log = m_context.getTestContext().getLog();
1509
1510 // Log the blend operations to test
1511 {
1512 if (m_param.independentBlend)
1513 {
1514 for (deUint32 i = 0; (i < m_param.colorAttachmentsCount); i++)
1515 log << tcu::TestLog::Message << "Color attachment " << i << " uses depth op: "<< de::toLower(getBlendOpStr(m_param.blendOps[i]).toString().substr(3)) << tcu::TestLog::EndMessage;
1516
1517 }
1518 else
1519 {
1520 log << tcu::TestLog::Message << "All color attachments use depth op: " << de::toLower(getBlendOpStr(m_param.blendOps[0]).toString().substr(3)) << tcu::TestLog::EndMessage;
1521
1522 }
1523 }
1524 prepareCommandBuffer();
1525 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1526
1527 if (verifyTestResult() == DE_FALSE)
1528 return tcu::TestStatus::fail("Image mismatch");
1529
1530 return tcu::TestStatus::pass("Result images matches references");
1531 }
1532
verifyTestResult()1533 deBool BlendOperationAdvancedTestInstance::verifyTestResult ()
1534 {
1535 deBool compareOk = DE_TRUE;
1536 const DeviceInterface& vk = m_context.getDeviceInterface();
1537 const VkDevice vkDevice = m_context.getDevice();
1538 const VkQueue queue = m_context.getUniversalQueue();
1539 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1540 Allocator& allocator = m_context.getDefaultAllocator();
1541 std::vector<tcu::TextureLevel> referenceImages;
1542
1543 for (deUint32 colorAtt = 0; colorAtt < m_param.colorAttachmentsCount; colorAtt++)
1544 {
1545 tcu::TextureLevel refImage (vk::mapVkFormat(m_colorFormat), 32, 32);
1546 tcu::clear(refImage.getAccess(), clearColorVec4);
1547 referenceImages.emplace_back(refImage);
1548 }
1549
1550 for (deUint32 color = 0; color < DE_LENGTH_OF_ARRAY(srcColors); color++)
1551 {
1552 deBool skipColor = DE_FALSE;
1553
1554 // Check if any color attachment will generate an ill-formed color. If that's the case, skip that color in the verification.
1555 for (deUint32 colorAtt = 0; colorAtt < m_param.colorAttachmentsCount; colorAtt++)
1556 {
1557 Vec4 rectColor = calculateFinalColor(m_param, m_param.blendOps[colorAtt], srcColors[color], dstColors[color]);
1558 if (m_param.premultipliedDstColor == VK_FALSE)
1559 {
1560 if (rectColor.w() > 0.0f)
1561 {
1562 rectColor.x() = rectColor.x() / rectColor.w();
1563 rectColor.y() = rectColor.y() / rectColor.w();
1564 rectColor.z() = rectColor.z() / rectColor.w();
1565 }
1566 else
1567 {
1568 // Skip the color check if it is ill-formed.
1569 if (rectColor != Vec4(0.0f))
1570 {
1571 skipColor = DE_TRUE;
1572 break;
1573 }
1574 }
1575 }
1576 }
1577
1578 // Skip ill-formed colors that appears in any color attachment.
1579 if (skipColor)
1580 continue;
1581
1582 // If we reach this point, the final color for all color attachment is not ill-formed.
1583 for (deUint32 colorAtt = 0; colorAtt < m_param.colorAttachmentsCount; colorAtt++)
1584 {
1585 Vec4 rectColor = calculateFinalColor(m_param, m_param.blendOps[colorAtt], srcColors[color], dstColors[color]);
1586 if (m_param.premultipliedDstColor == VK_FALSE)
1587 {
1588 if (rectColor.w() > 0.0f)
1589 {
1590 rectColor.x() = rectColor.x() / rectColor.w();
1591 rectColor.y() = rectColor.y() / rectColor.w();
1592 rectColor.z() = rectColor.z() / rectColor.w();
1593 }
1594 else
1595 {
1596 // Ill-formed colors were already skipped
1597 DE_ASSERT(rectColor == Vec4(0.0f));
1598 }
1599 }
1600 deInt32 x = 0;
1601 deInt32 y = 0;
1602 getCoordinates(color, x, y);
1603 tcu::clear(tcu::getSubregion(referenceImages[colorAtt].getAccess(), x, y, 1u, 1u), rectColor);
1604 }
1605 }
1606
1607 for (deUint32 colorAtt = 0; colorAtt < m_param.colorAttachmentsCount; colorAtt++)
1608 {
1609 // Compare image
1610 de::MovePtr<tcu::TextureLevel> result = vkt::pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImages[colorAtt], m_colorFormat, m_renderSize);
1611 std::ostringstream name;
1612 name << "Image comparison. Color attachment: " << colorAtt << ". Depth op: " << de::toLower(getBlendOpStr(m_param.blendOps[colorAtt]).toString().substr(3));
1613
1614 compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1615 "FloatImageCompare",
1616 name.str().c_str(),
1617 referenceImages[colorAtt].getAccess(),
1618 result->getAccess(),
1619 Vec4(0.01f, 0.01f, 0.01f, 0.01f),
1620 tcu::COMPARE_LOG_RESULT);
1621 if (!compareOk)
1622 return DE_FALSE;
1623 }
1624 return DE_TRUE;
1625 }
1626
1627 class BlendOperationAdvancedTest : public vkt::TestCase
1628 {
1629 public:
BlendOperationAdvancedTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const BlendOperationAdvancedParam param)1630 BlendOperationAdvancedTest (tcu::TestContext& testContext,
1631 const std::string& name,
1632 const std::string& description,
1633 const BlendOperationAdvancedParam param)
1634 : vkt::TestCase (testContext, name, description)
1635 , m_param (param)
1636 { }
~BlendOperationAdvancedTest(void)1637 virtual ~BlendOperationAdvancedTest (void) { }
1638 virtual void initPrograms (SourceCollections& programCollection) const;
1639 virtual TestInstance* createInstance (Context& context) const;
1640 virtual void checkSupport (Context& context) const;
1641
1642 protected:
1643 const BlendOperationAdvancedParam m_param;
1644 };
1645
checkSupport(Context & context) const1646 void BlendOperationAdvancedTest::checkSupport(Context& context) const
1647 {
1648 const InstanceInterface& vki = context.getInstanceInterface();
1649
1650 context.requireDeviceFunctionality("VK_EXT_blend_operation_advanced");
1651
1652 VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT blendProperties;
1653 blendProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT;
1654 blendProperties.pNext = DE_NULL;
1655
1656 VkPhysicalDeviceProperties2 properties2;
1657 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1658 properties2.pNext = &blendProperties;
1659 vki.getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties2);
1660
1661 if (!blendProperties.advancedBlendAllOperations)
1662 {
1663 for (deUint32 index = 0u; index < m_param.blendOps.size(); index++)
1664 {
1665 switch (m_param.blendOps[index])
1666 {
1667 case VK_BLEND_OP_MULTIPLY_EXT:
1668 case VK_BLEND_OP_SCREEN_EXT:
1669 case VK_BLEND_OP_OVERLAY_EXT:
1670 case VK_BLEND_OP_DARKEN_EXT:
1671 case VK_BLEND_OP_LIGHTEN_EXT:
1672 case VK_BLEND_OP_COLORDODGE_EXT:
1673 case VK_BLEND_OP_COLORBURN_EXT:
1674 case VK_BLEND_OP_HARDLIGHT_EXT:
1675 case VK_BLEND_OP_SOFTLIGHT_EXT:
1676 case VK_BLEND_OP_DIFFERENCE_EXT:
1677 case VK_BLEND_OP_EXCLUSION_EXT:
1678 case VK_BLEND_OP_HSL_HUE_EXT:
1679 case VK_BLEND_OP_HSL_SATURATION_EXT:
1680 case VK_BLEND_OP_HSL_COLOR_EXT:
1681 case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
1682 break;
1683 default:
1684 throw tcu::NotSupportedError("Unsupported all advanced blend operations and unsupported advanced blend operation");
1685 }
1686 }
1687 }
1688
1689 if (m_param.colorAttachmentsCount > blendProperties.advancedBlendMaxColorAttachments)
1690 {
1691 std::ostringstream error;
1692 error << "Unsupported number of color attachments (" << blendProperties.advancedBlendMaxColorAttachments << " < " << m_param.colorAttachmentsCount;
1693 throw tcu::NotSupportedError(error.str().c_str());
1694 }
1695
1696 if (m_param.overlap != VK_BLEND_OVERLAP_UNCORRELATED_EXT && !blendProperties.advancedBlendCorrelatedOverlap)
1697 {
1698 throw tcu::NotSupportedError("Unsupported blend correlated overlap");
1699 }
1700
1701 if (m_param.colorAttachmentsCount > 1 && m_param.independentBlend && !blendProperties.advancedBlendIndependentBlend)
1702 {
1703 throw tcu::NotSupportedError("Unsupported independent blend");
1704 }
1705
1706 if (!m_param.premultipliedSrcColor && !blendProperties.advancedBlendNonPremultipliedSrcColor)
1707 {
1708 throw tcu::NotSupportedError("Unsupported non-premultiplied source color");
1709 }
1710
1711 if (!m_param.premultipliedDstColor && !blendProperties.advancedBlendNonPremultipliedDstColor)
1712 {
1713 throw tcu::NotSupportedError("Unsupported non-premultiplied destination color");
1714 }
1715
1716 const VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT blendFeatures = context.getBlendOperationAdvancedFeaturesEXT();
1717 if (m_param.coherentOperations && !blendFeatures.advancedBlendCoherentOperations)
1718 {
1719 throw tcu::NotSupportedError("Unsupported required coherent operations");
1720 }
1721 }
1722
initPrograms(SourceCollections & programCollection) const1723 void BlendOperationAdvancedTest::initPrograms (SourceCollections& programCollection) const
1724 {
1725 programCollection.glslSources.add("vert") << glu::VertexSource(
1726 "#version 310 es\n"
1727 "layout(location = 0) in vec4 position;\n"
1728 "void main (void)\n"
1729 "{\n"
1730 " gl_Position = position;\n"
1731 "}\n");
1732
1733 std::ostringstream fragmentSource;
1734 fragmentSource << "#version 310 es\n";
1735 fragmentSource << "layout(push_constant) uniform Color { highp vec4 color; };\n";
1736 for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
1737 fragmentSource << "layout(location = "<< i <<") out highp vec4 fragColor" << i <<";\n";
1738 fragmentSource << "void main (void)\n";
1739 fragmentSource << "{\n";
1740 for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
1741 fragmentSource << " fragColor" << i <<" = color;\n";
1742 fragmentSource << "}\n";
1743 programCollection.glslSources.add("frag") << glu::FragmentSource(fragmentSource.str().c_str());
1744 }
1745
1746 class BlendOperationAdvancedTestCoherentInstance : public vkt::TestInstance
1747 {
1748 public:
1749 BlendOperationAdvancedTestCoherentInstance (Context& context,
1750 const BlendOperationAdvancedParam param);
1751 virtual ~BlendOperationAdvancedTestCoherentInstance (void);
1752 virtual tcu::TestStatus iterate (void);
1753 protected:
1754 void prepareRenderPass (VkFramebuffer framebuffer, VkPipeline pipeline,
1755 VkRenderPass renderpass, deBool secondDraw);
1756 virtual void prepareCommandBuffer (void);
1757 virtual void buildPipeline (void);
1758 virtual void bindShaderStage (VkShaderStageFlagBits stage,
1759 const char* sourceName,
1760 const char* entryName);
1761 virtual tcu::TestStatus verifyTestResult (void);
1762
1763 protected:
1764 const BlendOperationAdvancedParam m_param;
1765 const tcu::UVec2 m_renderSize;
1766 const VkFormat m_colorFormat;
1767 Move<VkPipelineLayout> m_pipelineLayout;
1768
1769 Move<VkBuffer> m_vertexBuffer;
1770 de::MovePtr<Allocation> m_vertexBufferMemory;
1771 std::vector<Vec4> m_vertices;
1772
1773 std::vector<Move<VkRenderPass>> m_renderPasses;
1774 Move<VkCommandPool> m_cmdPool;
1775 Move<VkCommandBuffer> m_cmdBuffer;
1776 Move<VkImage> m_colorImage;
1777 Move<VkImageView> m_colorAttachmentView;
1778 de::MovePtr<Allocation> m_colorImageAlloc;
1779 std::vector<VkImageMemoryBarrier> m_imageLayoutBarriers;
1780 std::vector<Move<VkFramebuffer>> m_framebuffers;
1781 std::vector<Move<VkPipeline>> m_pipelines;
1782
1783 Move<VkShaderModule> m_shaderModules[2];
1784 deUint32 m_shaderStageCount;
1785 VkPipelineShaderStageCreateInfo m_shaderStageInfo[2];
1786 };
1787
~BlendOperationAdvancedTestCoherentInstance(void)1788 BlendOperationAdvancedTestCoherentInstance::~BlendOperationAdvancedTestCoherentInstance (void)
1789 {
1790 }
1791
bindShaderStage(VkShaderStageFlagBits stage,const char * sourceName,const char * entryName)1792 void BlendOperationAdvancedTestCoherentInstance::bindShaderStage (VkShaderStageFlagBits stage,
1793 const char* sourceName,
1794 const char* entryName)
1795 {
1796 const DeviceInterface& vk = m_context.getDeviceInterface();
1797 const VkDevice vkDevice = m_context.getDevice();
1798
1799 // Create shader module
1800 deUint32* code = (deUint32*)m_context.getBinaryCollection().get(sourceName).getBinary();
1801 deUint32 codeSize = (deUint32)m_context.getBinaryCollection().get(sourceName).getSize();
1802
1803 const VkShaderModuleCreateInfo moduleCreateInfo =
1804 {
1805 VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType;
1806 DE_NULL, // const void* pNext;
1807 0u, // VkShaderModuleCreateFlags flags;
1808 codeSize, // deUintptr codeSize;
1809 code, // const deUint32* pCode;
1810 };
1811
1812 m_shaderModules[m_shaderStageCount] = createShaderModule(vk, vkDevice, &moduleCreateInfo);
1813
1814 // Prepare shader stage info
1815 m_shaderStageInfo[m_shaderStageCount].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1816 m_shaderStageInfo[m_shaderStageCount].pNext = DE_NULL;
1817 m_shaderStageInfo[m_shaderStageCount].flags = 0u;
1818 m_shaderStageInfo[m_shaderStageCount].stage = stage;
1819 m_shaderStageInfo[m_shaderStageCount].module = *m_shaderModules[m_shaderStageCount];
1820 m_shaderStageInfo[m_shaderStageCount].pName = entryName;
1821 m_shaderStageInfo[m_shaderStageCount].pSpecializationInfo = DE_NULL;
1822
1823 m_shaderStageCount++;
1824 }
1825
buildPipeline()1826 void BlendOperationAdvancedTestCoherentInstance::buildPipeline ()
1827 {
1828 const DeviceInterface& vk = m_context.getDeviceInterface();
1829 const VkDevice vkDevice = m_context.getDevice();
1830
1831 // Create pipeline
1832 const VkVertexInputBindingDescription vertexInputBindingDescription =
1833 {
1834 0u, // deUint32 binding;
1835 sizeof(Vec4) , // deUint32 strideInBytes;
1836 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
1837 };
1838
1839 const VkVertexInputAttributeDescription vertexInputAttributeDescription =
1840 {
1841 0u, // deUint32 location;
1842 0u, // deUint32 binding;
1843 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1844 0u // deUint32 offsetInBytes;
1845 };
1846
1847 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1848 {
1849 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1850 DE_NULL, // const void* pNext;
1851 0u, // VkPipelineVertexInputStateCreateFlags flags;
1852 1u, // deUint32 vertexBindingDescriptionCount;
1853 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1854 1u, // deUint32 vertexAttributeDescriptionCount;
1855 &vertexInputAttributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1856 };
1857
1858 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
1859 {
1860 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
1861 DE_NULL, // const void* pNext;
1862 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
1863 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
1864 VK_FALSE, // VkBool32 primitiveRestartEnable;
1865 };
1866
1867 const VkRect2D scissor = makeRect2D(m_renderSize);
1868 VkViewport viewport = makeViewport(m_renderSize);
1869
1870 const VkPipelineViewportStateCreateInfo viewportStateParams =
1871 {
1872 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
1873 DE_NULL, // const void* pNext;
1874 0u, // VkPipelineViewportStateCreateFlags flags;
1875 1u, // deUint32 viewportCount;
1876 &viewport, // const VkViewport* pViewports;
1877 1u, // deUint32 scissorCount;
1878 &scissor // const VkRect2D* pScissors;
1879 };
1880
1881 const VkPipelineRasterizationStateCreateInfo rasterStateParams =
1882 {
1883 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
1884 DE_NULL, // const void* pNext;
1885 0u, // VkPipelineRasterizationStateCreateFlags flags;
1886 VK_FALSE, // VkBool32 depthClampEnable;
1887 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
1888 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
1889 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
1890 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
1891 VK_FALSE, // VkBool32 depthBiasEnable;
1892 0.0f, // float depthBiasConstantFactor;
1893 0.0f, // float depthBiasClamp;
1894 0.0f, // float depthBiasSlopeFactor;
1895 1.0f, // float lineWidth;
1896 };
1897
1898 const VkPipelineColorBlendAdvancedStateCreateInfoEXT blendAdvancedStateParams =
1899 {
1900 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT, // VkStructureType sType;
1901 DE_NULL, // const void* pNext;
1902 VK_TRUE, // VkBool32 srcPremultiplied;
1903 VK_TRUE, // VkBool32 dstPremultiplied;
1904 m_param.overlap, // VkBlendOverlapEXT blendOverlap;
1905 };
1906
1907 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates;
1908
1909 // One VkPipelineColorBlendAttachmentState for each pipeline, we only have one color attachment.
1910 for (deUint32 i = 0; i < 2; i++)
1911 {
1912 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1913 {
1914 VK_TRUE, // VkBool32 blendEnable;
1915 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
1916 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstColorBlendFactor;
1917 m_param.blendOps[i], // VkBlendOp colorBlendOp;
1918 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
1919 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor;
1920 m_param.blendOps[i], // VkBlendOp alphaBlendOp;
1921 VK_COLOR_COMPONENT_R_BIT |
1922 VK_COLOR_COMPONENT_G_BIT |
1923 VK_COLOR_COMPONENT_B_BIT |
1924 VK_COLOR_COMPONENT_A_BIT // VkColorComponentFlags colorWriteMask;
1925 };
1926 colorBlendAttachmentStates.emplace_back(colorBlendAttachmentState);
1927 }
1928
1929 std::vector<VkPipelineColorBlendStateCreateInfo> colorBlendStateParams;
1930 VkPipelineColorBlendStateCreateInfo colorBlendStateParam =
1931 {
1932 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1933 &blendAdvancedStateParams, // const void* pNext;
1934 0u, // VkPipelineColorBlendStateCreateFlags flags;
1935 VK_FALSE, // VkBool32 logicOpEnable;
1936 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
1937 1u, // deUint32 attachmentCount;
1938 &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState* pAttachments;
1939 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4];
1940 };
1941 colorBlendStateParams.emplace_back(colorBlendStateParam);
1942
1943 // For the second pipeline, the blendOp changed.
1944 colorBlendStateParam.pAttachments = &colorBlendAttachmentStates[1];
1945 colorBlendStateParams.emplace_back(colorBlendStateParam);
1946
1947 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1948 {
1949 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1950 DE_NULL, // const void* pNext;
1951 0u, // VkPipelineMultisampleStateCreateFlags flags;
1952 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
1953 VK_FALSE, // VkBool32 sampleShadingEnable;
1954 0.0f, // float minSampleShading;
1955 DE_NULL, // const VkSampleMask* pSampleMask;
1956 VK_FALSE, // VkBool32 alphaToCoverageEnable;
1957 VK_FALSE, // VkBool32 alphaToOneEnable;
1958 };
1959
1960 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
1961 {
1962 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
1963 DE_NULL, // const void* pNext;
1964 0u, // VkPipelineDepthStencilStateCreateFlags flags;
1965 VK_FALSE, // VkBool32 depthTestEnable;
1966 VK_FALSE, // VkBool32 depthWriteEnable;
1967 VK_COMPARE_OP_NEVER, // VkCompareOp depthCompareOp;
1968 VK_FALSE, // VkBool32 depthBoundsTestEnable;
1969 VK_FALSE, // VkBool32 stencilTestEnable;
1970 // VkStencilOpState front;
1971 {
1972 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
1973 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
1974 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
1975 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
1976 0u, // deUint32 compareMask;
1977 0u, // deUint32 writeMask;
1978 0u, // deUint32 reference;
1979 },
1980 // VkStencilOpState back;
1981 {
1982 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
1983 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
1984 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
1985 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
1986 0u, // deUint32 compareMask;
1987 0u, // deUint32 writeMask;
1988 0u, // deUint32 reference;
1989 },
1990 0.0f, // float minDepthBounds;
1991 1.0f, // float maxDepthBounds;
1992 };
1993
1994 const VkDynamicState dynamicState = VK_DYNAMIC_STATE_SCISSOR;
1995 const VkPipelineDynamicStateCreateInfo dynamicStateParams =
1996 {
1997 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
1998 DE_NULL, // const void* pNext;
1999 0u, // VkPipelineDynamicStateCreateFlags flags;
2000 1u, // uint32_t dynamicStateCount;
2001 &dynamicState // const VkDynamicState* pDynamicStates;
2002 };
2003
2004 VkGraphicsPipelineCreateInfo graphicsPipelineParams =
2005 {
2006 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
2007 DE_NULL, // const void* pNext;
2008 0u, // VkPipelineCreateFlags flags;
2009 m_shaderStageCount, // deUint32 stageCount;
2010 m_shaderStageInfo, // const VkPipelineShaderStageCreateInfo* pStages;
2011 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
2012 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
2013 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
2014 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
2015 &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterState;
2016 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
2017 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
2018 &colorBlendStateParams[0], // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
2019 &dynamicStateParams, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
2020 *m_pipelineLayout, // VkPipelineLayout layout;
2021 m_renderPasses[0].get(), // VkRenderPass renderPass;
2022 0u, // deUint32 subpass;
2023 DE_NULL, // VkPipeline basePipelineHandle;
2024 0u, // deInt32 basePipelineIndex;
2025 };
2026
2027 // Create first pipeline
2028 m_pipelines.emplace_back(createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams));
2029 // Create second pipeline
2030 graphicsPipelineParams.pColorBlendState = &colorBlendStateParams[1];
2031 graphicsPipelineParams.renderPass = m_renderPasses[1].get();
2032 m_pipelines.emplace_back(createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams));
2033 }
2034
prepareRenderPass(VkFramebuffer framebuffer,VkPipeline pipeline,VkRenderPass renderpass,deBool secondDraw)2035 void BlendOperationAdvancedTestCoherentInstance::prepareRenderPass (VkFramebuffer framebuffer, VkPipeline pipeline, VkRenderPass renderpass, deBool secondDraw)
2036 {
2037 const DeviceInterface& vk = m_context.getDeviceInterface();
2038
2039 VkClearValue attachmentClearValue = makeClearValueColor(clearColorVec4);
2040
2041 beginRenderPass(vk, *m_cmdBuffer, renderpass, framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
2042 (secondDraw ? 0u : 1u),
2043 (secondDraw ? DE_NULL : &attachmentClearValue));
2044
2045 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
2046 VkDeviceSize offsets = 0u;
2047 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets);
2048
2049 // There are two different renderpasses, each of them draw
2050 // one half of the colors.
2051 deBool skippedColors = 0u;
2052 for (deUint32 color = 0; color < DE_LENGTH_OF_ARRAY(srcColors)/2; color++)
2053 {
2054 // Skip ill-formed colors when we have non-premultiplied destination colors.
2055 if (m_param.premultipliedDstColor == VK_FALSE)
2056 {
2057 deBool skipColor = false;
2058 for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
2059 {
2060 Vec4 calculatedColor = calculateFinalColor(m_param, m_param.blendOps[i], srcColors[color], dstColors[color]);
2061 if (calculatedColor.w() <= 0.0f && calculatedColor != Vec4(0.0f))
2062 {
2063 // Skip ill-formed colors, because the spec says the result is undefined.
2064 skippedColors++;
2065 skipColor = true;
2066 break;
2067 }
2068 }
2069 if (skipColor)
2070 continue;
2071 }
2072 deInt32 x = 0;
2073 deInt32 y = 0;
2074 getCoordinates(color, x, y);
2075
2076 deUint32 index = secondDraw ? (color + DE_LENGTH_OF_ARRAY(srcColors) / 2) : color;
2077
2078 // Set source color as push constant
2079 vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(Vec4), &srcColors[index]);
2080 VkRect2D scissor = makeRect2D(x, y, 1u, 1u);
2081 vk.cmdSetScissor(*m_cmdBuffer, 0u, 1u, &scissor);
2082
2083 // To set destination color, we do clear attachment restricting the area to the respective pixel of each color attachment.
2084 // Only clear in the first draw, for the second draw the destination color is the result of the first draw's blend.
2085 if (secondDraw == DE_FALSE)
2086 {
2087 std::vector<VkClearAttachment> attachments;
2088 VkClearValue clearValue = vk::makeClearValueColorVec4(dstColors[index]);
2089
2090 const VkClearAttachment attachment =
2091 {
2092 VK_IMAGE_ASPECT_COLOR_BIT,
2093 0u,
2094 clearValue
2095 };
2096
2097 const VkClearRect rect =
2098 {
2099 scissor,
2100 0u,
2101 1u
2102 };
2103 vk.cmdClearAttachments(*m_cmdBuffer, 1u, &attachment, 1u, &rect);
2104 }
2105
2106 // Draw
2107 vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1u, 0u, 0u);
2108 }
2109
2110 // If we break this assert, then we are not testing anything in this test.
2111 DE_ASSERT(skippedColors < (DE_LENGTH_OF_ARRAY(srcColors) / 2));
2112
2113 // Log number of skipped colors
2114 if (skippedColors != 0u)
2115 {
2116 tcu::TestLog& log = m_context.getTestContext().getLog();
2117 log << tcu::TestLog::Message << "Skipped " << skippedColors << " out of " << (DE_LENGTH_OF_ARRAY(srcColors) / 2) << " color cases due to ill-formed colors" << tcu::TestLog::EndMessage;
2118 }
2119 endRenderPass(vk, *m_cmdBuffer);
2120 }
2121
prepareCommandBuffer()2122 void BlendOperationAdvancedTestCoherentInstance::prepareCommandBuffer ()
2123 {
2124 const DeviceInterface& vk = m_context.getDeviceInterface();
2125
2126 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2127
2128 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0,
2129 0u, DE_NULL, 0u, DE_NULL, (deUint32)m_imageLayoutBarriers.size(), m_imageLayoutBarriers.data());
2130
2131 prepareRenderPass(m_framebuffers[0].get(), m_pipelines[0].get(), m_renderPasses[0].get(), false);
2132
2133 if (m_param.coherentOperations == DE_FALSE)
2134 {
2135 const VkImageMemoryBarrier colorImageBarrier =
2136 {
2137 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
2138 DE_NULL, // const void* pNext;
2139 (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2140 VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT), // VkAccessFlags srcAccessMask;
2141 (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2142 VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT), // VkAccessFlags dstAccessMask;
2143 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
2144 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
2145 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
2146 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
2147 *m_colorImage, // VkImage image;
2148 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
2149 };
2150 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
2151 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0,
2152 0u, DE_NULL, 0u, DE_NULL, 1u, &colorImageBarrier);
2153 }
2154
2155 prepareRenderPass(m_framebuffers[1].get(), m_pipelines[1].get(), m_renderPasses[1].get(), true);
2156
2157 endCommandBuffer(vk, *m_cmdBuffer);
2158 }
2159
BlendOperationAdvancedTestCoherentInstance(Context & context,const BlendOperationAdvancedParam param)2160 BlendOperationAdvancedTestCoherentInstance::BlendOperationAdvancedTestCoherentInstance (Context& context,
2161 const BlendOperationAdvancedParam param)
2162 : TestInstance (context)
2163 , m_param (param)
2164 , m_renderSize (tcu::UVec2(widthArea, heightArea))
2165 , m_colorFormat (VK_FORMAT_R16G16B16A16_SFLOAT)
2166 , m_shaderStageCount (0)
2167 {
2168 const DeviceInterface& vk = m_context.getDeviceInterface();
2169 const VkDevice vkDevice = m_context.getDevice();
2170 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2171
2172 // Create vertex buffer
2173 {
2174 m_vertices = createPoints();
2175 DE_ASSERT((deUint32)m_vertices.size() == 6);
2176
2177 m_vertexBuffer = createBufferAndBindMemory(m_context, m_vertices.size() * sizeof(Vec4), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &m_vertexBufferMemory);
2178 // Load vertices into vertex buffer
2179 deMemcpy(m_vertexBufferMemory->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vec4));
2180 flushAlloc(vk, vkDevice, *m_vertexBufferMemory);
2181 }
2182
2183 // Create render passes
2184 m_renderPasses.emplace_back(makeTestRenderPass(param, vk, vkDevice, m_colorFormat, VK_ATTACHMENT_LOAD_OP_CLEAR));
2185 m_renderPasses.emplace_back(makeTestRenderPass(param, vk, vkDevice, m_colorFormat, VK_ATTACHMENT_LOAD_OP_LOAD));
2186
2187 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
2188
2189 // Create color image
2190 m_colorImage = createImage2DAndBindMemory(m_context,
2191 m_colorFormat,
2192 m_renderSize.x(),
2193 m_renderSize.y(),
2194 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
2195 VK_SAMPLE_COUNT_1_BIT,
2196 &m_colorImageAlloc);
2197 // Set up image layout transition barriers
2198 {
2199 VkImageMemoryBarrier colorImageBarrier =
2200 {
2201 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
2202 DE_NULL, // const void* pNext;
2203 0u, // VkAccessFlags srcAccessMask;
2204 (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2205 VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT), // VkAccessFlags dstAccessMask;
2206 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
2207 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
2208 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
2209 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
2210 *m_colorImage, // VkImage image;
2211 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
2212 };
2213
2214 m_imageLayoutBarriers.emplace_back(colorImageBarrier);
2215 }
2216
2217 // Create color attachment view
2218 {
2219 VkImageViewCreateInfo colorAttachmentViewParams =
2220 {
2221 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
2222 DE_NULL, // const void* pNext;
2223 0u, // VkImageViewCreateFlags flags;
2224 *m_colorImage, // VkImage image;
2225 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
2226 m_colorFormat, // VkFormat format;
2227 componentMappingRGBA, // VkComponentMapping components;
2228 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
2229 };
2230
2231 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
2232 }
2233
2234 // Create framebuffers
2235 {
2236 VkFramebufferCreateInfo framebufferParams =
2237 {
2238 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
2239 DE_NULL, // const void* pNext;
2240 0u, // VkFramebufferCreateFlags flags;
2241 m_renderPasses[0].get(), // VkRenderPass renderPass;
2242 1u, // deUint32 attachmentCount;
2243 &m_colorAttachmentView.get(), // const VkImageView* pAttachments;
2244 (deUint32)m_renderSize.x(), // deUint32 width;
2245 (deUint32)m_renderSize.y(), // deUint32 height;
2246 1u, // deUint32 layers;
2247 };
2248
2249 m_framebuffers.emplace_back(createFramebuffer(vk, vkDevice, &framebufferParams));
2250 framebufferParams.renderPass = m_renderPasses[1].get();
2251 m_framebuffers.emplace_back(createFramebuffer(vk, vkDevice, &framebufferParams));
2252 }
2253
2254 // Bind shader stages
2255 {
2256 bindShaderStage(VK_SHADER_STAGE_VERTEX_BIT, "vert", "main");
2257 bindShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, "frag", "main");
2258 }
2259
2260
2261 // Create pipeline layout
2262 {
2263 const VkPushConstantRange pushConstantRange =
2264 {
2265 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags
2266 0, // deUint32 offset
2267 sizeof(Vec4) // deUint32 size
2268 };
2269
2270 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
2271 {
2272 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
2273 DE_NULL, // const void* pNext;
2274 0u, // VkPipelineLayoutCreateFlags flags;
2275 0u, // deUint32 setLayoutCount;
2276 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
2277 1u, // deUint32 pushConstantRangeCount;
2278 &pushConstantRange // const VkPushConstantRange* pPushConstantRanges;
2279 };
2280
2281 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
2282 }
2283
2284 // Create pipeline
2285 buildPipeline();
2286
2287 // Create command pool
2288 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
2289
2290 // Create command buffer
2291 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2292 }
2293
iterate(void)2294 tcu::TestStatus BlendOperationAdvancedTestCoherentInstance::iterate (void)
2295 {
2296 const DeviceInterface& vk = m_context.getDeviceInterface();
2297 const VkDevice vkDevice = m_context.getDevice();
2298 const VkQueue queue = m_context.getUniversalQueue();
2299 tcu::TestLog& log = m_context.getTestContext().getLog();
2300
2301 // Log the blend operations to test
2302 {
2303 DE_ASSERT(m_param.blendOps.size() == 2u);
2304 log << tcu::TestLog::Message << "First depth op: " << de::toLower(getBlendOpStr(m_param.blendOps[0]).toString().substr(3)) << tcu::TestLog::EndMessage;
2305 log << tcu::TestLog::Message << "Second depth op: " << de::toLower(getBlendOpStr(m_param.blendOps[1]).toString().substr(3)) << tcu::TestLog::EndMessage;
2306
2307 }
2308
2309 prepareCommandBuffer();
2310
2311 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
2312 return verifyTestResult();
2313 }
2314
verifyTestResult(void)2315 tcu::TestStatus BlendOperationAdvancedTestCoherentInstance::verifyTestResult (void)
2316 {
2317 deBool compareOk = DE_TRUE;
2318 const DeviceInterface& vk = m_context.getDeviceInterface();
2319 const VkDevice vkDevice = m_context.getDevice();
2320 const VkQueue queue = m_context.getUniversalQueue();
2321 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2322 Allocator& allocator = m_context.getDefaultAllocator();
2323 tcu::TextureLevel refImage (vk::mapVkFormat(m_colorFormat), 32, 32);
2324
2325 tcu::clear(refImage.getAccess(), clearColorVec4);
2326
2327 // Generate reference image
2328 for (deUint32 color = 0; color < DE_LENGTH_OF_ARRAY(srcColors)/2; color++)
2329 {
2330 deUint32 secondDrawColorIndex = color + DE_LENGTH_OF_ARRAY(srcColors)/2;
2331 // Calculate first draw final color
2332 Vec4 rectColorTmp = calculateFinalColor(m_param, m_param.blendOps[0], srcColors[color], dstColors[color]);
2333
2334 if (m_param.premultipliedDstColor == VK_FALSE)
2335 {
2336 if (rectColorTmp.w() > 0.0f)
2337 {
2338 rectColorTmp.x() = rectColorTmp.x() / rectColorTmp.w();
2339 rectColorTmp.y() = rectColorTmp.y() / rectColorTmp.w();
2340 rectColorTmp.z() = rectColorTmp.z() / rectColorTmp.w();
2341 }
2342 else
2343 {
2344 // Skip the color check if it is ill-formed.
2345 if (rectColorTmp != Vec4(0.0f))
2346 continue;
2347 }
2348 }
2349 // Calculate second draw final color
2350 Vec4 rectColor = calculateFinalColor(m_param, m_param.blendOps[1], srcColors[secondDrawColorIndex], rectColorTmp);
2351 if (m_param.premultipliedDstColor == VK_FALSE)
2352 {
2353 if (rectColor.w() > 0.0f)
2354 {
2355 rectColor.x() = rectColor.x() / rectColor.w();
2356 rectColor.y() = rectColor.y() / rectColor.w();
2357 rectColor.z() = rectColor.z() / rectColor.w();
2358 }
2359 else
2360 {
2361 // Skip the color check if it is ill-formed.
2362 if (rectColor != Vec4(0.0f))
2363 continue;
2364 }
2365 }
2366
2367 deInt32 x = 0;
2368 deInt32 y = 0;
2369 getCoordinates(color, x, y);
2370 tcu::clear(tcu::getSubregion(refImage.getAccess(), x, y, 1u, 1u), rectColor);
2371 }
2372
2373 de::MovePtr<tcu::TextureLevel> result = vkt::pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
2374 std::ostringstream name;
2375 name << "Image comparison. Depth ops: " << de::toLower(getBlendOpStr(m_param.blendOps[0]).toString().substr(3)) << " and " << de::toLower(getBlendOpStr(m_param.blendOps[1]).toString().substr(3));
2376 compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
2377 "FloatImageCompare",
2378 name.str().c_str(),
2379 refImage.getAccess(),
2380 result->getAccess(),
2381 Vec4(0.01f, 0.01f, 0.01f, 0.01f),
2382 tcu::COMPARE_LOG_RESULT);
2383 if (!compareOk)
2384 return tcu::TestStatus::fail("Image mismatch");
2385
2386 return tcu::TestStatus::pass("Result images matches references");
2387 }
2388
createInstance(Context & context) const2389 TestInstance* BlendOperationAdvancedTest::createInstance (Context& context) const
2390 {
2391 if (m_param.testMode == TEST_MODE_GENERIC)
2392 return new BlendOperationAdvancedTestInstance(context, m_param);
2393 else
2394 return new BlendOperationAdvancedTestCoherentInstance(context, m_param);
2395 }
2396
2397 } // anonymous
2398
createBlendOperationAdvancedTests(tcu::TestContext & testCtx)2399 tcu::TestCaseGroup* createBlendOperationAdvancedTests (tcu::TestContext& testCtx)
2400 {
2401 enum nonpremultiplyEnum
2402 {
2403 PREMULTIPLY_SRC = 1u,
2404 PREMULTIPLY_DST = 2u
2405 };
2406 deUint32 premultiplyModes[] = { 0u, PREMULTIPLY_SRC, PREMULTIPLY_DST, PREMULTIPLY_SRC | PREMULTIPLY_DST };
2407 deUint32 colorAttachmentCounts[] = { 1u, 2u, 4u, 8u, 16u };
2408 deBool coherentOps[] = { DE_FALSE, DE_TRUE };
2409 VkBlendOp blendOps[] =
2410 {
2411 VK_BLEND_OP_ZERO_EXT, VK_BLEND_OP_SRC_EXT, VK_BLEND_OP_DST_EXT, VK_BLEND_OP_SRC_OVER_EXT, VK_BLEND_OP_DST_OVER_EXT,
2412 VK_BLEND_OP_SRC_IN_EXT, VK_BLEND_OP_DST_IN_EXT, VK_BLEND_OP_SRC_OUT_EXT, VK_BLEND_OP_DST_OUT_EXT, VK_BLEND_OP_SRC_ATOP_EXT,
2413 VK_BLEND_OP_DST_ATOP_EXT, VK_BLEND_OP_XOR_EXT, VK_BLEND_OP_MULTIPLY_EXT, VK_BLEND_OP_SCREEN_EXT, VK_BLEND_OP_OVERLAY_EXT,
2414 VK_BLEND_OP_DARKEN_EXT, VK_BLEND_OP_LIGHTEN_EXT, VK_BLEND_OP_COLORDODGE_EXT, VK_BLEND_OP_COLORBURN_EXT, VK_BLEND_OP_HARDLIGHT_EXT,
2415 VK_BLEND_OP_SOFTLIGHT_EXT, VK_BLEND_OP_DIFFERENCE_EXT, VK_BLEND_OP_EXCLUSION_EXT, VK_BLEND_OP_INVERT_EXT, VK_BLEND_OP_INVERT_RGB_EXT,
2416 VK_BLEND_OP_LINEARDODGE_EXT, VK_BLEND_OP_LINEARBURN_EXT, VK_BLEND_OP_VIVIDLIGHT_EXT, VK_BLEND_OP_LINEARLIGHT_EXT, VK_BLEND_OP_PINLIGHT_EXT,
2417 VK_BLEND_OP_HARDMIX_EXT, VK_BLEND_OP_HSL_HUE_EXT, VK_BLEND_OP_HSL_SATURATION_EXT, VK_BLEND_OP_HSL_COLOR_EXT, VK_BLEND_OP_HSL_LUMINOSITY_EXT,
2418 VK_BLEND_OP_PLUS_EXT, VK_BLEND_OP_PLUS_CLAMPED_EXT, VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT, VK_BLEND_OP_PLUS_DARKER_EXT, VK_BLEND_OP_MINUS_EXT,
2419 VK_BLEND_OP_MINUS_CLAMPED_EXT, VK_BLEND_OP_CONTRAST_EXT, VK_BLEND_OP_INVERT_OVG_EXT, VK_BLEND_OP_RED_EXT, VK_BLEND_OP_GREEN_EXT, VK_BLEND_OP_BLUE_EXT,
2420 };
2421
2422 de::MovePtr<tcu::TestCaseGroup> tests (new tcu::TestCaseGroup(testCtx, "blend_operation_advanced", "VK_EXT_blend_operation_advanced tests"));
2423 de::Random rnd (deStringHash(tests->getName()));
2424
2425 de::MovePtr<tcu::TestCaseGroup> opsTests (new tcu::TestCaseGroup(testCtx, "ops", "Test each blend operation advance op"));
2426
2427
2428 for (deUint32 colorAttachmentCount = 0u; colorAttachmentCount < DE_LENGTH_OF_ARRAY(colorAttachmentCounts); colorAttachmentCount++)
2429 {
2430 for (deUint32 overlap = 0; overlap <= VK_BLEND_OVERLAP_CONJOINT_EXT; overlap++)
2431 {
2432 for (deUint32 premultiply = 0u; premultiply < DE_LENGTH_OF_ARRAY(premultiplyModes); premultiply++)
2433 {
2434 deUint32 testNumber = 0u;
2435 for (deUint64 blendOp = 0u; blendOp < DE_LENGTH_OF_ARRAY(blendOps); blendOp++)
2436 {
2437 deBool isAdditionalRGBBlendOp = blendOps[blendOp] >= VK_BLEND_OP_PLUS_EXT && blendOps[blendOp] < VK_BLEND_OP_MAX_ENUM;
2438
2439 // Additional RGB Blend operations are not affected by the blend overlap modes
2440 if (isAdditionalRGBBlendOp && overlap != VK_BLEND_OVERLAP_UNCORRELATED_EXT)
2441 continue;
2442
2443 BlendOperationAdvancedParam testParams;
2444 testParams.testMode = TEST_MODE_GENERIC;
2445 testParams.overlap = (VkBlendOverlapEXT) overlap;
2446 testParams.coherentOperations = DE_FALSE;
2447 testParams.colorAttachmentsCount = colorAttachmentCounts[colorAttachmentCount];
2448 testParams.independentBlend = DE_FALSE;
2449 testParams.premultipliedSrcColor = (premultiplyModes[premultiply] & PREMULTIPLY_SRC) ? VK_TRUE : VK_FALSE;
2450 testParams.premultipliedDstColor = (premultiplyModes[premultiply] & PREMULTIPLY_DST) ? VK_TRUE : VK_FALSE;
2451 testParams.testNumber = testNumber++;
2452
2453 for (deUint32 numColorAtt = 0; numColorAtt < colorAttachmentCounts[colorAttachmentCount]; numColorAtt++)
2454 testParams.blendOps.push_back(blendOps[blendOp]);
2455 opsTests->addChild(newTestCase<BlendOperationAdvancedTest>(testCtx, testParams));
2456 }
2457 }
2458 }
2459 }
2460 tests->addChild(opsTests.release());
2461
2462 // Independent Blend Tests: test more than one color attachment.
2463 de::MovePtr<tcu::TestCaseGroup> independentTests (new tcu::TestCaseGroup(testCtx, "independent", "Test independent blend feature"));
2464 deUint32 testNumber = 0u;
2465
2466 for (deUint32 colorAttachmentCount = 1u; colorAttachmentCount < DE_LENGTH_OF_ARRAY(colorAttachmentCounts); colorAttachmentCount++)
2467 {
2468 BlendOperationAdvancedParam testParams;
2469 testParams.testMode = TEST_MODE_GENERIC;
2470 testParams.overlap = VK_BLEND_OVERLAP_UNCORRELATED_EXT;
2471 testParams.coherentOperations = DE_FALSE;
2472 testParams.colorAttachmentsCount = colorAttachmentCounts[colorAttachmentCount];
2473 testParams.independentBlend = DE_TRUE;
2474 testParams.premultipliedSrcColor = VK_TRUE;
2475 testParams.premultipliedDstColor = VK_TRUE;
2476 testParams.testNumber = testNumber++;
2477
2478 for (deUint32 numColorAtt = 0; numColorAtt < colorAttachmentCounts[colorAttachmentCount]; numColorAtt++)
2479 {
2480 deUint32 i = de::randomScalar<deUint32>(rnd, 0, DE_LENGTH_OF_ARRAY(blendOps) - 1);
2481 testParams.blendOps.push_back(blendOps[i]);
2482 }
2483 independentTests->addChild(newTestCase<BlendOperationAdvancedTest>(testCtx, testParams));
2484 }
2485
2486 tests->addChild(independentTests.release());
2487
2488 // Coherent tests, do two consecutive advanced blending operations on the same color attachment.
2489 de::MovePtr<tcu::TestCaseGroup> coherentTests (new tcu::TestCaseGroup(testCtx, "coherent", "Test coherent memory"));
2490 testNumber = 0u;
2491
2492 for (deUint32 coherent = 0u; coherent < DE_LENGTH_OF_ARRAY(coherentOps); coherent++)
2493 {
2494 BlendOperationAdvancedParam testParams;
2495 testParams.testMode = TEST_MODE_COHERENT;
2496 testParams.overlap = VK_BLEND_OVERLAP_UNCORRELATED_EXT;
2497 testParams.coherentOperations = coherentOps[coherent];
2498 testParams.colorAttachmentsCount = 1u;
2499 testParams.independentBlend = DE_FALSE;
2500 testParams.premultipliedSrcColor = VK_TRUE;
2501 testParams.premultipliedDstColor = VK_TRUE;
2502 testParams.testNumber = testNumber++;
2503
2504 // We do two consecutive advanced blending operations
2505 deUint32 i = de::randomScalar<deUint32>(rnd, 0, DE_LENGTH_OF_ARRAY(blendOps) - 1);
2506 testParams.blendOps.push_back(blendOps[i]);
2507 i = de::randomScalar<deUint32>(rnd, 0, DE_LENGTH_OF_ARRAY(blendOps) - 1);
2508 testParams.blendOps.push_back(blendOps[i]);
2509
2510 coherentTests->addChild(newTestCase<BlendOperationAdvancedTest>(testCtx, testParams));
2511 }
2512 tests->addChild(coherentTests.release());
2513
2514
2515 return tests.release();
2516 }
2517
2518 } // pipeline
2519
2520 } // vkt
2521