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