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