1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Imagination Technologies Ltd.
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 Blend Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktPipelineBlendTests.hpp"
26 #include "vktPipelineClearUtil.hpp"
27 #include "vktPipelineImageUtil.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktPipelineUniqueRandomIterator.hpp"
30 #include "vktPipelineReferenceRenderer.hpp"
31 #include "vktTestCase.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkImageWithMemory.hpp"
34 #include "vkBufferWithMemory.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkPlatform.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkRef.hpp"
41 #include "vkRefUtil.hpp"
42 #include "vkTypeUtil.hpp"
43 #include "vkCmdUtil.hpp"
44 #include "vkObjUtil.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuPlatform.hpp"
47 #include "tcuTextureUtil.hpp"
48 #include "deRandom.hpp"
49 #include "deStringUtil.hpp"
50 #include "deUniquePtr.hpp"
51 #include <cstring>
52 #include <set>
53 #include <sstream>
54 #include <vector>
55 #include <algorithm>
56 #include <iterator>
57 
58 namespace vkt
59 {
60 namespace pipeline
61 {
62 
63 using namespace vk;
64 
65 namespace
66 {
67 
isSupportedBlendFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)68 bool isSupportedBlendFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
69 {
70 	VkFormatProperties formatProps;
71 
72 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
73 
74 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) &&
75 		   (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT);
76 }
77 
78 class BlendStateUniqueRandomIterator : public UniqueRandomIterator<VkPipelineColorBlendAttachmentState>
79 {
80 public:
81 											BlendStateUniqueRandomIterator		(deUint32 numberOfCombinations, int seed);
~BlendStateUniqueRandomIterator(void)82 	virtual									~BlendStateUniqueRandomIterator		(void) {}
83 	VkPipelineColorBlendAttachmentState		getIndexedValue	(deUint32 index);
84 
85 private:
86 	const static VkBlendFactor				m_blendFactors[];
87 	const static VkBlendOp					m_blendOps[];
88 
89 	// Pre-calculated constants
90 	const static deUint32					m_blendFactorsLength;
91 	const static deUint32					m_blendFactorsLength2;
92 	const static deUint32					m_blendFactorsLength3;
93 	const static deUint32					m_blendFactorsLength4;
94 	const static deUint32					m_blendOpsLength;
95 
96 	// Total number of cross-combinations of (srcBlendColor x destBlendColor x blendOpColor x srcBlendAlpha x destBlendAlpha x blendOpAlpha)
97 	const static deUint32					m_totalBlendStates;
98 };
99 
100 class BlendStateUniqueRandomIteratorDualSource : public UniqueRandomIterator<VkPipelineColorBlendAttachmentState>
101 {
102 public:
103 											BlendStateUniqueRandomIteratorDualSource		(deUint32 numberOfCombinations, int seed);
~BlendStateUniqueRandomIteratorDualSource(void)104 	virtual									~BlendStateUniqueRandomIteratorDualSource		(void) {}
105 	VkPipelineColorBlendAttachmentState		getIndexedValue	(deUint32 index);
106 
107 private:
108 	const static VkBlendFactor				m_blendFactors[];
109 	const static VkBlendOp					m_blendOps[];
110 
111 	// Pre-calculated constants
112 	const static deUint32					m_blendFactorsLength;
113 	const static deUint32					m_blendFactorsLength2;
114 	const static deUint32					m_blendFactorsLength3;
115 	const static deUint32					m_blendFactorsLength4;
116 	const static deUint32					m_blendOpsLength;
117 
118 	// Total number of cross-combinations of (srcBlendColor x destBlendColor x blendOpColor x srcBlendAlpha x destBlendAlpha x blendOpAlpha)
119 	const static deUint32					m_totalBlendStates;
120 };
121 
122 class BlendTest : public vkt::TestCase
123 {
124 public:
125 	enum
126 	{
127 		QUAD_COUNT = 4
128 	};
129 
130 	const static VkColorComponentFlags	s_colorWriteMasks[QUAD_COUNT];
131 	const static tcu::Vec4				s_blendConst;
132 
133 										BlendTest				(tcu::TestContext&							testContext,
134 																 const std::string&							name,
135 																 const std::string&							description,
136 																 const VkFormat								colorFormat,
137 																 const VkPipelineColorBlendAttachmentState	blendStates[QUAD_COUNT]);
138 	virtual								~BlendTest				(void);
139 	virtual void						initPrograms			(SourceCollections& sourceCollections) const;
140 	virtual void						checkSupport			(Context& context) const;
141 	virtual TestInstance*				createInstance			(Context& context) const;
142 
143 private:
144 	const VkFormat						m_colorFormat;
145 	VkPipelineColorBlendAttachmentState	m_blendStates[QUAD_COUNT];
146 };
147 
148 class DualSourceBlendTest : public vkt::TestCase
149 {
150 public:
151 	enum
152 	{
153 		QUAD_COUNT = 4
154 	};
155 
156 	const static VkColorComponentFlags	s_colorWriteMasks[QUAD_COUNT];
157 	const static tcu::Vec4				s_blendConst;
158 
159 										DualSourceBlendTest		(tcu::TestContext&							testContext,
160 																 const std::string&							name,
161 																 const std::string&							description,
162 																 const VkFormat								colorFormat,
163 																 const VkPipelineColorBlendAttachmentState	blendStates[QUAD_COUNT]);
164 	virtual								~DualSourceBlendTest	(void);
165 	virtual void						initPrograms			(SourceCollections& sourceCollections) const;
166 	virtual void						checkSupport			(Context& context) const;
167 	virtual TestInstance*				createInstance			(Context& context) const;
168 
169 private:
170 	const VkFormat						m_colorFormat;
171 	VkPipelineColorBlendAttachmentState	m_blendStates[QUAD_COUNT];
172 };
173 
174 class BlendTestInstance : public vkt::TestInstance
175 {
176 public:
177 										BlendTestInstance		(Context& context, const VkFormat colorFormat, const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT]);
178 	virtual								~BlendTestInstance		(void);
179 	virtual tcu::TestStatus				iterate					(void);
180 
181 private:
182 	tcu::TestStatus						verifyImage				(void);
183 
184 	VkPipelineColorBlendAttachmentState	m_blendStates[BlendTest::QUAD_COUNT];
185 
186 	const tcu::UVec2					m_renderSize;
187 	const VkFormat						m_colorFormat;
188 
189 	VkImageCreateInfo					m_colorImageCreateInfo;
190 	Move<VkImage>						m_colorImage;
191 	de::MovePtr<Allocation>				m_colorImageAlloc;
192 	Move<VkImageView>					m_colorAttachmentView;
193 	Move<VkRenderPass>					m_renderPass;
194 	Move<VkFramebuffer>					m_framebuffer;
195 
196 	Move<VkShaderModule>				m_vertexShaderModule;
197 	Move<VkShaderModule>				m_fragmentShaderModule;
198 
199 	Move<VkBuffer>						m_vertexBuffer;
200 	std::vector<Vertex4RGBA>			m_vertices;
201 	de::MovePtr<Allocation>				m_vertexBufferAlloc;
202 
203 	Move<VkPipelineLayout>				m_pipelineLayout;
204 	Move<VkPipeline>					m_graphicsPipelines[BlendTest::QUAD_COUNT];
205 
206 	Move<VkCommandPool>					m_cmdPool;
207 	Move<VkCommandBuffer>				m_cmdBuffer;
208 };
209 
210 // Blend test dual source blending
211 class DualSourceBlendTestInstance : public vkt::TestInstance
212 {
213 public:
214 										DualSourceBlendTestInstance		(Context& context, const VkFormat colorFormat, const VkPipelineColorBlendAttachmentState blendStates[DualSourceBlendTest::QUAD_COUNT]);
215 	virtual								~DualSourceBlendTestInstance	(void);
216 	virtual tcu::TestStatus				iterate					(void);
217 
218 private:
219 	tcu::TestStatus						verifyImage				(void);
220 
221 	VkPipelineColorBlendAttachmentState	m_blendStates[DualSourceBlendTest::QUAD_COUNT];
222 
223 	const tcu::UVec2					m_renderSize;
224 	const VkFormat						m_colorFormat;
225 
226 	VkImageCreateInfo					m_colorImageCreateInfo;
227 	Move<VkImage>						m_colorImage;
228 	de::MovePtr<Allocation>				m_colorImageAlloc;
229 	Move<VkImageView>					m_colorAttachmentView;
230 	Move<VkRenderPass>					m_renderPass;
231 	Move<VkFramebuffer>					m_framebuffer;
232 
233 	Move<VkShaderModule>				m_vertexShaderModule;
234 	Move<VkShaderModule>				m_fragmentShaderModule;
235 
236 	Move<VkBuffer>						m_vertexBuffer;
237 	std::vector<Vertex4RGBARGBA>		m_vertices;
238 	de::MovePtr<Allocation>				m_vertexBufferAlloc;
239 
240 	Move<VkPipelineLayout>				m_pipelineLayout;
241 	Move<VkPipeline>					m_graphicsPipelines[DualSourceBlendTest::QUAD_COUNT];
242 
243 	Move<VkCommandPool>					m_cmdPool;
244 	Move<VkCommandBuffer>				m_cmdBuffer;
245 };
246 
247 // BlendStateUniqueRandomIterator
248 
249 const VkBlendFactor BlendStateUniqueRandomIterator::m_blendFactors[] =
250 {
251 	VK_BLEND_FACTOR_ZERO,
252 	VK_BLEND_FACTOR_ONE,
253 	VK_BLEND_FACTOR_SRC_COLOR,
254 	VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
255 	VK_BLEND_FACTOR_DST_COLOR,
256 	VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
257 	VK_BLEND_FACTOR_SRC_ALPHA,
258 	VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
259 	VK_BLEND_FACTOR_DST_ALPHA,
260 	VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
261 	VK_BLEND_FACTOR_CONSTANT_COLOR,
262 	VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
263 	VK_BLEND_FACTOR_CONSTANT_ALPHA,
264 	VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
265 	VK_BLEND_FACTOR_SRC_ALPHA_SATURATE,
266 };
267 
268 const VkBlendOp BlendStateUniqueRandomIterator::m_blendOps[] =
269 {
270 	VK_BLEND_OP_ADD,
271 	VK_BLEND_OP_SUBTRACT,
272 	VK_BLEND_OP_REVERSE_SUBTRACT,
273 	VK_BLEND_OP_MIN,
274 	VK_BLEND_OP_MAX
275 };
276 
277 const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength		= DE_LENGTH_OF_ARRAY(m_blendFactors);
278 const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength2	= m_blendFactorsLength * m_blendFactorsLength;
279 const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength3	= m_blendFactorsLength2 * m_blendFactorsLength;
280 const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength4	= m_blendFactorsLength3 * m_blendFactorsLength;
281 const deUint32 BlendStateUniqueRandomIterator::m_blendOpsLength			= DE_LENGTH_OF_ARRAY(m_blendOps);
282 const deUint32 BlendStateUniqueRandomIterator::m_totalBlendStates		= m_blendFactorsLength4 * m_blendOpsLength * m_blendOpsLength;
283 
284 
BlendStateUniqueRandomIterator(deUint32 numberOfCombinations,int seed)285 BlendStateUniqueRandomIterator::BlendStateUniqueRandomIterator (deUint32 numberOfCombinations, int seed)
286 	: UniqueRandomIterator<VkPipelineColorBlendAttachmentState>(numberOfCombinations, m_totalBlendStates, seed)
287 {
288 }
289 
getIndexedValue(deUint32 index)290 VkPipelineColorBlendAttachmentState BlendStateUniqueRandomIterator::getIndexedValue (deUint32 index)
291 {
292 	const deUint32		blendOpAlphaIndex			= index / (m_blendFactorsLength4 * m_blendOpsLength);
293 	const deUint32		blendOpAlphaSeqIndex		= blendOpAlphaIndex * (m_blendFactorsLength4 * m_blendOpsLength);
294 
295 	const deUint32		destBlendAlphaIndex			= (index - blendOpAlphaSeqIndex) / (m_blendFactorsLength3 * m_blendOpsLength);
296 	const deUint32		destBlendAlphaSeqIndex		= destBlendAlphaIndex * (m_blendFactorsLength3 * m_blendOpsLength);
297 
298 	const deUint32		srcBlendAlphaIndex			= (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex) / (m_blendFactorsLength2 * m_blendOpsLength);
299 	const deUint32		srcBlendAlphaSeqIndex		= srcBlendAlphaIndex * (m_blendFactorsLength2 * m_blendOpsLength);
300 
301 	const deUint32		blendOpColorIndex			= (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex) / m_blendFactorsLength2;
302 	const deUint32		blendOpColorSeqIndex		= blendOpColorIndex * m_blendFactorsLength2;
303 
304 	const deUint32		destBlendColorIndex			= (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex - blendOpColorSeqIndex) / m_blendFactorsLength;
305 	const deUint32		destBlendColorSeqIndex		= destBlendColorIndex * m_blendFactorsLength;
306 
307 	const deUint32		srcBlendColorIndex			= index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex - blendOpColorSeqIndex - destBlendColorSeqIndex;
308 
309 	const VkPipelineColorBlendAttachmentState blendAttachmentState =
310 	{
311 		true,														// VkBool32					blendEnable;
312 		m_blendFactors[srcBlendColorIndex],							// VkBlendFactor			srcColorBlendFactor;
313 		m_blendFactors[destBlendColorIndex],						// VkBlendFactor			dstColorBlendFactor;
314 		m_blendOps[blendOpColorIndex],								// VkBlendOp				colorBlendOp;
315 		m_blendFactors[srcBlendAlphaIndex],							// VkBlendFactor			srcAlphaBlendFactor;
316 		m_blendFactors[destBlendAlphaIndex],						// VkBlendFactor			dstAlphaBlendFactor;
317 		m_blendOps[blendOpAlphaIndex],								// VkBlendOp				alphaBlendOp;
318 		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |		// VkColorComponentFlags	colorWriteMask;
319 			VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
320 	};
321 
322 	return blendAttachmentState;
323 }
324 
325 // BlendStateUniqueRandomIteratorDualSource
326 
327 const VkBlendFactor BlendStateUniqueRandomIteratorDualSource::m_blendFactors[] =
328 {
329 	VK_BLEND_FACTOR_ZERO,
330 	VK_BLEND_FACTOR_ONE,
331 	VK_BLEND_FACTOR_SRC_COLOR,
332 	VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
333 	VK_BLEND_FACTOR_DST_COLOR,
334 	VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
335 	VK_BLEND_FACTOR_SRC_ALPHA,
336 	VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
337 	VK_BLEND_FACTOR_DST_ALPHA,
338 	VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
339 	VK_BLEND_FACTOR_CONSTANT_COLOR,
340 	VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
341 	VK_BLEND_FACTOR_CONSTANT_ALPHA,
342 	VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
343 	VK_BLEND_FACTOR_SRC_ALPHA_SATURATE,
344 	VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR,
345 	VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA,
346 	VK_BLEND_FACTOR_SRC1_COLOR,
347 	VK_BLEND_FACTOR_SRC1_ALPHA
348 };
349 
350 const VkBlendOp BlendStateUniqueRandomIteratorDualSource::m_blendOps[] =
351 {
352 	VK_BLEND_OP_ADD,
353 	VK_BLEND_OP_SUBTRACT,
354 	VK_BLEND_OP_REVERSE_SUBTRACT,
355 	VK_BLEND_OP_MIN,
356 	VK_BLEND_OP_MAX
357 };
358 
359 const deUint32 BlendStateUniqueRandomIteratorDualSource::m_blendFactorsLength	= DE_LENGTH_OF_ARRAY(m_blendFactors);
360 const deUint32 BlendStateUniqueRandomIteratorDualSource::m_blendFactorsLength2	= m_blendFactorsLength * m_blendFactorsLength;
361 const deUint32 BlendStateUniqueRandomIteratorDualSource::m_blendFactorsLength3	= m_blendFactorsLength2 * m_blendFactorsLength;
362 const deUint32 BlendStateUniqueRandomIteratorDualSource::m_blendFactorsLength4	= m_blendFactorsLength3 * m_blendFactorsLength;
363 const deUint32 BlendStateUniqueRandomIteratorDualSource::m_blendOpsLength		= DE_LENGTH_OF_ARRAY(m_blendOps);
364 const deUint32 BlendStateUniqueRandomIteratorDualSource::m_totalBlendStates		= m_blendFactorsLength4 * m_blendOpsLength * m_blendOpsLength;
365 
366 
BlendStateUniqueRandomIteratorDualSource(deUint32 numberOfCombinations,int seed)367 BlendStateUniqueRandomIteratorDualSource::BlendStateUniqueRandomIteratorDualSource (deUint32 numberOfCombinations, int seed)
368 	: UniqueRandomIterator<VkPipelineColorBlendAttachmentState>(numberOfCombinations, m_totalBlendStates, seed)
369 {
370 }
371 
getIndexedValue(deUint32 index)372 VkPipelineColorBlendAttachmentState BlendStateUniqueRandomIteratorDualSource::getIndexedValue (deUint32 index)
373 {
374 	const deUint32		blendOpAlphaIndex			= index / (m_blendFactorsLength4 * m_blendOpsLength);
375 	const deUint32		blendOpAlphaSeqIndex		= blendOpAlphaIndex * (m_blendFactorsLength4 * m_blendOpsLength);
376 
377 	const deUint32		destBlendAlphaIndex			= (index - blendOpAlphaSeqIndex) / (m_blendFactorsLength3 * m_blendOpsLength);
378 	const deUint32		destBlendAlphaSeqIndex		= destBlendAlphaIndex * (m_blendFactorsLength3 * m_blendOpsLength);
379 
380 	const deUint32		srcBlendAlphaIndex			= (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex) / (m_blendFactorsLength2 * m_blendOpsLength);
381 	const deUint32		srcBlendAlphaSeqIndex		= srcBlendAlphaIndex * (m_blendFactorsLength2 * m_blendOpsLength);
382 
383 	const deUint32		blendOpColorIndex			= (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex) / m_blendFactorsLength2;
384 	const deUint32		blendOpColorSeqIndex		= blendOpColorIndex * m_blendFactorsLength2;
385 
386 	const deUint32		destBlendColorIndex			= (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex - blendOpColorSeqIndex) / m_blendFactorsLength;
387 	const deUint32		destBlendColorSeqIndex		= destBlendColorIndex * m_blendFactorsLength;
388 
389 	const deUint32		srcBlendColorIndex			= index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex - blendOpColorSeqIndex - destBlendColorSeqIndex;
390 
391 	const VkPipelineColorBlendAttachmentState blendAttachmentState =
392 	{
393 		true,														// VkBool32					blendEnable;
394 		m_blendFactors[srcBlendColorIndex],							// VkBlendFactor			srcColorBlendFactor;
395 		m_blendFactors[destBlendColorIndex],						// VkBlendFactor			dstColorBlendFactor;
396 		m_blendOps[blendOpColorIndex],								// VkBlendOp				colorBlendOp;
397 		m_blendFactors[srcBlendAlphaIndex],							// VkBlendFactor			srcAlphaBlendFactor;
398 		m_blendFactors[destBlendAlphaIndex],						// VkBlendFactor			dstAlphaBlendFactor;
399 		m_blendOps[blendOpAlphaIndex],								// VkBlendOp				alphaBlendOp;
400 		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |		// VkColorComponentFlags	colorWriteMask;
401 			VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
402 	};
403 
404 	return blendAttachmentState;
405 }
406 
407 
408 // BlendTest
409 
410 const VkColorComponentFlags BlendTest::s_colorWriteMasks[BlendTest::QUAD_COUNT] = { VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT,	// Pair of channels: R & G
411 																					VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT,	// Pair of channels: G & B
412 																					VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,	// Pair of channels: B & A
413 																					VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT };	// All channels
414 
415 const tcu::Vec4 BlendTest::s_blendConst = tcu::Vec4(0.1f, 0.2f, 0.3f, 0.4f);
416 
BlendTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const VkFormat colorFormat,const VkPipelineColorBlendAttachmentState blendStates[QUAD_COUNT])417 BlendTest::BlendTest (tcu::TestContext&								testContext,
418 					  const std::string&							name,
419 					  const std::string&							description,
420 					  const VkFormat								colorFormat,
421 					  const VkPipelineColorBlendAttachmentState		blendStates[QUAD_COUNT])
422 	: vkt::TestCase	(testContext, name, description)
423 	, m_colorFormat(colorFormat)
424 {
425 	deMemcpy(m_blendStates, blendStates, sizeof(VkPipelineColorBlendAttachmentState) * QUAD_COUNT);
426 }
427 
~BlendTest(void)428 BlendTest::~BlendTest (void)
429 {
430 }
431 
createInstance(Context & context) const432 TestInstance* BlendTest::createInstance(Context& context) const
433 {
434 	return new BlendTestInstance(context, m_colorFormat, m_blendStates);
435 }
436 
checkSupport(Context & context) const437 void BlendTest::checkSupport (Context& context) const
438 {
439 	if (!isSupportedBlendFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_colorFormat))
440 		throw tcu::NotSupportedError(std::string("Unsupported color blending format: ") + getFormatName(m_colorFormat));
441 }
442 
initPrograms(SourceCollections & sourceCollections) const443 void BlendTest::initPrograms (SourceCollections& sourceCollections) const
444 {
445 	std::ostringstream fragmentSource;
446 
447 	sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
448 		"#version 310 es\n"
449 		"layout(location = 0) in highp vec4 position;\n"
450 		"layout(location = 1) in highp vec4 color;\n"
451 		"layout(location = 0) out highp vec4 vtxColor;\n"
452 		"void main (void)\n"
453 		"{\n"
454 		"	gl_Position = position;\n"
455 		"	vtxColor = color;\n"
456 		"}\n");
457 
458 	fragmentSource << "#version 310 es\n"
459 		"layout(location = 0) in highp vec4 vtxColor;\n"
460 		"layout(location = 0) out highp vec4 fragColor;\n"
461 		"void main (void)\n"
462 		"{\n"
463 		"	fragColor = vtxColor;\n"
464 		"}\n";
465 
466 	sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
467 }
468 
469 // DualSourceBlendTest
470 
471 const VkColorComponentFlags DualSourceBlendTest::s_colorWriteMasks[BlendTest::QUAD_COUNT] = { VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT,	// Pair of channels: R & G
472 																							  VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT,	// Pair of channels: G & B
473 																							  VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,	// Pair of channels: B & A
474 																							  VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT };	// All channels
475 
476 const tcu::Vec4 DualSourceBlendTest::s_blendConst = tcu::Vec4(0.1f, 0.2f, 0.3f, 0.4f);
477 
DualSourceBlendTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const VkFormat colorFormat,const VkPipelineColorBlendAttachmentState blendStates[QUAD_COUNT])478 DualSourceBlendTest::DualSourceBlendTest (tcu::TestContext&								testContext,
479 										  const std::string&							name,
480 										  const std::string&							description,
481 										  const VkFormat								colorFormat,
482 										  const VkPipelineColorBlendAttachmentState		blendStates[QUAD_COUNT])
483 	: vkt::TestCase	(testContext, name, description)
484 	, m_colorFormat(colorFormat)
485 {
486 	deMemcpy(m_blendStates, blendStates, sizeof(VkPipelineColorBlendAttachmentState) * QUAD_COUNT);
487 }
488 
~DualSourceBlendTest(void)489 DualSourceBlendTest::~DualSourceBlendTest (void)
490 {
491 }
492 
isSrc1BlendFactor(vk::VkBlendFactor blendFactor)493 deBool isSrc1BlendFactor(vk::VkBlendFactor blendFactor)
494 {
495 	switch(blendFactor)
496 	{
497 		case vk::VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:
498 		case vk::VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA:
499 		case vk::VK_BLEND_FACTOR_SRC1_ALPHA:
500 		case vk::VK_BLEND_FACTOR_SRC1_COLOR:
501 			return DE_TRUE;
502 		default:
503 			return DE_FALSE;
504 	}
505 }
506 
createInstance(Context & context) const507 TestInstance* DualSourceBlendTest::createInstance(Context& context) const
508 {
509 	return new DualSourceBlendTestInstance(context, m_colorFormat, m_blendStates);
510 }
511 
checkSupport(Context & context) const512 void DualSourceBlendTest::checkSupport (Context& context) const
513 {
514 	const vk::VkPhysicalDeviceFeatures features = context.getDeviceFeatures();
515 
516 	deBool	isDualSourceTest = DE_FALSE;
517 	for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
518 	{
519 		isDualSourceTest =
520 			isSrc1BlendFactor(this->m_blendStates[quadNdx].srcColorBlendFactor) ||
521 			isSrc1BlendFactor(this->m_blendStates[quadNdx].dstColorBlendFactor) ||
522 			isSrc1BlendFactor(this->m_blendStates[quadNdx].srcAlphaBlendFactor) ||
523 			isSrc1BlendFactor(this->m_blendStates[quadNdx].dstAlphaBlendFactor);
524 		if (isDualSourceTest)
525 			break;
526 	}
527 	if (isDualSourceTest && !features.dualSrcBlend)
528 		throw tcu::NotSupportedError("Dual-Source blending not supported");
529 
530 	if (!isSupportedBlendFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_colorFormat))
531 		throw tcu::NotSupportedError(std::string("Unsupported color blending format: ") + getFormatName(m_colorFormat));
532 }
533 
initPrograms(SourceCollections & sourceCollections) const534 void DualSourceBlendTest::initPrograms (SourceCollections& sourceCollections) const
535 {
536 	std::ostringstream fragmentSource;
537 
538 	sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
539 		"#version 450\n"
540 		"layout(location = 0) in highp vec4 position;\n"
541 		"layout(location = 1) in highp vec4 color0;\n"
542 		"layout(location = 2) in highp vec4 color1;\n"
543 		"layout(location = 0) out highp vec4 vtxColor0;\n"
544 		"layout(location = 1) out highp vec4 vtxColor1;\n"
545 		"void main (void)\n"
546 		"{\n"
547 		"	gl_Position = position;\n"
548 		"	vtxColor0 = color0;\n"
549 		"	vtxColor1 = color1;\n"
550 		"}\n");
551 
552 	fragmentSource << "#version 450\n"
553 		"layout(location = 0) in highp vec4 vtxColor0;\n"
554 		"layout(location = 1) in highp vec4 vtxColor1;\n"
555 		"layout(location = 0, index = 0) out highp vec4 fragColor0;\n"
556 		"layout(location = 0, index = 1) out highp vec4 fragColor1;\n"
557 		"void main (void)\n"
558 		"{\n"
559 		"	fragColor0 = vtxColor0;\n"
560 		"	fragColor1 = vtxColor1;\n"
561 		"}\n";
562 
563 	sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
564 }
565 
566 // BlendTestInstance
567 
BlendTestInstance(Context & context,const VkFormat colorFormat,const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])568 BlendTestInstance::BlendTestInstance (Context&									context,
569 									  const VkFormat							colorFormat,
570 									  const VkPipelineColorBlendAttachmentState	blendStates[BlendTest::QUAD_COUNT])
571 	: vkt::TestInstance	(context)
572 	, m_renderSize		(32, 32)
573 	, m_colorFormat		(colorFormat)
574 {
575 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
576 	const VkDevice				vkDevice			= m_context.getDevice();
577 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
578 	SimpleAllocator				memAlloc			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
579 
580 	// Copy depth operators
581 	deMemcpy(m_blendStates, blendStates, sizeof(VkPipelineColorBlendAttachmentState) * BlendTest::QUAD_COUNT);
582 
583 	// Create color image
584 	{
585 		const VkImageCreateInfo	colorImageParams =
586 		{
587 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
588 			DE_NULL,																	// const void*				pNext;
589 			0u,																			// VkImageCreateFlags		flags;
590 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
591 			m_colorFormat,																// VkFormat					format;
592 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
593 			1u,																			// deUint32					mipLevels;
594 			1u,																			// deUint32					arrayLayers;
595 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
596 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
597 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
598 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
599 			1u,																			// deUint32					queueFamilyIndexCount;
600 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
601 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
602 		};
603 
604 		m_colorImageCreateInfo	= colorImageParams;
605 		m_colorImage			= createImage(vk, vkDevice, &m_colorImageCreateInfo);
606 
607 		// Allocate and bind color image memory
608 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
609 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
610 	}
611 
612 	// Create color attachment view
613 	{
614 		const VkImageViewCreateInfo colorAttachmentViewParams =
615 		{
616 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
617 			DE_NULL,											// const void*				pNext;
618 			0u,													// VkImageViewCreateFlags	flags;
619 			*m_colorImage,										// VkImage					image;
620 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
621 			m_colorFormat,										// VkFormat					format;
622 			{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY},
623 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
624 		};
625 
626 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
627 	}
628 
629 	// Create render pass
630 	m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat);
631 
632 	// Create framebuffer
633 	{
634 		const VkFramebufferCreateInfo framebufferParams =
635 		{
636 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
637 			DE_NULL,											// const void*				pNext;
638 			0u,													// VkFramebufferCreateFlags	flags;
639 			*m_renderPass,										// VkRenderPass				renderPass;
640 			1u,													// deUint32					attachmentCount;
641 			&m_colorAttachmentView.get(),						// const VkImageView*		pAttachments;
642 			(deUint32)m_renderSize.x(),							// deUint32					width;
643 			(deUint32)m_renderSize.y(),							// deUint32					height;
644 			1u													// deUint32					layers;
645 		};
646 
647 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
648 	}
649 
650 	// Create pipeline layout
651 	{
652 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
653 		{
654 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
655 			DE_NULL,											// const void*						pNext;
656 			0u,													// VkPipelineLayoutCreateFlags		flags;
657 			0u,													// deUint32							setLayoutCount;
658 			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
659 			0u,													// deUint32							pushConstantRangeCount;
660 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
661 		};
662 
663 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
664 	}
665 
666 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
667 	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
668 
669 	// Create pipeline
670 	{
671 		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
672 		{
673 			0u,									// deUint32					binding;
674 			sizeof(Vertex4RGBA),				// deUint32					strideInBytes;
675 			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	inputRate;
676 		};
677 
678 		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[2]	=
679 		{
680 			{
681 				0u,								// deUint32	location;
682 				0u,								// deUint32	binding;
683 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
684 				0u								// deUint32	offset;
685 			},
686 			{
687 				1u,								// deUint32	location;
688 				0u,								// deUint32	binding;
689 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
690 				(deUint32)(sizeof(float) * 4),	// deUint32	offset;
691 			}
692 		};
693 
694 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
695 		{
696 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
697 			DE_NULL,														// const void*								pNext;
698 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
699 			1u,																// deUint32									vertexBindingDescriptionCount;
700 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
701 			2u,																// deUint32									vertexAttributeDescriptionCount;
702 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
703 		};
704 
705 		const std::vector<VkViewport>				viewports							(1, makeViewport(m_renderSize));
706 		const std::vector<VkRect2D>					scissors							(1, makeRect2D(m_renderSize));
707 
708 		// The color blend attachment will be set up before creating the graphics pipeline.
709 		VkPipelineColorBlendStateCreateInfo			colorBlendStateParams				=
710 		{
711 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
712 			DE_NULL,													// const void*									pNext;
713 			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
714 			false,														// VkBool32										logicOpEnable;
715 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
716 			0u,															// deUint32										attachmentCount;
717 			DE_NULL,													// const VkPipelineColorBlendAttachmentState*	pAttachments;
718 			{															// float										blendConstants[4];
719 				BlendTest::s_blendConst.x(),
720 				BlendTest::s_blendConst.y(),
721 				BlendTest::s_blendConst.z(),
722 				BlendTest::s_blendConst.w()
723 			}
724 		};
725 
726 		for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
727 		{
728 			colorBlendStateParams.attachmentCount	= 1u;
729 			colorBlendStateParams.pAttachments		= &m_blendStates[quadNdx];
730 			m_graphicsPipelines[quadNdx]			= makeGraphicsPipeline(vk,									// const DeviceInterface&                        vk
731 																		   vkDevice,							// const VkDevice                                device
732 																		   *m_pipelineLayout,					// const VkPipelineLayout                        pipelineLayout
733 																		   *m_vertexShaderModule,				// const VkShaderModule                          vertexShaderModule
734 																		   DE_NULL,								// const VkShaderModule                          tessellationControlModule
735 																		   DE_NULL,								// const VkShaderModule                          tessellationEvalModule
736 																		   DE_NULL,								// const VkShaderModule                          geometryShaderModule
737 																		   *m_fragmentShaderModule,				// const VkShaderModule                          fragmentShaderModule
738 																		   *m_renderPass,						// const VkRenderPass                            renderPass
739 																		   viewports,							// const std::vector<VkViewport>&                viewports
740 																		   scissors,							// const std::vector<VkRect2D>&                  scissors
741 																		   VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
742 																		   0u,									// const deUint32                                subpass
743 																		   0u,									// const deUint32                                patchControlPoints
744 																		   &vertexInputStateParams,				// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
745 																		   DE_NULL,								// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
746 																		   DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
747 																		   DE_NULL,								// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
748 																		   &colorBlendStateParams);				// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
749 		}
750 	}
751 
752 	// Create vertex buffer
753 	{
754 		const VkBufferCreateInfo vertexBufferParams =
755 		{
756 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
757 			DE_NULL,									// const void*			pNext;
758 			0u,											// VkBufferCreateFlags	flags;
759 			1024u,										// VkDeviceSize			size;
760 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
761 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
762 			1u,											// deUint32				queueFamilyIndexCount;
763 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
764 		};
765 
766 		m_vertices			= createOverlappingQuads();
767 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
768 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
769 
770 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
771 
772 		// Adjust vertex colors
773 		if (!isFloatFormat(m_colorFormat))
774 		{
775 			const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(mapVkFormat(m_colorFormat));
776 			for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
777 				m_vertices[vertexNdx].color = (m_vertices[vertexNdx].color - formatInfo.lookupBias) / formatInfo.lookupScale;
778 		}
779 
780 		// Upload vertex data
781 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
782 
783 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
784 	}
785 
786 	// Create command pool
787 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
788 
789 	// Create command buffer
790 	{
791 		const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
792 
793 		// Color image layout transition
794 		const VkImageMemoryBarrier imageLayoutBarrier =
795 		{
796 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
797 			DE_NULL,																// const void*                pNext;
798 			(VkAccessFlags)0,														// VkAccessFlags              srcAccessMask;
799 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,									// VkAccessFlags              dstAccessMask;
800 			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
801 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,								// VkImageLayout              newLayout;
802 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
803 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
804 			*m_colorImage,															// VkImage                    image;
805 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }							// VkImageSubresourceRange    subresourceRange;
806 		};
807 
808 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
809 
810 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
811 
812 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
813 			0u, DE_NULL, 0u, DE_NULL, 1u, &imageLayoutBarrier);
814 
815 		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
816 
817 		const VkDeviceSize quadOffset = (m_vertices.size() / BlendTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
818 
819 		for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
820 		{
821 			VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
822 
823 			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]);
824 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
825 			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / BlendTest::QUAD_COUNT), 1, 0, 0);
826 		}
827 
828 		endRenderPass(vk, *m_cmdBuffer);
829 		endCommandBuffer(vk, *m_cmdBuffer);
830 	}
831 }
832 
~BlendTestInstance(void)833 BlendTestInstance::~BlendTestInstance (void)
834 {
835 }
836 
iterate(void)837 tcu::TestStatus BlendTestInstance::iterate (void)
838 {
839 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
840 	const VkDevice				vkDevice	= m_context.getDevice();
841 	const VkQueue				queue		= m_context.getUniversalQueue();
842 
843 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
844 
845 	return verifyImage();
846 }
847 
getNormChannelThreshold(const tcu::TextureFormat & format,int numBits)848 float getNormChannelThreshold (const tcu::TextureFormat& format, int numBits)
849 {
850 	switch (tcu::getTextureChannelClass(format.type))
851 	{
852 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:	return static_cast<float>(BlendTest::QUAD_COUNT) / static_cast<float>((1 << numBits) - 1);
853 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:	return static_cast<float>(BlendTest::QUAD_COUNT) / static_cast<float>((1 << (numBits - 1)) - 1);
854 		default:
855 			break;
856 	}
857 
858 	DE_ASSERT(false);
859 	return 0.0f;
860 }
861 
getFormatThreshold(const tcu::TextureFormat & format)862 tcu::Vec4 getFormatThreshold (const tcu::TextureFormat& format)
863 {
864 	using tcu::Vec4;
865 	using tcu::TextureFormat;
866 
867 	Vec4 threshold(0.01f);
868 
869 	switch (format.type)
870 	{
871 		case TextureFormat::UNORM_BYTE_44:
872 			threshold = Vec4(getNormChannelThreshold(format, 4), getNormChannelThreshold(format, 4), 1.0f, 1.0f);
873 			break;
874 
875 		case TextureFormat::UNORM_SHORT_565:
876 			threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 6), getNormChannelThreshold(format, 5), 1.0f);
877 			break;
878 
879 		case TextureFormat::UNORM_SHORT_555:
880 			threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), 1.0f);
881 			break;
882 
883 		case TextureFormat::UNORM_SHORT_4444:
884 			threshold = Vec4(getNormChannelThreshold(format, 4));
885 			break;
886 
887 		case TextureFormat::UNORM_SHORT_5551:
888 			threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), 0.1f);
889 			break;
890 
891 		case TextureFormat::UNORM_INT_1010102_REV:
892 		case TextureFormat::SNORM_INT_1010102_REV:
893 			threshold = Vec4(getNormChannelThreshold(format, 10), getNormChannelThreshold(format, 10), getNormChannelThreshold(format, 10), 0.34f);
894 			break;
895 
896 		case TextureFormat::UNORM_INT8:
897 		case TextureFormat::SNORM_INT8:
898 			threshold = Vec4(getNormChannelThreshold(format, 8));
899 			break;
900 
901 		case TextureFormat::UNORM_INT16:
902 		case TextureFormat::SNORM_INT16:
903 			threshold = Vec4(getNormChannelThreshold(format, 16));
904 			break;
905 
906 		case TextureFormat::UNORM_INT32:
907 		case TextureFormat::SNORM_INT32:
908 			threshold = Vec4(getNormChannelThreshold(format, 32));
909 			break;
910 
911 		case TextureFormat::HALF_FLOAT:
912 			threshold = Vec4(0.005f);
913 			break;
914 
915 		case TextureFormat::FLOAT:
916 			threshold = Vec4(0.00001f);
917 			break;
918 
919 		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:
920 			threshold = Vec4(0.02f, 0.02f, 0.0625f, 1.0f);
921 			break;
922 
923 		case TextureFormat::UNSIGNED_INT_999_E5_REV:
924 			threshold = Vec4(0.05f, 0.05f, 0.05f, 1.0f);
925 			break;
926 
927 		case TextureFormat::UNORM_SHORT_1555:
928 			threshold = Vec4(0.1f, getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5));
929 			break;
930 
931 		default:
932 			DE_ASSERT(false);
933 	}
934 
935 	// Return value matching the channel order specified by the format
936 	if (format.order == tcu::TextureFormat::BGR || format.order == tcu::TextureFormat::BGRA)
937 		return threshold.swizzle(2, 1, 0, 3);
938 	else
939 		return threshold;
940 }
941 
isLegalExpandableFormat(tcu::TextureFormat::ChannelType channeltype)942 bool isLegalExpandableFormat (tcu::TextureFormat::ChannelType channeltype)
943 {
944 	using tcu::TextureFormat;
945 
946 	switch (channeltype)
947 	{
948 		case TextureFormat::UNORM_INT24:
949 		case TextureFormat::UNORM_BYTE_44:
950 		case TextureFormat::UNORM_SHORT_565:
951 		case TextureFormat::UNORM_SHORT_555:
952 		case TextureFormat::UNORM_SHORT_4444:
953 		case TextureFormat::UNORM_SHORT_5551:
954 		case TextureFormat::UNORM_SHORT_1555:
955 		case TextureFormat::UNORM_INT_101010:
956 		case TextureFormat::SNORM_INT_1010102_REV:
957 		case TextureFormat::UNORM_INT_1010102_REV:
958 		case TextureFormat::UNSIGNED_BYTE_44:
959 		case TextureFormat::UNSIGNED_SHORT_565:
960 		case TextureFormat::UNSIGNED_SHORT_4444:
961 		case TextureFormat::UNSIGNED_SHORT_5551:
962 		case TextureFormat::SIGNED_INT_1010102_REV:
963 		case TextureFormat::UNSIGNED_INT_1010102_REV:
964 		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:
965 		case TextureFormat::UNSIGNED_INT_999_E5_REV:
966 		case TextureFormat::UNSIGNED_INT_24_8:
967 		case TextureFormat::UNSIGNED_INT_24_8_REV:
968 		case TextureFormat::UNSIGNED_INT24:
969 		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
970 			return true;
971 
972 		case TextureFormat::SNORM_INT8:
973 		case TextureFormat::SNORM_INT16:
974 		case TextureFormat::SNORM_INT32:
975 		case TextureFormat::UNORM_INT8:
976 		case TextureFormat::UNORM_INT16:
977 		case TextureFormat::UNORM_INT32:
978 		case TextureFormat::UNSIGNED_INT_16_8_8:
979 		case TextureFormat::SIGNED_INT8:
980 		case TextureFormat::SIGNED_INT16:
981 		case TextureFormat::SIGNED_INT32:
982 		case TextureFormat::UNSIGNED_INT8:
983 		case TextureFormat::UNSIGNED_INT16:
984 		case TextureFormat::UNSIGNED_INT32:
985 		case TextureFormat::HALF_FLOAT:
986 		case TextureFormat::FLOAT:
987 		case TextureFormat::FLOAT64:
988 			return false;
989 
990 		default:
991 			DE_FATAL("Unknown texture format");
992 	}
993 	return false;
994 }
995 
isSmallerThan8BitFormat(tcu::TextureFormat::ChannelType channeltype)996 bool isSmallerThan8BitFormat (tcu::TextureFormat::ChannelType channeltype)
997 {
998 	using tcu::TextureFormat;
999 
1000 	// Note: only checks the legal expandable formats
1001 	// (i.e, formats that have channels that fall outside
1002 	// the 8, 16 and 32 bit width)
1003 	switch (channeltype)
1004 	{
1005 		case TextureFormat::UNORM_BYTE_44:
1006 		case TextureFormat::UNORM_SHORT_565:
1007 		case TextureFormat::UNORM_SHORT_555:
1008 		case TextureFormat::UNORM_SHORT_4444:
1009 		case TextureFormat::UNORM_SHORT_5551:
1010 		case TextureFormat::UNORM_SHORT_1555:
1011 		case TextureFormat::UNSIGNED_BYTE_44:
1012 		case TextureFormat::UNSIGNED_SHORT_565:
1013 		case TextureFormat::UNSIGNED_SHORT_4444:
1014 		case TextureFormat::UNSIGNED_SHORT_5551:
1015 			return true;
1016 
1017 		case TextureFormat::UNORM_INT24:
1018 		case TextureFormat::UNORM_INT_101010:
1019 		case TextureFormat::SNORM_INT_1010102_REV:
1020 		case TextureFormat::UNORM_INT_1010102_REV:
1021 		case TextureFormat::SIGNED_INT_1010102_REV:
1022 		case TextureFormat::UNSIGNED_INT_1010102_REV:
1023 		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:
1024 		case TextureFormat::UNSIGNED_INT_999_E5_REV:
1025 		case TextureFormat::UNSIGNED_INT_24_8:
1026 		case TextureFormat::UNSIGNED_INT_24_8_REV:
1027 		case TextureFormat::UNSIGNED_INT24:
1028 		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
1029 			return false;
1030 
1031 		default:
1032 			DE_FATAL("Unknown texture format");
1033 	}
1034 
1035 	return false;
1036 }
1037 
verifyImage(void)1038 tcu::TestStatus BlendTestInstance::verifyImage (void)
1039 {
1040 	const tcu::TextureFormat	tcuColorFormat		= mapVkFormat(m_colorFormat);
1041 	const tcu::TextureFormat	tcuColorFormat64	= mapVkFormat(VK_FORMAT_R64G64B64A64_SFLOAT);
1042 	const tcu::TextureFormat	tcuColorFormat8		= mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
1043 	const tcu::TextureFormat	tcuDepthFormat		= tcu::TextureFormat(); // Undefined depth/stencil format
1044 	const ColorVertexShader		vertexShader;
1045 	const ColorFragmentShader	fragmentShader		(tcuColorFormat, tcuDepthFormat);
1046 	const rr::Program			program				(&vertexShader, &fragmentShader);
1047 	ReferenceRenderer			refRenderer			(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
1048 	ReferenceRenderer			refRenderer64		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat64, tcuDepthFormat, &program);
1049 	ReferenceRenderer			refRenderer8		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat8, tcuDepthFormat, &program);
1050 	bool						compareOk			= false;
1051 
1052 	// Render reference image
1053 	{
1054 		for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
1055 		{
1056 			const VkPipelineColorBlendAttachmentState& blendState = m_blendStates[quadNdx];
1057 
1058 			// Set blend state
1059 			rr::RenderState renderState					(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1060 			renderState.fragOps.blendMode				= rr::BLENDMODE_STANDARD;
1061 			renderState.fragOps.blendRGBState.srcFunc	= mapVkBlendFactor(blendState.srcColorBlendFactor);
1062 			renderState.fragOps.blendRGBState.dstFunc	= mapVkBlendFactor(blendState.dstColorBlendFactor);
1063 			renderState.fragOps.blendRGBState.equation	= mapVkBlendOp(blendState.colorBlendOp);
1064 			renderState.fragOps.blendAState.srcFunc		= mapVkBlendFactor(blendState.srcAlphaBlendFactor);
1065 			renderState.fragOps.blendAState.dstFunc		= mapVkBlendFactor(blendState.dstAlphaBlendFactor);
1066 			renderState.fragOps.blendAState.equation	= mapVkBlendOp(blendState.alphaBlendOp);
1067 			renderState.fragOps.blendColor				= BlendTest::s_blendConst;
1068 			renderState.fragOps.colorMask				= mapVkColorComponentFlags(BlendTest::s_colorWriteMasks[quadNdx]);
1069 
1070 			refRenderer.draw(renderState,
1071 							rr::PRIMITIVETYPE_TRIANGLES,
1072 							std::vector<Vertex4RGBA>(m_vertices.begin() + quadNdx * 6,
1073 													 m_vertices.begin() + (quadNdx + 1) * 6));
1074 
1075 			if (isLegalExpandableFormat(tcuColorFormat.type))
1076 			{
1077 				refRenderer64.draw(renderState,
1078 								   rr::PRIMITIVETYPE_TRIANGLES,
1079 								   std::vector<Vertex4RGBA>(m_vertices.begin() + quadNdx * 6,
1080 								   m_vertices.begin() + (quadNdx + 1) * 6));
1081 
1082 				if (isSmallerThan8BitFormat(tcuColorFormat.type))
1083 					refRenderer8.draw(renderState,
1084 									  rr::PRIMITIVETYPE_TRIANGLES,
1085 									  std::vector<Vertex4RGBA>(m_vertices.begin() + quadNdx * 6,
1086 									  m_vertices.begin() + (quadNdx + 1) * 6));
1087 			}
1088 		}
1089 	}
1090 
1091 	// Compare result with reference image
1092 	{
1093 		const DeviceInterface&				vk							= m_context.getDeviceInterface();
1094 		const VkDevice						vkDevice					= m_context.getDevice();
1095 		const VkQueue						queue						= m_context.getUniversalQueue();
1096 		const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
1097 		SimpleAllocator						allocator					(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1098 		de::UniquePtr<tcu::TextureLevel>	result						(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
1099 		const tcu::Vec4						threshold					(getFormatThreshold(tcuColorFormat));
1100 		tcu::TextureLevel					refLevel;
1101 
1102 		refLevel.setStorage(tcuColorFormat, m_renderSize.x(), m_renderSize.y(), 1);
1103 
1104 		compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1105 											   "FloatImageCompare",
1106 											   "Image comparison",
1107 											   refRenderer.getAccess(),
1108 											   result->getAccess(),
1109 											   threshold,
1110 											   tcu::COMPARE_LOG_RESULT);
1111 
1112 		if (isLegalExpandableFormat(tcuColorFormat.type))
1113 		{
1114 			if (!compareOk && isSmallerThan8BitFormat(tcuColorFormat.type))
1115 			{
1116 				// Convert to target format
1117 				tcu::copy(refLevel.getAccess(), refRenderer8.getAccess());
1118 
1119 				compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1120 													   "FloatImageCompare",
1121 													   "Image comparison, 8 bit intermediate format",
1122 													   refLevel.getAccess(),
1123 													   result->getAccess(),
1124 													   threshold,
1125 													   tcu::COMPARE_LOG_RESULT);
1126 			}
1127 
1128 			if (!compareOk)
1129 			{
1130 				// Convert to target format
1131 				tcu::copy(refLevel.getAccess(), refRenderer64.getAccess());
1132 
1133 				compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1134 													   "FloatImageCompare",
1135 													   "Image comparison, 64 bit intermediate format",
1136 													   refLevel.getAccess(),
1137 													   result->getAccess(),
1138 													   threshold,
1139 													   tcu::COMPARE_LOG_RESULT);
1140 			}
1141 		}
1142 	}
1143 
1144 	if (compareOk)
1145 		return tcu::TestStatus::pass("Result image matches reference");
1146 	else
1147 		return tcu::TestStatus::fail("Image mismatch");
1148 }
1149 
1150 // DualSourceBlendTestInstance
1151 
DualSourceBlendTestInstance(Context & context,const VkFormat colorFormat,const VkPipelineColorBlendAttachmentState blendStates[DualSourceBlendTest::QUAD_COUNT])1152 DualSourceBlendTestInstance::DualSourceBlendTestInstance (Context&									context,
1153 														  const VkFormat							colorFormat,
1154 														  const VkPipelineColorBlendAttachmentState	blendStates[DualSourceBlendTest::QUAD_COUNT])
1155 	: vkt::TestInstance	(context)
1156 	, m_renderSize		(32, 32)
1157 	, m_colorFormat		(colorFormat)
1158 {
1159 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
1160 	const VkDevice				vkDevice			= m_context.getDevice();
1161 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1162 	SimpleAllocator				memAlloc			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1163 
1164 	// Copy depth operators
1165 	deMemcpy(m_blendStates, blendStates, sizeof(VkPipelineColorBlendAttachmentState) * DualSourceBlendTest::QUAD_COUNT);
1166 
1167 	// Create color image
1168 	{
1169 		const VkImageCreateInfo	colorImageParams =
1170 		{
1171 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
1172 			DE_NULL,																	// const void*				pNext;
1173 			0u,																			// VkImageCreateFlags		flags;
1174 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
1175 			m_colorFormat,																// VkFormat					format;
1176 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
1177 			1u,																			// deUint32					mipLevels;
1178 			1u,																			// deUint32					arrayLayers;
1179 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
1180 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
1181 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
1182 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
1183 			1u,																			// deUint32					queueFamilyIndexCount;
1184 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
1185 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
1186 		};
1187 
1188 		m_colorImageCreateInfo	= colorImageParams;
1189 		m_colorImage			= createImage(vk, vkDevice, &m_colorImageCreateInfo);
1190 
1191 		// Allocate and bind color image memory
1192 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
1193 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
1194 	}
1195 
1196 	// Create color attachment view
1197 	{
1198 		const VkImageViewCreateInfo colorAttachmentViewParams =
1199 		{
1200 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
1201 			DE_NULL,											// const void*				pNext;
1202 			0u,													// VkImageViewCreateFlags	flags;
1203 			*m_colorImage,										// VkImage					image;
1204 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
1205 			m_colorFormat,										// VkFormat					format;
1206 			{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY},
1207 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
1208 		};
1209 
1210 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
1211 	}
1212 
1213 	// Create render pass
1214 	m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat);
1215 
1216 	// Create framebuffer
1217 	{
1218 		const VkFramebufferCreateInfo framebufferParams =
1219 		{
1220 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
1221 			DE_NULL,											// const void*				pNext;
1222 			0u,													// VkFramebufferCreateFlags	flags;
1223 			*m_renderPass,										// VkRenderPass				renderPass;
1224 			1u,													// deUint32					attachmentCount;
1225 			&m_colorAttachmentView.get(),						// const VkImageView*		pAttachments;
1226 			(deUint32)m_renderSize.x(),							// deUint32					width;
1227 			(deUint32)m_renderSize.y(),							// deUint32					height;
1228 			1u													// deUint32					layers;
1229 		};
1230 
1231 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
1232 	}
1233 
1234 	// Create pipeline layout
1235 	{
1236 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1237 		{
1238 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
1239 			DE_NULL,											// const void*						pNext;
1240 			0u,													// VkPipelineLayoutCreateFlags		flags;
1241 			0u,													// deUint32							setLayoutCount;
1242 			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
1243 			0u,													// deUint32							pushConstantRangeCount;
1244 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
1245 		};
1246 
1247 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1248 	}
1249 
1250 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
1251 	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
1252 
1253 	// Create pipeline
1254 	{
1255 		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
1256 		{
1257 			0u,									// deUint32					binding;
1258 			sizeof(Vertex4RGBARGBA),			// deUint32					strideInBytes;
1259 			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	inputRate;
1260 		};
1261 
1262 		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[3]	=
1263 		{
1264 			{
1265 				0u,								// deUint32	location;
1266 				0u,								// deUint32	binding;
1267 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
1268 				0u								// deUint32	offset;
1269 			},
1270 			{
1271 				1u,								// deUint32	location;
1272 				0u,								// deUint32	binding;
1273 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
1274 				(deUint32)(sizeof(float) * 4),	// deUint32	offset;
1275 			},
1276 			{
1277 				2u,								// deUint32	location;
1278 				0u,								// deUint32	binding;
1279 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
1280 				(deUint32)(sizeof(float) * 8),	// deUint32	offset;
1281 			}
1282 		};
1283 
1284 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
1285 		{
1286 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
1287 			DE_NULL,														// const void*								pNext;
1288 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
1289 			1u,																// deUint32									vertexBindingDescriptionCount;
1290 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1291 			3u,																// deUint32									vertexAttributeDescriptionCount;
1292 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1293 		};
1294 
1295 		const std::vector<VkViewport>				viewports							(1, makeViewport(m_renderSize));
1296 		const std::vector<VkRect2D>					scissors							(1, makeRect2D(m_renderSize));
1297 
1298 		// The color blend attachment will be set up before creating the graphics pipeline.
1299 		VkPipelineColorBlendStateCreateInfo			colorBlendStateParams				=
1300 		{
1301 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1302 			DE_NULL,													// const void*									pNext;
1303 			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
1304 			false,														// VkBool32										logicOpEnable;
1305 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1306 			0u,															// deUint32										attachmentCount;
1307 			DE_NULL,													// const VkPipelineColorBlendAttachmentState*	pAttachments;
1308 			{															// float										blendConstants[4];
1309 				DualSourceBlendTest::s_blendConst.x(),
1310 				DualSourceBlendTest::s_blendConst.y(),
1311 				DualSourceBlendTest::s_blendConst.z(),
1312 				DualSourceBlendTest::s_blendConst.w()
1313 			}
1314 		};
1315 
1316 		for (int quadNdx = 0; quadNdx < DualSourceBlendTest::QUAD_COUNT; quadNdx++)
1317 		{
1318 			colorBlendStateParams.attachmentCount	= 1u;
1319 			colorBlendStateParams.pAttachments		= &m_blendStates[quadNdx];
1320 			m_graphicsPipelines[quadNdx]			= makeGraphicsPipeline(vk,									// const DeviceInterface&                        vk
1321 																		   vkDevice,							// const VkDevice                                device
1322 																		   *m_pipelineLayout,					// const VkPipelineLayout                        pipelineLayout
1323 																		   *m_vertexShaderModule,				// const VkShaderModule                          vertexShaderModule
1324 																		   DE_NULL,								// const VkShaderModule                          tessellationControlModule
1325 																		   DE_NULL,								// const VkShaderModule                          tessellationEvalModule
1326 																		   DE_NULL,								// const VkShaderModule                          geometryShaderModule
1327 																		   *m_fragmentShaderModule,				// const VkShaderModule                          fragmentShaderModule
1328 																		   *m_renderPass,						// const VkRenderPass                            renderPass
1329 																		   viewports,							// const std::vector<VkViewport>&                viewports
1330 																		   scissors,							// const std::vector<VkRect2D>&                  scissors
1331 																		   VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
1332 																		   0u,									// const deUint32                                subpass
1333 																		   0u,									// const deUint32                                patchControlPoints
1334 																		   &vertexInputStateParams,				// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
1335 																		   DE_NULL,								// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1336 																		   DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
1337 																		   DE_NULL,								// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
1338 																		   &colorBlendStateParams);				// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
1339 		}
1340 	}
1341 
1342 	// Create vertex buffer
1343 	{
1344 		const VkBufferCreateInfo vertexBufferParams =
1345 		{
1346 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1347 			DE_NULL,									// const void*			pNext;
1348 			0u,											// VkBufferCreateFlags	flags;
1349 			1152u,										// VkDeviceSize			size;
1350 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
1351 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1352 			1u,											// deUint32				queueFamilyIndexCount;
1353 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
1354 		};
1355 
1356 		m_vertices			= createOverlappingQuadsDualSource();
1357 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
1358 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
1359 
1360 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
1361 
1362 		// Adjust vertex colors
1363 		if (!isFloatFormat(m_colorFormat))
1364 		{
1365 			const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(mapVkFormat(m_colorFormat));
1366 			for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
1367 			{
1368 				m_vertices[vertexNdx].color0 = (m_vertices[vertexNdx].color0 - formatInfo.lookupBias) / formatInfo.lookupScale;
1369 				m_vertices[vertexNdx].color1 = (m_vertices[vertexNdx].color1 - formatInfo.lookupBias) / formatInfo.lookupScale;
1370 			}
1371 		}
1372 
1373 		// Upload vertex data
1374 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBARGBA));
1375 
1376 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
1377 	}
1378 
1379 	// Create command pool
1380 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1381 
1382 	// Create command buffer
1383 	{
1384 		const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
1385 
1386 		// Color image layout transition
1387 		const VkImageMemoryBarrier imageLayoutBarrier =
1388 		{
1389 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
1390 			DE_NULL,																// const void*                pNext;
1391 			(VkAccessFlags)0,														// VkAccessFlags              srcAccessMask;
1392 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,									// VkAccessFlags              dstAccessMask;
1393 			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
1394 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,								// VkImageLayout              newLayout;
1395 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
1396 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
1397 			*m_colorImage,															// VkImage                    image;
1398 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }							// VkImageSubresourceRange    subresourceRange;
1399 		};
1400 
1401 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1402 
1403 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1404 
1405 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
1406 			0u, DE_NULL, 0u, DE_NULL, 1u, &imageLayoutBarrier);
1407 
1408 		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
1409 
1410 		const VkDeviceSize quadOffset = (m_vertices.size() / DualSourceBlendTest::QUAD_COUNT) * sizeof(Vertex4RGBARGBA);
1411 
1412 		for (int quadNdx = 0; quadNdx < DualSourceBlendTest::QUAD_COUNT; quadNdx++)
1413 		{
1414 			VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
1415 
1416 			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]);
1417 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1418 			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / DualSourceBlendTest::QUAD_COUNT), 1, 0, 0);
1419 		}
1420 
1421 		endRenderPass(vk, *m_cmdBuffer);
1422 		endCommandBuffer(vk, *m_cmdBuffer);
1423 	}
1424 }
1425 
~DualSourceBlendTestInstance(void)1426 DualSourceBlendTestInstance::~DualSourceBlendTestInstance (void)
1427 {
1428 }
1429 
iterate(void)1430 tcu::TestStatus DualSourceBlendTestInstance::iterate (void)
1431 {
1432 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1433 	const VkDevice				vkDevice	= m_context.getDevice();
1434 	const VkQueue				queue		= m_context.getUniversalQueue();
1435 
1436 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1437 
1438 	return verifyImage();
1439 }
1440 
verifyImage(void)1441 tcu::TestStatus DualSourceBlendTestInstance::verifyImage (void)
1442 {
1443 	const tcu::TextureFormat			tcuColorFormat		= mapVkFormat(m_colorFormat);
1444 	const tcu::TextureFormat			tcuColorFormat64	= mapVkFormat(VK_FORMAT_R64G64B64A64_SFLOAT);
1445 	const tcu::TextureFormat			tcuColorFormat8		= mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
1446 	const tcu::TextureFormat			tcuDepthFormat		= tcu::TextureFormat(); // Undefined depth/stencil format
1447 	const ColorVertexShaderDualSource	vertexShader;
1448 	const ColorFragmentShaderDualSource	fragmentShader		(tcuColorFormat, tcuDepthFormat);
1449 	const rr::Program					program				(&vertexShader, &fragmentShader);
1450 	ReferenceRenderer					refRenderer			(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
1451 	ReferenceRenderer					refRenderer64		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat64, tcuDepthFormat, &program);
1452 	ReferenceRenderer					refRenderer8		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat8, tcuDepthFormat, &program);
1453 	bool								compareOk			= false;
1454 
1455 	// Render reference image
1456 	{
1457 		for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
1458 		{
1459 			const VkPipelineColorBlendAttachmentState& blendState = m_blendStates[quadNdx];
1460 
1461 			// Set blend state
1462 			rr::RenderState renderState					(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1463 			renderState.fragOps.blendMode				= rr::BLENDMODE_STANDARD;
1464 			renderState.fragOps.blendRGBState.srcFunc	= mapVkBlendFactor(blendState.srcColorBlendFactor);
1465 			renderState.fragOps.blendRGBState.dstFunc	= mapVkBlendFactor(blendState.dstColorBlendFactor);
1466 			renderState.fragOps.blendRGBState.equation	= mapVkBlendOp(blendState.colorBlendOp);
1467 			renderState.fragOps.blendAState.srcFunc		= mapVkBlendFactor(blendState.srcAlphaBlendFactor);
1468 			renderState.fragOps.blendAState.dstFunc		= mapVkBlendFactor(blendState.dstAlphaBlendFactor);
1469 			renderState.fragOps.blendAState.equation	= mapVkBlendOp(blendState.alphaBlendOp);
1470 			renderState.fragOps.blendColor				= DualSourceBlendTest::s_blendConst;
1471 			renderState.fragOps.colorMask				= mapVkColorComponentFlags(DualSourceBlendTest::s_colorWriteMasks[quadNdx]);
1472 
1473 			refRenderer.draw(renderState,
1474 							rr::PRIMITIVETYPE_TRIANGLES,
1475 							std::vector<Vertex4RGBARGBA>(m_vertices.begin() + quadNdx * 6,
1476 													 m_vertices.begin() + (quadNdx + 1) * 6));
1477 
1478 			if (isLegalExpandableFormat(tcuColorFormat.type))
1479 			{
1480 				refRenderer64.draw(renderState,
1481 								   rr::PRIMITIVETYPE_TRIANGLES,
1482 								   std::vector<Vertex4RGBARGBA>(m_vertices.begin() + quadNdx * 6,
1483 								   m_vertices.begin() + (quadNdx + 1) * 6));
1484 
1485 				if (isSmallerThan8BitFormat(tcuColorFormat.type))
1486 					refRenderer8.draw(renderState,
1487 									  rr::PRIMITIVETYPE_TRIANGLES,
1488 									  std::vector<Vertex4RGBARGBA>(m_vertices.begin() + quadNdx * 6,
1489 									  m_vertices.begin() + (quadNdx + 1) * 6));
1490 			}
1491 		}
1492 	}
1493 
1494 	// Compare result with reference image
1495 	{
1496 		const DeviceInterface&				vk							= m_context.getDeviceInterface();
1497 		const VkDevice						vkDevice					= m_context.getDevice();
1498 		const VkQueue						queue						= m_context.getUniversalQueue();
1499 		const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
1500 		SimpleAllocator						allocator					(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1501 		de::UniquePtr<tcu::TextureLevel>	result						(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
1502 		tcu::Vec4							threshold					(getFormatThreshold(tcuColorFormat));
1503 		tcu::TextureLevel					refLevel;
1504 
1505 		// For SRGB formats there is an extra precision loss due to doing
1506 		// the following conversions sRGB -> RGB -> blend -> RGB  -> sRGB with floats.
1507 		// Take that into account in the threshold. For example, VK_FORMAT_R8G8B8A8_SRGB
1508 		// threshold is 4/255f, but we changed it to be 10/255f.
1509 		if (tcu::isSRGB(tcuColorFormat))
1510 			threshold = 2.5f * threshold;
1511 
1512 		refLevel.setStorage(tcuColorFormat, m_renderSize.x(), m_renderSize.y(), 1);
1513 
1514 		compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1515 											   "FloatImageCompare",
1516 											   "Image comparison",
1517 											   refRenderer.getAccess(),
1518 											   result->getAccess(),
1519 											   threshold,
1520 											   tcu::COMPARE_LOG_RESULT);
1521 
1522 		if (isLegalExpandableFormat(tcuColorFormat.type))
1523 		{
1524 			if (!compareOk && isSmallerThan8BitFormat(tcuColorFormat.type))
1525 			{
1526 				// Convert to target format
1527 				tcu::copy(refLevel.getAccess(), refRenderer8.getAccess());
1528 
1529 				compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1530 													   "FloatImageCompare",
1531 													   "Image comparison, 8 bit intermediate format",
1532 													   refLevel.getAccess(),
1533 													   result->getAccess(),
1534 													   threshold,
1535 													   tcu::COMPARE_LOG_RESULT);
1536 			}
1537 
1538 			if (!compareOk)
1539 			{
1540 				// Convert to target format
1541 				tcu::copy(refLevel.getAccess(), refRenderer64.getAccess());
1542 
1543 				compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1544 													   "FloatImageCompare",
1545 													   "Image comparison, 64 bit intermediate format",
1546 													   refLevel.getAccess(),
1547 													   result->getAccess(),
1548 													   threshold,
1549 													   tcu::COMPARE_LOG_RESULT);
1550 			}
1551 		}
1552 	}
1553 
1554 	if (compareOk)
1555 		return tcu::TestStatus::pass("Result image matches reference");
1556 	else
1557 		return tcu::TestStatus::fail("Image mismatch");
1558 }
1559 
1560 // Clamping tests for colors and constants.
1561 
1562 struct ClampTestParams
1563 {
1564 	vk::VkFormat	colorFormat;
1565 	tcu::Vec4		quadColor;
1566 	tcu::Vec4		blendConstants;
1567 };
1568 
1569 class ClampTest : public vkt::TestCase
1570 {
1571 public:
1572 										ClampTest				(tcu::TestContext&							testContext,
1573 																 const std::string&							name,
1574 																 const std::string&							description,
1575 																 const ClampTestParams&						testParams);
~ClampTest(void)1576 	virtual								~ClampTest				(void) {}
1577 	virtual void						initPrograms			(SourceCollections& sourceCollections) const;
1578 	virtual void						checkSupport			(Context& context) const;
1579 	virtual TestInstance*				createInstance			(Context& context) const;
1580 
1581 private:
1582 	const ClampTestParams				m_params;
1583 };
1584 
1585 class ClampTestInstance : public vkt::TestInstance
1586 {
1587 public:
ClampTestInstance(Context & context,const ClampTestParams & testParams)1588 								ClampTestInstance		(Context& context, const ClampTestParams& testParams)
1589 									: vkt::TestInstance(context), m_params(testParams)
1590 									{}
~ClampTestInstance(void)1591 	virtual						~ClampTestInstance		(void) {}
1592 	virtual tcu::TestStatus		iterate					(void);
1593 
1594 private:
1595 	const ClampTestParams		m_params;
1596 };
1597 
ClampTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const ClampTestParams & testParams)1598 ClampTest::ClampTest (tcu::TestContext&			testContext,
1599 					  const std::string&		name,
1600 					  const std::string&		description,
1601 					  const ClampTestParams&	testParams)
1602 	: vkt::TestCase (testContext, name, description)
1603 	, m_params(testParams)
1604 {
1605 	// As per the spec:
1606 	//
1607 	//  If the color attachment is fixed-point, the components of the source and destination values and blend factors are each
1608 	//  clamped to [0,1] or [-1,1] respectively for an unsigned normalized or signed normalized color attachment prior to evaluating
1609 	//  the blend operations. If the color attachment is floating-point, no clamping occurs.
1610 	//
1611 	// We will only test signed and unsigned normalized formats, and avoid precision problems by having all channels have the same
1612 	// bit depth.
1613 	//
1614 	DE_ASSERT(isSnormFormat(m_params.colorFormat) || isUnormFormat(m_params.colorFormat));
1615 
1616 	const auto bitDepth = tcu::getTextureFormatBitDepth(mapVkFormat(m_params.colorFormat));
1617 	DE_UNREF(bitDepth); // For release builds.
1618 	DE_ASSERT(bitDepth[0] == bitDepth[1] && bitDepth[0] == bitDepth[2] && bitDepth[0] == bitDepth[3]);
1619 }
1620 
initPrograms(SourceCollections & sourceCollections) const1621 void ClampTest::initPrograms (SourceCollections& sourceCollections) const
1622 {
1623 	std::ostringstream fragmentSource;
1624 
1625 	sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
1626 		"#version 310 es\n"
1627 		"layout(location = 0) in highp vec4 position;\n"
1628 		"layout(location = 1) in highp vec4 color;\n"
1629 		"layout(location = 0) out highp vec4 vtxColor;\n"
1630 		"void main (void)\n"
1631 		"{\n"
1632 		"	gl_Position = position;\n"
1633 		"	vtxColor = color;\n"
1634 		"}\n");
1635 
1636 	fragmentSource << "#version 310 es\n"
1637 		"layout(location = 0) in highp vec4 vtxColor;\n"
1638 		"layout(location = 0) out highp vec4 fragColor;\n"
1639 		"void main (void)\n"
1640 		"{\n"
1641 		"	fragColor = vtxColor;\n"
1642 		"}\n";
1643 
1644 	sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
1645 }
1646 
checkSupport(Context & context) const1647 void ClampTest::checkSupport (Context& context) const
1648 {
1649 	if (!isSupportedBlendFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.colorFormat))
1650 		throw tcu::NotSupportedError(std::string("Unsupported color blending format: ") + getFormatName(m_params.colorFormat));
1651 }
1652 
createInstance(Context & context) const1653 TestInstance* ClampTest::createInstance(Context& context) const
1654 {
1655 	return new ClampTestInstance(context, m_params);
1656 }
1657 
iterate(void)1658 tcu::TestStatus ClampTestInstance::iterate (void)
1659 {
1660 	const vk::DeviceInterface&	vkd					= m_context.getDeviceInterface();
1661 	const vk::VkDevice			device				= m_context.getDevice();
1662 	vk::Allocator&				allocator			= m_context.getDefaultAllocator();
1663 	const vk::VkQueue			queue				= m_context.getUniversalQueue();
1664 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1665 	const vk::VkExtent3D		renderSize			= { 32u, 32u, 1u };
1666 
1667 	// Image.
1668 	const vk::VkImageCreateInfo	imageCreateInfo =
1669 	{
1670 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
1671 		nullptr,																		// const void*				pNext;
1672 		0u,																				// VkImageCreateFlags		flags;
1673 		vk::VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
1674 		m_params.colorFormat,															// VkFormat					format;
1675 		renderSize,																		// VkExtent3D				extent;
1676 		1u,																				// deUint32					mipLevels;
1677 		1u,																				// deUint32					arrayLayers;
1678 		vk::VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
1679 		vk::VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
1680 		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage;
1681 		vk::VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
1682 		1u,																				// deUint32					queueFamilyIndexCount;
1683 		&queueFamilyIndex,																// const deUint32*			pQueueFamilyIndices;
1684 		vk::VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			initialLayout;
1685 	};
1686 
1687 	vk::ImageWithMemory colorImage (vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any);
1688 
1689 	// Image view.
1690 	const vk::VkImageViewCreateInfo imageViewCreateInfo =
1691 	{
1692 		vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
1693 		nullptr,											// const void*				pNext;
1694 		0u,													// VkImageViewCreateFlags	flags;
1695 		colorImage.get(),									// VkImage					image;
1696 		vk::VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
1697 		m_params.colorFormat,								// VkFormat					format;
1698 		{													// VkComponentMapping		components;
1699 			vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1700 			vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1701 			vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1702 			vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1703 		},
1704 		{ vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
1705 	};
1706 
1707 	auto colorImageView = createImageView(vkd, device, &imageViewCreateInfo);
1708 
1709 	// Render pass.
1710 	auto renderPass = makeRenderPass(vkd, device, m_params.colorFormat);
1711 
1712 	// Frame buffer.
1713 	const vk::VkFramebufferCreateInfo framebufferParams =
1714 	{
1715 		vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType			sType;
1716 		nullptr,											// const void*				pNext;
1717 		0u,													// VkFramebufferCreateFlags	flags;
1718 		renderPass.get(),									// VkRenderPass				renderPass;
1719 		1u,													// deUint32					attachmentCount;
1720 		&colorImageView.get(),								// const VkImageView*		pAttachments;
1721 		renderSize.width,									// deUint32					width;
1722 		renderSize.height,									// deUint32					height;
1723 		1u,													// deUint32					layers;
1724 	};
1725 
1726 	auto framebuffer = createFramebuffer(vkd, device, &framebufferParams);
1727 
1728 	// Pipeline layout.
1729 	const vk::VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1730 	{
1731 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType					sType;
1732 		nullptr,											// const void*						pNext;
1733 		0u,													// VkPipelineLayoutCreateFlags		flags;
1734 		0u,													// deUint32							setLayoutCount;
1735 		nullptr,											// const VkDescriptorSetLayout*		pSetLayouts;
1736 		0u,													// deUint32							pushConstantRangeCount;
1737 		nullptr,											// const VkPushConstantRange*		pPushConstantRanges;
1738 	};
1739 
1740 	auto pipelineLayout = createPipelineLayout(vkd, device, &pipelineLayoutCreateInfo);
1741 
1742 	// Shader modules.
1743 	auto vertexShaderModule		= createShaderModule(vkd, device, m_context.getBinaryCollection().get("color_vert"), 0);
1744 	auto fragmentShaderModule	= createShaderModule(vkd, device, m_context.getBinaryCollection().get("color_frag"), 0);
1745 
1746 	// Graphics pipeline.
1747 	const vk::VkVertexInputBindingDescription vertexInputBindingDescription =
1748 	{
1749 		0u,									// deUint32					binding;
1750 		sizeof(Vertex4RGBA),				// deUint32					strideInBytes;
1751 		vk::VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputStepRate	inputRate;
1752 	};
1753 
1754 	const vk::VkVertexInputAttributeDescription	vertexInputAttributeDescriptions[2]	=
1755 	{
1756 		{
1757 			0u,									// deUint32	location;
1758 			0u,									// deUint32	binding;
1759 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
1760 			0u									// deUint32	offset;
1761 		},
1762 		{
1763 			1u,														// deUint32	location;
1764 			0u,														// deUint32	binding;
1765 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,						// VkFormat	format;
1766 			static_cast<deUint32>(offsetof(Vertex4RGBA, color)),	// deUint32	offset;
1767 		},
1768 	};
1769 
1770 	const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1771 	{
1772 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,					// VkStructureType							sType;
1773 		nullptr,																		// const void*								pNext;
1774 		0u,																				// VkPipelineVertexInputStateCreateFlags	flags;
1775 		1u,																				// deUint32									vertexBindingDescriptionCount;
1776 		&vertexInputBindingDescription,													// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1777 		static_cast<deUint32>(DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions)),	// deUint32									vertexAttributeDescriptionCount;
1778 		vertexInputAttributeDescriptions,												// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1779 	};
1780 
1781 	const std::vector<vk::VkViewport>	viewports	(1, makeViewport(renderSize));
1782 	const std::vector<vk::VkRect2D>		scissors	(1, makeRect2D(renderSize));
1783 
1784 	const vk::VkColorComponentFlags colorComponentFlags = (0u
1785 		| vk::VK_COLOR_COMPONENT_R_BIT
1786 		| vk::VK_COLOR_COMPONENT_G_BIT
1787 		| vk::VK_COLOR_COMPONENT_B_BIT
1788 		| vk::VK_COLOR_COMPONENT_A_BIT
1789 	);
1790 
1791 	// Color blend attachment state. Central aspect of the test.
1792 	const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1793 	{
1794 		VK_TRUE,							// VkBool32					blendEnable;
1795 		vk::VK_BLEND_FACTOR_CONSTANT_COLOR,	// VkBlendFactor			srcColorBlendFactor;
1796 		vk::VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstColorBlendFactor;
1797 		vk::VK_BLEND_OP_ADD,				// VkBlendOp				colorBlendOp;
1798 		vk::VK_BLEND_FACTOR_CONSTANT_ALPHA,	// VkBlendFactor			srcAlphaBlendFactor;
1799 		vk::VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstAlphaBlendFactor;
1800 		vk::VK_BLEND_OP_ADD,				// VkBlendOp				alphaBlendOp;
1801 		colorComponentFlags,				// VkColorComponentFlags	colorWriteMask;
1802 	};
1803 
1804 	const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1805 	{
1806 		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1807 		nullptr,														// const void*									pNext;
1808 		0u,																// VkPipelineColorBlendStateCreateFlags			flags;
1809 		false,															// VkBool32										logicOpEnable;
1810 		vk::VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1811 		1u,																// deUint32										attachmentCount;
1812 		&colorBlendAttachmentState,										// const VkPipelineColorBlendAttachmentState*	pAttachments;
1813 		{																// float										blendConstants[4];
1814 			m_params.blendConstants[0],
1815 			m_params.blendConstants[1],
1816 			m_params.blendConstants[2],
1817 			m_params.blendConstants[3],
1818 		},
1819 	};
1820 
1821 	auto graphicsPipeline = makeGraphicsPipeline(
1822 		vkd,										// const DeviceInterface&                        vk
1823 		device,										// const VkDevice                                device
1824 		pipelineLayout.get(),						// const VkPipelineLayout                        pipelineLayout
1825 		vertexShaderModule.get(),					// const VkShaderModule                          vertexShaderModule
1826 		DE_NULL,									// const VkShaderModule                          tessellationControlModule
1827 		DE_NULL,									// const VkShaderModule                          tessellationEvalModule
1828 		DE_NULL,									// const VkShaderModule                          geometryShaderModule
1829 		fragmentShaderModule.get(),					// const VkShaderModule                          fragmentShaderModule
1830 		renderPass.get(),							// const VkRenderPass                            renderPass
1831 		viewports,									// const std::vector<VkViewport>&                viewports
1832 		scissors,									// const std::vector<VkRect2D>&                  scissors
1833 		vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
1834 		0u,											// const deUint32                                subpass
1835 		0u,											// const deUint32                                patchControlPoints
1836 		&vertexInputStateParams,					// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
1837 		nullptr,									// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1838 		nullptr,									// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
1839 		nullptr,									// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
1840 		&colorBlendStateParams);					// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
1841 
1842 	// Vertex buffer
1843 	auto						quadTexture = createFullscreenQuad();
1844 	std::vector<Vertex4RGBA>	vertices;
1845 
1846 	// Keep position but replace texture coordinates with our own color.
1847 	vertices.reserve(quadTexture.size());
1848 	std::transform(begin(quadTexture), end(quadTexture), std::back_inserter(vertices),
1849 		[this](const decltype(quadTexture)::value_type& v) { return Vertex4RGBA{ v.position, this->m_params.quadColor }; });
1850 
1851 	const vk::VkDeviceSize			vtxBufferSize		= static_cast<vk::VkDeviceSize>(vertices.size() * sizeof(decltype(vertices)::value_type));
1852 	const vk::VkBufferCreateInfo	bufferCreateInfo	=
1853 	{
1854 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
1855 		nullptr,									// const void*			pNext;
1856 		0u,											// VkBufferCreateFlags	flags;
1857 		vtxBufferSize,								// VkDeviceSize			size;
1858 		vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,		// VkBufferUsageFlags	usage;
1859 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
1860 		1u,											// deUint32				queueFamilyIndexCount;
1861 		&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
1862 	};
1863 
1864 	vk::BufferWithMemory vertexBuffer(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible);
1865 
1866 	// Upload vertex data
1867 	deMemcpy(vertexBuffer.getAllocation().getHostPtr(), vertices.data(), static_cast<size_t>(vtxBufferSize));
1868 	flushAlloc(vkd, device, vertexBuffer.getAllocation());
1869 
1870 	// Create command pool
1871 	auto cmdPool = createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1872 
1873 	// Create and record command buffer
1874 	auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1875 	auto cmdBuffer		= cmdBufferPtr.get();
1876 
1877 	vk::VkClearValue clearValue;
1878 	clearValue.color.float32[0] = 0.0f;
1879 	clearValue.color.float32[1] = 0.0f;
1880 	clearValue.color.float32[2] = 0.0f;
1881 	clearValue.color.float32[3] = 1.0f;
1882 
1883 	const vk::VkDeviceSize vertexOffets[] = { 0u };
1884 
1885 	beginCommandBuffer(vkd, cmdBuffer, 0u);
1886 		beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), makeRect2D(renderSize), clearValue);
1887 			vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.get());
1888 			vkd.cmdBindVertexBuffers(cmdBuffer, 0, 1u, &vertexBuffer.get(), vertexOffets);
1889 			vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(vertices.size()), 1, 0, 0);
1890 		endRenderPass(vkd, cmdBuffer);
1891 	endCommandBuffer(vkd, cmdBuffer);
1892 
1893 	// Submit commands.
1894 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1895 
1896 	// Calculate reference final color.
1897 	const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_params.colorFormat);
1898 	const auto					formatInfo		= tcu::getTextureFormatInfo(tcuColorFormat);
1899 
1900 	tcu::Vec4 clampedBlendConstants	= m_params.blendConstants;
1901 	tcu::Vec4 clampedQuadColor		= m_params.quadColor;
1902 
1903 	for (int i = 0; i < tcu::Vec4::SIZE; ++i)
1904 	{
1905 		clampedBlendConstants[i]	= de::clamp(clampedBlendConstants[i],	formatInfo.valueMin[i], formatInfo.valueMax[i]);
1906 		clampedQuadColor[i]			= de::clamp(clampedQuadColor[i],		formatInfo.valueMin[i], formatInfo.valueMax[i]);
1907 	}
1908 
1909 	tcu::Vec4 referenceColor;
1910 	for (int i = 0; i < tcu::Vec4::SIZE; ++i)
1911 		referenceColor[i] = clampedBlendConstants[i] * clampedQuadColor[i];
1912 
1913 	// Compare result with reference color
1914 	const tcu::UVec2					renderSizeUV2		(renderSize.width, renderSize.height);
1915 	de::UniquePtr<tcu::TextureLevel>	result				(readColorAttachment(vkd, device, queue, queueFamilyIndex, allocator, colorImage.get(), m_params.colorFormat, renderSizeUV2).release());
1916 	const tcu::Vec4						threshold			(getFormatThreshold(tcuColorFormat));
1917 	const tcu::ConstPixelBufferAccess	pixelBufferAccess	= result->getAccess();
1918 
1919 	const bool compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "BlendClampCompare", "Blend clamping pixel comparison", referenceColor, pixelBufferAccess, threshold, tcu::COMPARE_LOG_ON_ERROR);
1920 
1921 	if (compareOk)
1922 		return tcu::TestStatus::pass("Pass");
1923 	else
1924 		return tcu::TestStatus::fail("Pixel mismatch");
1925 }
1926 
1927 } // anonymous
1928 
getBlendStateName(const VkPipelineColorBlendAttachmentState & blendState)1929 std::string getBlendStateName (const VkPipelineColorBlendAttachmentState& blendState)
1930 {
1931 	const char* shortBlendFactorNames[] =
1932 	{
1933 		"z",		// VK_BLEND_ZERO
1934 		"o",		// VK_BLEND_ONE
1935 		"sc",		// VK_BLEND_SRC_COLOR
1936 		"1msc",		// VK_BLEND_ONE_MINUS_SRC_COLOR
1937 		"dc",		// VK_BLEND_DEST_COLOR
1938 		"1mdc",		// VK_BLEND_ONE_MINUS_DEST_COLOR
1939 		"sa",		// VK_BLEND_SRC_ALPHA
1940 		"1msa",		// VK_BLEND_ONE_MINUS_SRC_ALPHA
1941 		"da",		// VK_BLEND_DEST_ALPHA
1942 		"1mda",		// VK_BLEND_ONE_MINUS_DEST_ALPHA
1943 		"cc",		// VK_BLEND_CONSTANT_COLOR
1944 		"1mcc",		// VK_BLEND_ONE_MINUS_CONSTANT_COLOR
1945 		"ca",		// VK_BLEND_CONSTANT_ALPHA
1946 		"1mca",		// VK_BLEND_ONE_MINUS_CONSTANT_ALPHA
1947 		"sas",		// VK_BLEND_SRC_ALPHA_SATURATE
1948 		"1ms1c",	// VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR
1949 		"1ms1a",	// VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA
1950 		"s1c",		// VK_BLEND_FACTOR_SRC1_COLOR
1951 		"s1a"		// VK_BLEND_FACTOR_SRC1_ALPHA
1952 	};
1953 
1954 	const char* blendOpNames[] =
1955 	{
1956 		"add",		// VK_BLEND_OP_ADD
1957 		"sub",		// VK_BLEND_OP_SUBTRACT
1958 		"rsub",		// VK_BLEND_OP_REVERSE_SUBTRACT
1959 		"min",		// VK_BLEND_OP_MIN
1960 		"max",		// VK_BLEND_OP_MAX
1961 	};
1962 
1963 	std::ostringstream shortName;
1964 
1965 	shortName << "color_" << shortBlendFactorNames[blendState.srcColorBlendFactor] << "_" << shortBlendFactorNames[blendState.dstColorBlendFactor] << "_" << blendOpNames[blendState.colorBlendOp];
1966 	shortName << "_alpha_" << shortBlendFactorNames[blendState.srcAlphaBlendFactor] << "_" << shortBlendFactorNames[blendState.dstAlphaBlendFactor] << "_" << blendOpNames[blendState.alphaBlendOp];
1967 
1968 	return shortName.str();
1969 }
1970 
getBlendStateSetName(const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])1971 std::string getBlendStateSetName (const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])
1972 {
1973 	std::ostringstream name;
1974 
1975 	for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
1976 	{
1977 		name << getBlendStateName(blendStates[quadNdx]);
1978 
1979 		if (quadNdx < BlendTest::QUAD_COUNT - 1)
1980 			name << "-";
1981 	}
1982 
1983 	return name.str();
1984 }
1985 
getBlendStateSetDescription(const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])1986 std::string getBlendStateSetDescription (const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])
1987 {
1988 	std::ostringstream description;
1989 
1990 	description << "Draws " << BlendTest::QUAD_COUNT << " quads with the following blend states:\n";
1991 
1992 	for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
1993 		description << blendStates[quadNdx] << "\n";
1994 
1995 	return description.str();
1996 }
1997 
getFormatCaseName(VkFormat format)1998 std::string getFormatCaseName (VkFormat format)
1999 {
2000 	const std::string fullName = getFormatName(format);
2001 
2002 	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
2003 
2004 	return de::toLower(fullName.substr(10));
2005 }
2006 
createBlendTests(tcu::TestContext & testCtx)2007 tcu::TestCaseGroup* createBlendTests (tcu::TestContext& testCtx)
2008 {
2009 	const deUint32 blendStatesPerFormat = 100 * BlendTest::QUAD_COUNT;
2010 
2011 	// Formats that are dEQP-compatible, non-integer and uncompressed
2012 	const VkFormat blendFormats[] =
2013 	{
2014 		VK_FORMAT_R4G4_UNORM_PACK8,
2015 		VK_FORMAT_R4G4B4A4_UNORM_PACK16,
2016 		VK_FORMAT_R5G6B5_UNORM_PACK16,
2017 		VK_FORMAT_R5G5B5A1_UNORM_PACK16,
2018 		VK_FORMAT_A1R5G5B5_UNORM_PACK16,
2019 		VK_FORMAT_R8_UNORM,
2020 		VK_FORMAT_R8_SNORM,
2021 		VK_FORMAT_R8_SRGB,
2022 		VK_FORMAT_R8G8_UNORM,
2023 		VK_FORMAT_R8G8_SNORM,
2024 		VK_FORMAT_R8G8_SRGB,
2025 		VK_FORMAT_R8G8B8_UNORM,
2026 		VK_FORMAT_R8G8B8_SNORM,
2027 		VK_FORMAT_R8G8B8_SRGB,
2028 		VK_FORMAT_R8G8B8A8_UNORM,
2029 		VK_FORMAT_R8G8B8A8_SNORM,
2030 		VK_FORMAT_R8G8B8A8_SRGB,
2031 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
2032 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2033 		VK_FORMAT_R16_UNORM,
2034 		VK_FORMAT_R16_SNORM,
2035 		VK_FORMAT_R16_SFLOAT,
2036 		VK_FORMAT_R16G16_UNORM,
2037 		VK_FORMAT_R16G16_SNORM,
2038 		VK_FORMAT_R16G16_SFLOAT,
2039 		VK_FORMAT_R16G16B16_UNORM,
2040 		VK_FORMAT_R16G16B16_SNORM,
2041 		VK_FORMAT_R16G16B16_SFLOAT,
2042 		VK_FORMAT_R16G16B16A16_UNORM,
2043 		VK_FORMAT_R16G16B16A16_SNORM,
2044 		VK_FORMAT_R16G16B16A16_SFLOAT,
2045 		VK_FORMAT_R32_SFLOAT,
2046 		VK_FORMAT_R32G32_SFLOAT,
2047 		VK_FORMAT_R32G32B32_SFLOAT,
2048 		VK_FORMAT_R32G32B32A32_SFLOAT,
2049 		VK_FORMAT_B10G11R11_UFLOAT_PACK32,
2050 		VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
2051 		VK_FORMAT_B4G4R4A4_UNORM_PACK16,
2052 		VK_FORMAT_B5G5R5A1_UNORM_PACK16,
2053 	};
2054 
2055 	de::MovePtr<tcu::TestCaseGroup>				blendTests				(new tcu::TestCaseGroup(testCtx, "blend", "Blend tests"));
2056 	de::MovePtr<tcu::TestCaseGroup>				formatTests				(new tcu::TestCaseGroup(testCtx, "format", "Uses different blend formats"));
2057 	de::MovePtr<tcu::TestCaseGroup>				clampTests				(new tcu::TestCaseGroup(testCtx, "clamp", "Verifies clamping for normalized formats"));
2058 	de::MovePtr<tcu::TestCaseGroup>				dualSourceBlendTests	(new tcu::TestCaseGroup(testCtx, "dual_source", "Blend tests taking into account dual-source blend factors"));
2059 	de::MovePtr<tcu::TestCaseGroup>				dualSourceFormatTests	(new tcu::TestCaseGroup(testCtx, "format", "Uses different blend formats"));
2060 
2061 
2062 	BlendStateUniqueRandomIterator				blendStateItr			(blendStatesPerFormat, 123);
2063 	BlendStateUniqueRandomIteratorDualSource	dualSourceBlendStateItr	(blendStatesPerFormat, 123);
2064 
2065 	for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(blendFormats); formatNdx++)
2066 	{
2067 		const VkFormat					format			= blendFormats[formatNdx];
2068 
2069 		// Blend tests
2070 		{
2071 			de::MovePtr<tcu::TestCaseGroup>	formatTest		(new tcu::TestCaseGroup(testCtx,
2072 																					getFormatCaseName(format).c_str(),
2073 																					(std::string("Uses format ") + getFormatName(format)).c_str()));
2074 			de::MovePtr<tcu::TestCaseGroup>	blendStateTests;
2075 			{
2076 				std::ostringstream blendStateDescription;
2077 				blendStateDescription << "Combines blend factors, operators and channel write masks. The constant color used in all tests is " << BlendTest::s_blendConst;
2078 				blendStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", blendStateDescription.str().c_str()));
2079 			}
2080 
2081 			blendStateItr.reset();
2082 
2083 			while (blendStateItr.hasNext())
2084 			{
2085 				VkPipelineColorBlendAttachmentState quadBlendConfigs[BlendTest::QUAD_COUNT];
2086 
2087 				for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
2088 				{
2089 					quadBlendConfigs[quadNdx]					= blendStateItr.next();
2090 					quadBlendConfigs[quadNdx].colorWriteMask	= BlendTest::s_colorWriteMasks[quadNdx];
2091 				}
2092 
2093 				blendStateTests->addChild(new BlendTest(testCtx,
2094 														getBlendStateSetName(quadBlendConfigs),
2095 														getBlendStateSetDescription(quadBlendConfigs),
2096 														format,
2097 														quadBlendConfigs));
2098 			}
2099 			formatTest->addChild(blendStateTests.release());
2100 			formatTests->addChild(formatTest.release());
2101 		}
2102 
2103 		// Dual-Source blending tests
2104 		{
2105 			de::MovePtr<tcu::TestCaseGroup>	formatTest		(new tcu::TestCaseGroup(testCtx,
2106 																					getFormatCaseName(format).c_str(),
2107 																					(std::string("Uses format ") + getFormatName(format)).c_str()));
2108 			de::MovePtr<tcu::TestCaseGroup>	blendStateTests;
2109 			{
2110 				std::ostringstream blendStateDescription;
2111 				blendStateDescription << "Combines blend factors, operators and channel write masks. The constant color used in all tests is " << BlendTest::s_blendConst;
2112 				blendStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", blendStateDescription.str().c_str()));
2113 			}
2114 
2115 			dualSourceBlendStateItr.reset();
2116 
2117 			while (dualSourceBlendStateItr.hasNext())
2118 			{
2119 				VkPipelineColorBlendAttachmentState quadBlendConfigs[BlendTest::QUAD_COUNT];
2120 				deBool isDualSourceBlendTest = DE_FALSE;
2121 				for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
2122 				{
2123 					quadBlendConfigs[quadNdx]					= dualSourceBlendStateItr.next();
2124 					quadBlendConfigs[quadNdx].colorWriteMask	= BlendTest::s_colorWriteMasks[quadNdx];
2125 					isDualSourceBlendTest =
2126 						isDualSourceBlendTest ||
2127 						isSrc1BlendFactor(quadBlendConfigs[quadNdx].srcColorBlendFactor) ||
2128 						isSrc1BlendFactor(quadBlendConfigs[quadNdx].dstColorBlendFactor) ||
2129 						isSrc1BlendFactor(quadBlendConfigs[quadNdx].srcAlphaBlendFactor) ||
2130 						isSrc1BlendFactor(quadBlendConfigs[quadNdx].dstAlphaBlendFactor);
2131 				}
2132 
2133 				// Skip tests that don't have dual-source blend factors as they are already tested.
2134 				if (!isDualSourceBlendTest)
2135 					continue;
2136 
2137 				blendStateTests->addChild(new DualSourceBlendTest(testCtx,
2138 																  getBlendStateSetName(quadBlendConfigs),
2139 																  getBlendStateSetDescription(quadBlendConfigs),
2140 																  format,
2141 																  quadBlendConfigs));
2142 			}
2143 			formatTest->addChild(blendStateTests.release());
2144 			dualSourceFormatTests->addChild(formatTest.release());
2145 		}
2146 	}
2147 
2148 	// Subselection of formats that are easy to test for clamping.
2149 	const vk::VkFormat clampFormats[] =
2150 	{
2151 		vk::VK_FORMAT_R8G8B8A8_UNORM,
2152 		vk::VK_FORMAT_R8G8B8A8_SNORM,
2153 		vk::VK_FORMAT_B8G8R8A8_UNORM,
2154 		vk::VK_FORMAT_B8G8R8A8_SNORM,
2155 		vk::VK_FORMAT_R16G16B16A16_UNORM,
2156 		vk::VK_FORMAT_R16G16B16A16_SNORM,
2157 	};
2158 
2159 	for (int formatIdx = 0; formatIdx < DE_LENGTH_OF_ARRAY(clampFormats); ++formatIdx)
2160 	{
2161 		const auto& format = clampFormats[formatIdx];
2162 		ClampTestParams testParams;
2163 
2164 		testParams.colorFormat = format;
2165 
2166 		if (isUnormFormat(format))
2167 		{
2168 			testParams.quadColor[0] = 2.0f;
2169 			testParams.quadColor[1] = 0.5f;
2170 			testParams.quadColor[2] = 1.0f;
2171 			testParams.quadColor[3] = -1.0f;
2172 
2173 			testParams.blendConstants[0] = 0.5f;
2174 			testParams.blendConstants[1] = 2.0f;
2175 			testParams.blendConstants[2] = -1.0f;
2176 			testParams.blendConstants[3] = 1.0f;
2177 		}
2178 		else
2179 		{
2180 			testParams.quadColor[0] = 2.0f;
2181 			testParams.quadColor[1] = 0.5f;
2182 			testParams.quadColor[2] = 1.0f;
2183 			testParams.quadColor[3] = -2.0f;
2184 
2185 			testParams.blendConstants[0] = 0.5f;
2186 			testParams.blendConstants[1] = 2.0f;
2187 			testParams.blendConstants[2] = -2.0f;
2188 			testParams.blendConstants[3] = 1.0f;
2189 		}
2190 
2191 		clampTests->addChild(new ClampTest(testCtx, getFormatCaseName(format), std::string("Using format ") + getFormatName(format), testParams));
2192 	}
2193 
2194 	blendTests->addChild(formatTests.release());
2195 	blendTests->addChild(clampTests.release());
2196 
2197 	dualSourceBlendTests->addChild(dualSourceFormatTests.release());
2198 	blendTests->addChild(dualSourceBlendTests.release());
2199 
2200 	return blendTests.release();
2201 }
2202 
2203 } // pipeline
2204 } // vkt
2205