• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
443 		!context.getPortabilitySubsetFeatures().constantAlphaColorBlendFactors)
444 	{
445 		int quadNdx = 0;
446 		for (; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
447 		{
448 			const VkPipelineColorBlendAttachmentState& blendState = m_blendStates[quadNdx];
449 			if (blendState.srcColorBlendFactor == VK_BLEND_FACTOR_CONSTANT_ALPHA ||
450 				blendState.dstColorBlendFactor == VK_BLEND_FACTOR_CONSTANT_ALPHA ||
451 				blendState.srcColorBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA ||
452 				blendState.dstColorBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)
453 			{
454 				break;
455 			}
456 		}
457 		if (quadNdx < BlendTest::QUAD_COUNT)
458 			TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Constant alpha color blend factors are not supported by this implementation");
459 	}
460 }
461 
initPrograms(SourceCollections & sourceCollections) const462 void BlendTest::initPrograms (SourceCollections& sourceCollections) const
463 {
464 	std::ostringstream fragmentSource;
465 
466 	sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
467 		"#version 310 es\n"
468 		"layout(location = 0) in highp vec4 position;\n"
469 		"layout(location = 1) in highp vec4 color;\n"
470 		"layout(location = 0) out highp vec4 vtxColor;\n"
471 		"void main (void)\n"
472 		"{\n"
473 		"	gl_Position = position;\n"
474 		"	vtxColor = color;\n"
475 		"}\n");
476 
477 	fragmentSource << "#version 310 es\n"
478 		"layout(location = 0) in highp vec4 vtxColor;\n"
479 		"layout(location = 0) out highp vec4 fragColor;\n"
480 		"void main (void)\n"
481 		"{\n"
482 		"	fragColor = vtxColor;\n"
483 		"}\n";
484 
485 	sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
486 }
487 
488 // DualSourceBlendTest
489 
490 const VkColorComponentFlags DualSourceBlendTest::s_colorWriteMasks[BlendTest::QUAD_COUNT] = { VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT,	// Pair of channels: R & G
491 																							  VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT,	// Pair of channels: G & B
492 																							  VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,	// Pair of channels: B & A
493 																							  VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT };	// All channels
494 
495 const tcu::Vec4 DualSourceBlendTest::s_blendConst = tcu::Vec4(0.1f, 0.2f, 0.3f, 0.4f);
496 
DualSourceBlendTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const VkFormat colorFormat,const VkPipelineColorBlendAttachmentState blendStates[QUAD_COUNT])497 DualSourceBlendTest::DualSourceBlendTest (tcu::TestContext&								testContext,
498 										  const std::string&							name,
499 										  const std::string&							description,
500 										  const VkFormat								colorFormat,
501 										  const VkPipelineColorBlendAttachmentState		blendStates[QUAD_COUNT])
502 	: vkt::TestCase	(testContext, name, description)
503 	, m_colorFormat(colorFormat)
504 {
505 	deMemcpy(m_blendStates, blendStates, sizeof(VkPipelineColorBlendAttachmentState) * QUAD_COUNT);
506 }
507 
~DualSourceBlendTest(void)508 DualSourceBlendTest::~DualSourceBlendTest (void)
509 {
510 }
511 
isSrc1BlendFactor(vk::VkBlendFactor blendFactor)512 deBool isSrc1BlendFactor(vk::VkBlendFactor blendFactor)
513 {
514 	switch(blendFactor)
515 	{
516 		case vk::VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:
517 		case vk::VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA:
518 		case vk::VK_BLEND_FACTOR_SRC1_ALPHA:
519 		case vk::VK_BLEND_FACTOR_SRC1_COLOR:
520 			return DE_TRUE;
521 		default:
522 			return DE_FALSE;
523 	}
524 }
525 
createInstance(Context & context) const526 TestInstance* DualSourceBlendTest::createInstance(Context& context) const
527 {
528 	return new DualSourceBlendTestInstance(context, m_colorFormat, m_blendStates);
529 }
530 
checkSupport(Context & context) const531 void DualSourceBlendTest::checkSupport (Context& context) const
532 {
533 	const vk::VkPhysicalDeviceFeatures features = context.getDeviceFeatures();
534 
535 	deBool	isDualSourceTest = DE_FALSE;
536 	for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
537 	{
538 		isDualSourceTest =
539 			isSrc1BlendFactor(this->m_blendStates[quadNdx].srcColorBlendFactor) ||
540 			isSrc1BlendFactor(this->m_blendStates[quadNdx].dstColorBlendFactor) ||
541 			isSrc1BlendFactor(this->m_blendStates[quadNdx].srcAlphaBlendFactor) ||
542 			isSrc1BlendFactor(this->m_blendStates[quadNdx].dstAlphaBlendFactor);
543 		if (isDualSourceTest)
544 			break;
545 	}
546 	if (isDualSourceTest && !features.dualSrcBlend)
547 		throw tcu::NotSupportedError("Dual-Source blending not supported");
548 
549 	if (!isSupportedBlendFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_colorFormat))
550 		throw tcu::NotSupportedError(std::string("Unsupported color blending format: ") + getFormatName(m_colorFormat));
551 }
552 
initPrograms(SourceCollections & sourceCollections) const553 void DualSourceBlendTest::initPrograms (SourceCollections& sourceCollections) const
554 {
555 	std::ostringstream fragmentSource;
556 
557 	sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
558 		"#version 450\n"
559 		"layout(location = 0) in highp vec4 position;\n"
560 		"layout(location = 1) in highp vec4 color0;\n"
561 		"layout(location = 2) in highp vec4 color1;\n"
562 		"layout(location = 0) out highp vec4 vtxColor0;\n"
563 		"layout(location = 1) out highp vec4 vtxColor1;\n"
564 		"void main (void)\n"
565 		"{\n"
566 		"	gl_Position = position;\n"
567 		"	vtxColor0 = color0;\n"
568 		"	vtxColor1 = color1;\n"
569 		"}\n");
570 
571 	fragmentSource << "#version 450\n"
572 		"layout(location = 0) in highp vec4 vtxColor0;\n"
573 		"layout(location = 1) in highp vec4 vtxColor1;\n"
574 		"layout(location = 0, index = 0) out highp vec4 fragColor0;\n"
575 		"layout(location = 0, index = 1) out highp vec4 fragColor1;\n"
576 		"void main (void)\n"
577 		"{\n"
578 		"	fragColor0 = vtxColor0;\n"
579 		"	fragColor1 = vtxColor1;\n"
580 		"   if (int(gl_FragCoord.x) == 2 || int(gl_FragCoord.y) == 3)\n"
581 		"      discard;\n"
582 		"}\n";
583 
584 	sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
585 }
586 
587 // BlendTestInstance
588 
BlendTestInstance(Context & context,const VkFormat colorFormat,const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])589 BlendTestInstance::BlendTestInstance (Context&									context,
590 									  const VkFormat							colorFormat,
591 									  const VkPipelineColorBlendAttachmentState	blendStates[BlendTest::QUAD_COUNT])
592 	: vkt::TestInstance	(context)
593 	, m_renderSize		(32, 32)
594 	, m_colorFormat		(colorFormat)
595 {
596 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
597 	const VkDevice				vkDevice			= m_context.getDevice();
598 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
599 	SimpleAllocator				memAlloc			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
600 
601 	// Copy depth operators
602 	deMemcpy(m_blendStates, blendStates, sizeof(VkPipelineColorBlendAttachmentState) * BlendTest::QUAD_COUNT);
603 
604 	// Create color image
605 	{
606 		const VkImageCreateInfo	colorImageParams =
607 		{
608 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
609 			DE_NULL,																	// const void*				pNext;
610 			0u,																			// VkImageCreateFlags		flags;
611 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
612 			m_colorFormat,																// VkFormat					format;
613 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
614 			1u,																			// deUint32					mipLevels;
615 			1u,																			// deUint32					arrayLayers;
616 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
617 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
618 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
619 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
620 			1u,																			// deUint32					queueFamilyIndexCount;
621 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
622 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
623 		};
624 
625 		m_colorImageCreateInfo	= colorImageParams;
626 		m_colorImage			= createImage(vk, vkDevice, &m_colorImageCreateInfo);
627 
628 		// Allocate and bind color image memory
629 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
630 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
631 	}
632 
633 	// Create color attachment view
634 	{
635 		const VkImageViewCreateInfo colorAttachmentViewParams =
636 		{
637 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
638 			DE_NULL,											// const void*				pNext;
639 			0u,													// VkImageViewCreateFlags	flags;
640 			*m_colorImage,										// VkImage					image;
641 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
642 			m_colorFormat,										// VkFormat					format;
643 			{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY},
644 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
645 		};
646 
647 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
648 	}
649 
650 	// Create render pass
651 	m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat);
652 
653 	// Create framebuffer
654 	{
655 		const VkFramebufferCreateInfo framebufferParams =
656 		{
657 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
658 			DE_NULL,											// const void*				pNext;
659 			0u,													// VkFramebufferCreateFlags	flags;
660 			*m_renderPass,										// VkRenderPass				renderPass;
661 			1u,													// deUint32					attachmentCount;
662 			&m_colorAttachmentView.get(),						// const VkImageView*		pAttachments;
663 			(deUint32)m_renderSize.x(),							// deUint32					width;
664 			(deUint32)m_renderSize.y(),							// deUint32					height;
665 			1u													// deUint32					layers;
666 		};
667 
668 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
669 	}
670 
671 	// Create pipeline layout
672 	{
673 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
674 		{
675 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
676 			DE_NULL,											// const void*						pNext;
677 			0u,													// VkPipelineLayoutCreateFlags		flags;
678 			0u,													// deUint32							setLayoutCount;
679 			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
680 			0u,													// deUint32							pushConstantRangeCount;
681 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
682 		};
683 
684 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
685 	}
686 
687 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
688 	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
689 
690 	// Create pipeline
691 	{
692 		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
693 		{
694 			0u,									// deUint32					binding;
695 			sizeof(Vertex4RGBA),				// deUint32					strideInBytes;
696 			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	inputRate;
697 		};
698 
699 		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[2]	=
700 		{
701 			{
702 				0u,								// deUint32	location;
703 				0u,								// deUint32	binding;
704 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
705 				0u								// deUint32	offset;
706 			},
707 			{
708 				1u,								// deUint32	location;
709 				0u,								// deUint32	binding;
710 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
711 				(deUint32)(sizeof(float) * 4),	// deUint32	offset;
712 			}
713 		};
714 
715 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
716 		{
717 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
718 			DE_NULL,														// const void*								pNext;
719 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
720 			1u,																// deUint32									vertexBindingDescriptionCount;
721 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
722 			2u,																// deUint32									vertexAttributeDescriptionCount;
723 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
724 		};
725 
726 		const std::vector<VkViewport>				viewports							(1, makeViewport(m_renderSize));
727 		const std::vector<VkRect2D>					scissors							(1, makeRect2D(m_renderSize));
728 
729 		// The color blend attachment will be set up before creating the graphics pipeline.
730 		VkPipelineColorBlendStateCreateInfo			colorBlendStateParams				=
731 		{
732 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
733 			DE_NULL,													// const void*									pNext;
734 			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
735 			false,														// VkBool32										logicOpEnable;
736 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
737 			0u,															// deUint32										attachmentCount;
738 			DE_NULL,													// const VkPipelineColorBlendAttachmentState*	pAttachments;
739 			{															// float										blendConstants[4];
740 				BlendTest::s_blendConst.x(),
741 				BlendTest::s_blendConst.y(),
742 				BlendTest::s_blendConst.z(),
743 				BlendTest::s_blendConst.w()
744 			}
745 		};
746 
747 		for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
748 		{
749 			colorBlendStateParams.attachmentCount	= 1u;
750 			colorBlendStateParams.pAttachments		= &m_blendStates[quadNdx];
751 			m_graphicsPipelines[quadNdx]			= makeGraphicsPipeline(vk,									// const DeviceInterface&                        vk
752 																		   vkDevice,							// const VkDevice                                device
753 																		   *m_pipelineLayout,					// const VkPipelineLayout                        pipelineLayout
754 																		   *m_vertexShaderModule,				// const VkShaderModule                          vertexShaderModule
755 																		   DE_NULL,								// const VkShaderModule                          tessellationControlModule
756 																		   DE_NULL,								// const VkShaderModule                          tessellationEvalModule
757 																		   DE_NULL,								// const VkShaderModule                          geometryShaderModule
758 																		   *m_fragmentShaderModule,				// const VkShaderModule                          fragmentShaderModule
759 																		   *m_renderPass,						// const VkRenderPass                            renderPass
760 																		   viewports,							// const std::vector<VkViewport>&                viewports
761 																		   scissors,							// const std::vector<VkRect2D>&                  scissors
762 																		   VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
763 																		   0u,									// const deUint32                                subpass
764 																		   0u,									// const deUint32                                patchControlPoints
765 																		   &vertexInputStateParams,				// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
766 																		   DE_NULL,								// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
767 																		   DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
768 																		   DE_NULL,								// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
769 																		   &colorBlendStateParams);				// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
770 		}
771 	}
772 
773 	// Create vertex buffer
774 	{
775 		const VkBufferCreateInfo vertexBufferParams =
776 		{
777 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
778 			DE_NULL,									// const void*			pNext;
779 			0u,											// VkBufferCreateFlags	flags;
780 			1024u,										// VkDeviceSize			size;
781 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
782 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
783 			1u,											// deUint32				queueFamilyIndexCount;
784 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
785 		};
786 
787 		m_vertices			= createOverlappingQuads();
788 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
789 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
790 
791 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
792 
793 		// Adjust vertex colors
794 		if (!isFloatFormat(m_colorFormat))
795 		{
796 			const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(mapVkFormat(m_colorFormat));
797 			for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
798 				m_vertices[vertexNdx].color = (m_vertices[vertexNdx].color - formatInfo.lookupBias) / formatInfo.lookupScale;
799 		}
800 
801 		// Upload vertex data
802 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
803 
804 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
805 	}
806 
807 	// Create command pool
808 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
809 
810 	// Create command buffer
811 	{
812 		const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
813 
814 		// Color image layout transition
815 		const VkImageMemoryBarrier imageLayoutBarrier =
816 		{
817 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
818 			DE_NULL,																// const void*                pNext;
819 			(VkAccessFlags)0,														// VkAccessFlags              srcAccessMask;
820 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,									// VkAccessFlags              dstAccessMask;
821 			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
822 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,								// VkImageLayout              newLayout;
823 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
824 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
825 			*m_colorImage,															// VkImage                    image;
826 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }							// VkImageSubresourceRange    subresourceRange;
827 		};
828 
829 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
830 
831 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
832 
833 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
834 			0u, DE_NULL, 0u, DE_NULL, 1u, &imageLayoutBarrier);
835 
836 		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
837 
838 		const VkDeviceSize quadOffset = (m_vertices.size() / BlendTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
839 
840 		for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
841 		{
842 			VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
843 
844 			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]);
845 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
846 			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / BlendTest::QUAD_COUNT), 1, 0, 0);
847 		}
848 
849 		endRenderPass(vk, *m_cmdBuffer);
850 		endCommandBuffer(vk, *m_cmdBuffer);
851 	}
852 }
853 
~BlendTestInstance(void)854 BlendTestInstance::~BlendTestInstance (void)
855 {
856 }
857 
iterate(void)858 tcu::TestStatus BlendTestInstance::iterate (void)
859 {
860 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
861 	const VkDevice				vkDevice	= m_context.getDevice();
862 	const VkQueue				queue		= m_context.getUniversalQueue();
863 
864 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
865 
866 	return verifyImage();
867 }
868 
getNormChannelThreshold(const tcu::TextureFormat & format,int numBits)869 float getNormChannelThreshold (const tcu::TextureFormat& format, int numBits)
870 {
871 	switch (tcu::getTextureChannelClass(format.type))
872 	{
873 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:	return static_cast<float>(BlendTest::QUAD_COUNT) / static_cast<float>((1 << numBits) - 1);
874 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:	return static_cast<float>(BlendTest::QUAD_COUNT) / static_cast<float>((1 << (numBits - 1)) - 1);
875 		default:
876 			break;
877 	}
878 
879 	DE_ASSERT(false);
880 	return 0.0f;
881 }
882 
getFormatThreshold(const tcu::TextureFormat & format)883 tcu::Vec4 getFormatThreshold (const tcu::TextureFormat& format)
884 {
885 	using tcu::Vec4;
886 	using tcu::TextureFormat;
887 
888 	Vec4 threshold(0.01f);
889 
890 	switch (format.type)
891 	{
892 		case TextureFormat::UNORM_BYTE_44:
893 			threshold = Vec4(getNormChannelThreshold(format, 4), getNormChannelThreshold(format, 4), 1.0f, 1.0f);
894 			break;
895 
896 		case TextureFormat::UNORM_SHORT_565:
897 			threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 6), getNormChannelThreshold(format, 5), 1.0f);
898 			break;
899 
900 		case TextureFormat::UNORM_SHORT_555:
901 			threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), 1.0f);
902 			break;
903 
904 		case TextureFormat::UNORM_SHORT_4444:
905 			threshold = Vec4(getNormChannelThreshold(format, 4));
906 			break;
907 
908 		case TextureFormat::UNORM_SHORT_5551:
909 			threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), 0.1f);
910 			break;
911 
912 		case TextureFormat::UNORM_SHORT_10:
913 			threshold = Vec4(getNormChannelThreshold(format, 10));
914 			break;
915 
916 		case TextureFormat::UNORM_INT_1010102_REV:
917 		case TextureFormat::SNORM_INT_1010102_REV:
918 			threshold = Vec4(getNormChannelThreshold(format, 10), getNormChannelThreshold(format, 10), getNormChannelThreshold(format, 10), 0.34f);
919 			break;
920 
921 		case TextureFormat::UNORM_INT8:
922 		case TextureFormat::SNORM_INT8:
923 			threshold = Vec4(getNormChannelThreshold(format, 8));
924 			break;
925 
926 		case TextureFormat::UNORM_INT16:
927 		case TextureFormat::SNORM_INT16:
928 			threshold = Vec4(getNormChannelThreshold(format, 16));
929 			break;
930 
931 		case TextureFormat::UNORM_INT32:
932 		case TextureFormat::SNORM_INT32:
933 			threshold = Vec4(getNormChannelThreshold(format, 32));
934 			break;
935 
936 		case TextureFormat::HALF_FLOAT:
937 			threshold = Vec4(0.005f);
938 			break;
939 
940 		case TextureFormat::FLOAT:
941 			threshold = Vec4(0.00001f);
942 			break;
943 
944 		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:
945 			threshold = Vec4(0.02f, 0.02f, 0.0625f, 1.0f);
946 			break;
947 
948 		case TextureFormat::UNSIGNED_INT_999_E5_REV:
949 			threshold = Vec4(0.05f, 0.05f, 0.05f, 1.0f);
950 			break;
951 
952 		case TextureFormat::UNORM_SHORT_1555:
953 			threshold = Vec4(0.1f, getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5));
954 			break;
955 
956 		default:
957 			DE_ASSERT(false);
958 	}
959 
960 	// Return value matching the channel order specified by the format
961 	if (format.order == tcu::TextureFormat::BGR || format.order == tcu::TextureFormat::BGRA)
962 		return threshold.swizzle(2, 1, 0, 3);
963 	else
964 		return threshold;
965 }
966 
isLegalExpandableFormat(tcu::TextureFormat::ChannelType channeltype)967 bool isLegalExpandableFormat (tcu::TextureFormat::ChannelType channeltype)
968 {
969 	using tcu::TextureFormat;
970 
971 	switch (channeltype)
972 	{
973 		case TextureFormat::UNORM_INT24:
974 		case TextureFormat::UNORM_BYTE_44:
975 		case TextureFormat::UNORM_SHORT_565:
976 		case TextureFormat::UNORM_SHORT_555:
977 		case TextureFormat::UNORM_SHORT_4444:
978 		case TextureFormat::UNORM_SHORT_5551:
979 		case TextureFormat::UNORM_SHORT_1555:
980 		case TextureFormat::UNORM_SHORT_10:
981 		case TextureFormat::UNORM_INT_101010:
982 		case TextureFormat::SNORM_INT_1010102_REV:
983 		case TextureFormat::UNORM_INT_1010102_REV:
984 		case TextureFormat::UNSIGNED_BYTE_44:
985 		case TextureFormat::UNSIGNED_SHORT_565:
986 		case TextureFormat::UNSIGNED_SHORT_4444:
987 		case TextureFormat::UNSIGNED_SHORT_5551:
988 		case TextureFormat::SIGNED_INT_1010102_REV:
989 		case TextureFormat::UNSIGNED_INT_1010102_REV:
990 		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:
991 		case TextureFormat::UNSIGNED_INT_999_E5_REV:
992 		case TextureFormat::UNSIGNED_INT_24_8:
993 		case TextureFormat::UNSIGNED_INT_24_8_REV:
994 		case TextureFormat::UNSIGNED_INT24:
995 		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
996 			return true;
997 
998 		case TextureFormat::SNORM_INT8:
999 		case TextureFormat::SNORM_INT16:
1000 		case TextureFormat::SNORM_INT32:
1001 		case TextureFormat::UNORM_INT8:
1002 		case TextureFormat::UNORM_INT16:
1003 		case TextureFormat::UNORM_INT32:
1004 		case TextureFormat::UNSIGNED_INT_16_8_8:
1005 		case TextureFormat::SIGNED_INT8:
1006 		case TextureFormat::SIGNED_INT16:
1007 		case TextureFormat::SIGNED_INT32:
1008 		case TextureFormat::UNSIGNED_INT8:
1009 		case TextureFormat::UNSIGNED_INT16:
1010 		case TextureFormat::UNSIGNED_INT32:
1011 		case TextureFormat::HALF_FLOAT:
1012 		case TextureFormat::FLOAT:
1013 		case TextureFormat::FLOAT64:
1014 			return false;
1015 
1016 		default:
1017 			DE_FATAL("Unknown texture format");
1018 	}
1019 	return false;
1020 }
1021 
isSmallerThan8BitFormat(tcu::TextureFormat::ChannelType channeltype)1022 bool isSmallerThan8BitFormat (tcu::TextureFormat::ChannelType channeltype)
1023 {
1024 	using tcu::TextureFormat;
1025 
1026 	// Note: only checks the legal expandable formats
1027 	// (i.e, formats that have channels that fall outside
1028 	// the 8, 16 and 32 bit width)
1029 	switch (channeltype)
1030 	{
1031 		case TextureFormat::UNORM_BYTE_44:
1032 		case TextureFormat::UNORM_SHORT_565:
1033 		case TextureFormat::UNORM_SHORT_555:
1034 		case TextureFormat::UNORM_SHORT_4444:
1035 		case TextureFormat::UNORM_SHORT_5551:
1036 		case TextureFormat::UNORM_SHORT_1555:
1037 		case TextureFormat::UNSIGNED_BYTE_44:
1038 		case TextureFormat::UNSIGNED_SHORT_565:
1039 		case TextureFormat::UNSIGNED_SHORT_4444:
1040 		case TextureFormat::UNSIGNED_SHORT_5551:
1041 			return true;
1042 
1043 		case TextureFormat::UNORM_INT24:
1044 		case TextureFormat::UNORM_INT_101010:
1045 		case TextureFormat::SNORM_INT_1010102_REV:
1046 		case TextureFormat::UNORM_INT_1010102_REV:
1047 		case TextureFormat::SIGNED_INT_1010102_REV:
1048 		case TextureFormat::UNSIGNED_INT_1010102_REV:
1049 		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:
1050 		case TextureFormat::UNSIGNED_INT_999_E5_REV:
1051 		case TextureFormat::UNSIGNED_INT_24_8:
1052 		case TextureFormat::UNSIGNED_INT_24_8_REV:
1053 		case TextureFormat::UNSIGNED_INT24:
1054 		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
1055 		case TextureFormat::UNORM_SHORT_10:
1056 			return false;
1057 
1058 		default:
1059 			DE_FATAL("Unknown texture format");
1060 	}
1061 
1062 	return false;
1063 }
1064 
verifyImage(void)1065 tcu::TestStatus BlendTestInstance::verifyImage (void)
1066 {
1067 	const tcu::TextureFormat	tcuColorFormat		= mapVkFormat(m_colorFormat);
1068 	const tcu::TextureFormat	tcuColorFormat64	= mapVkFormat(VK_FORMAT_R64G64B64A64_SFLOAT);
1069 	const tcu::TextureFormat	tcuColorFormat8		= mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
1070 	const tcu::TextureFormat	tcuDepthFormat		= tcu::TextureFormat(); // Undefined depth/stencil format
1071 	const ColorVertexShader		vertexShader;
1072 	const ColorFragmentShader	fragmentShader		(tcuColorFormat, tcuDepthFormat);
1073 	const rr::Program			program				(&vertexShader, &fragmentShader);
1074 	ReferenceRenderer			refRenderer			(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
1075 	ReferenceRenderer			refRenderer64		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat64, tcuDepthFormat, &program);
1076 	ReferenceRenderer			refRenderer8		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat8, tcuDepthFormat, &program);
1077 	bool						compareOk			= false;
1078 
1079 	// Render reference image
1080 	{
1081 		for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
1082 		{
1083 			const VkPipelineColorBlendAttachmentState& blendState = m_blendStates[quadNdx];
1084 
1085 			// Set blend state
1086 			rr::RenderState renderState					(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1087 			renderState.fragOps.blendMode				= rr::BLENDMODE_STANDARD;
1088 			renderState.fragOps.blendRGBState.srcFunc	= mapVkBlendFactor(blendState.srcColorBlendFactor);
1089 			renderState.fragOps.blendRGBState.dstFunc	= mapVkBlendFactor(blendState.dstColorBlendFactor);
1090 			renderState.fragOps.blendRGBState.equation	= mapVkBlendOp(blendState.colorBlendOp);
1091 			renderState.fragOps.blendAState.srcFunc		= mapVkBlendFactor(blendState.srcAlphaBlendFactor);
1092 			renderState.fragOps.blendAState.dstFunc		= mapVkBlendFactor(blendState.dstAlphaBlendFactor);
1093 			renderState.fragOps.blendAState.equation	= mapVkBlendOp(blendState.alphaBlendOp);
1094 			renderState.fragOps.blendColor				= BlendTest::s_blendConst;
1095 			renderState.fragOps.colorMask				= mapVkColorComponentFlags(BlendTest::s_colorWriteMasks[quadNdx]);
1096 
1097 			refRenderer.draw(renderState,
1098 							rr::PRIMITIVETYPE_TRIANGLES,
1099 							std::vector<Vertex4RGBA>(m_vertices.begin() + quadNdx * 6,
1100 													 m_vertices.begin() + (quadNdx + 1) * 6));
1101 
1102 			if (isLegalExpandableFormat(tcuColorFormat.type))
1103 			{
1104 				refRenderer64.draw(renderState,
1105 								   rr::PRIMITIVETYPE_TRIANGLES,
1106 								   std::vector<Vertex4RGBA>(m_vertices.begin() + quadNdx * 6,
1107 								   m_vertices.begin() + (quadNdx + 1) * 6));
1108 
1109 				if (isSmallerThan8BitFormat(tcuColorFormat.type))
1110 					refRenderer8.draw(renderState,
1111 									  rr::PRIMITIVETYPE_TRIANGLES,
1112 									  std::vector<Vertex4RGBA>(m_vertices.begin() + quadNdx * 6,
1113 									  m_vertices.begin() + (quadNdx + 1) * 6));
1114 			}
1115 		}
1116 	}
1117 
1118 	// Compare result with reference image
1119 	{
1120 		const DeviceInterface&				vk							= m_context.getDeviceInterface();
1121 		const VkDevice						vkDevice					= m_context.getDevice();
1122 		const VkQueue						queue						= m_context.getUniversalQueue();
1123 		const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
1124 		SimpleAllocator						allocator					(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1125 		de::UniquePtr<tcu::TextureLevel>	result						(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
1126 		const tcu::Vec4						threshold					(getFormatThreshold(tcuColorFormat));
1127 		tcu::TextureLevel					refLevel;
1128 
1129 		refLevel.setStorage(tcuColorFormat, m_renderSize.x(), m_renderSize.y(), 1);
1130 
1131 		compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1132 											   "FloatImageCompare",
1133 											   "Image comparison",
1134 											   refRenderer.getAccess(),
1135 											   result->getAccess(),
1136 											   threshold,
1137 											   tcu::COMPARE_LOG_RESULT);
1138 
1139 		if (isLegalExpandableFormat(tcuColorFormat.type))
1140 		{
1141 			if (!compareOk && isSmallerThan8BitFormat(tcuColorFormat.type))
1142 			{
1143 				// Convert to target format
1144 				tcu::copy(refLevel.getAccess(), refRenderer8.getAccess());
1145 
1146 				compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1147 													   "FloatImageCompare",
1148 													   "Image comparison, 8 bit intermediate format",
1149 													   refLevel.getAccess(),
1150 													   result->getAccess(),
1151 													   threshold,
1152 													   tcu::COMPARE_LOG_RESULT);
1153 			}
1154 
1155 			if (!compareOk)
1156 			{
1157 				// Convert to target format
1158 				tcu::copy(refLevel.getAccess(), refRenderer64.getAccess());
1159 
1160 				compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1161 													   "FloatImageCompare",
1162 													   "Image comparison, 64 bit intermediate format",
1163 													   refLevel.getAccess(),
1164 													   result->getAccess(),
1165 													   threshold,
1166 													   tcu::COMPARE_LOG_RESULT);
1167 			}
1168 		}
1169 	}
1170 
1171 	if (compareOk)
1172 		return tcu::TestStatus::pass("Result image matches reference");
1173 	else
1174 		return tcu::TestStatus::fail("Image mismatch");
1175 }
1176 
1177 // DualSourceBlendTestInstance
1178 
DualSourceBlendTestInstance(Context & context,const VkFormat colorFormat,const VkPipelineColorBlendAttachmentState blendStates[DualSourceBlendTest::QUAD_COUNT])1179 DualSourceBlendTestInstance::DualSourceBlendTestInstance (Context&									context,
1180 														  const VkFormat							colorFormat,
1181 														  const VkPipelineColorBlendAttachmentState	blendStates[DualSourceBlendTest::QUAD_COUNT])
1182 	: vkt::TestInstance	(context)
1183 	, m_renderSize		(32, 32)
1184 	, m_colorFormat		(colorFormat)
1185 {
1186 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
1187 	const VkDevice				vkDevice			= m_context.getDevice();
1188 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1189 	SimpleAllocator				memAlloc			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1190 
1191 	// Copy depth operators
1192 	deMemcpy(m_blendStates, blendStates, sizeof(VkPipelineColorBlendAttachmentState) * DualSourceBlendTest::QUAD_COUNT);
1193 
1194 	// Create color image
1195 	{
1196 		const VkImageCreateInfo	colorImageParams =
1197 		{
1198 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
1199 			DE_NULL,																	// const void*				pNext;
1200 			0u,																			// VkImageCreateFlags		flags;
1201 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
1202 			m_colorFormat,																// VkFormat					format;
1203 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
1204 			1u,																			// deUint32					mipLevels;
1205 			1u,																			// deUint32					arrayLayers;
1206 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
1207 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
1208 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
1209 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
1210 			1u,																			// deUint32					queueFamilyIndexCount;
1211 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
1212 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
1213 		};
1214 
1215 		m_colorImageCreateInfo	= colorImageParams;
1216 		m_colorImage			= createImage(vk, vkDevice, &m_colorImageCreateInfo);
1217 
1218 		// Allocate and bind color image memory
1219 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
1220 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
1221 	}
1222 
1223 	// Create color attachment view
1224 	{
1225 		const VkImageViewCreateInfo colorAttachmentViewParams =
1226 		{
1227 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
1228 			DE_NULL,											// const void*				pNext;
1229 			0u,													// VkImageViewCreateFlags	flags;
1230 			*m_colorImage,										// VkImage					image;
1231 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
1232 			m_colorFormat,										// VkFormat					format;
1233 			{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY},
1234 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
1235 		};
1236 
1237 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
1238 	}
1239 
1240 	// Create render pass
1241 	m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat);
1242 
1243 	// Create framebuffer
1244 	{
1245 		const VkFramebufferCreateInfo framebufferParams =
1246 		{
1247 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
1248 			DE_NULL,											// const void*				pNext;
1249 			0u,													// VkFramebufferCreateFlags	flags;
1250 			*m_renderPass,										// VkRenderPass				renderPass;
1251 			1u,													// deUint32					attachmentCount;
1252 			&m_colorAttachmentView.get(),						// const VkImageView*		pAttachments;
1253 			(deUint32)m_renderSize.x(),							// deUint32					width;
1254 			(deUint32)m_renderSize.y(),							// deUint32					height;
1255 			1u													// deUint32					layers;
1256 		};
1257 
1258 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
1259 	}
1260 
1261 	// Create pipeline layout
1262 	{
1263 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1264 		{
1265 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
1266 			DE_NULL,											// const void*						pNext;
1267 			0u,													// VkPipelineLayoutCreateFlags		flags;
1268 			0u,													// deUint32							setLayoutCount;
1269 			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
1270 			0u,													// deUint32							pushConstantRangeCount;
1271 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
1272 		};
1273 
1274 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1275 	}
1276 
1277 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
1278 	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
1279 
1280 	// Create pipeline
1281 	{
1282 		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
1283 		{
1284 			0u,									// deUint32					binding;
1285 			sizeof(Vertex4RGBARGBA),			// deUint32					strideInBytes;
1286 			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	inputRate;
1287 		};
1288 
1289 		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[3]	=
1290 		{
1291 			{
1292 				0u,								// deUint32	location;
1293 				0u,								// deUint32	binding;
1294 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
1295 				0u								// deUint32	offset;
1296 			},
1297 			{
1298 				1u,								// deUint32	location;
1299 				0u,								// deUint32	binding;
1300 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
1301 				(deUint32)(sizeof(float) * 4),	// deUint32	offset;
1302 			},
1303 			{
1304 				2u,								// deUint32	location;
1305 				0u,								// deUint32	binding;
1306 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
1307 				(deUint32)(sizeof(float) * 8),	// deUint32	offset;
1308 			}
1309 		};
1310 
1311 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
1312 		{
1313 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
1314 			DE_NULL,														// const void*								pNext;
1315 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
1316 			1u,																// deUint32									vertexBindingDescriptionCount;
1317 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1318 			3u,																// deUint32									vertexAttributeDescriptionCount;
1319 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1320 		};
1321 
1322 		const std::vector<VkViewport>				viewports							(1, makeViewport(m_renderSize));
1323 		const std::vector<VkRect2D>					scissors							(1, makeRect2D(m_renderSize));
1324 
1325 		// The color blend attachment will be set up before creating the graphics pipeline.
1326 		VkPipelineColorBlendStateCreateInfo			colorBlendStateParams				=
1327 		{
1328 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1329 			DE_NULL,													// const void*									pNext;
1330 			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
1331 			false,														// VkBool32										logicOpEnable;
1332 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1333 			0u,															// deUint32										attachmentCount;
1334 			DE_NULL,													// const VkPipelineColorBlendAttachmentState*	pAttachments;
1335 			{															// float										blendConstants[4];
1336 				DualSourceBlendTest::s_blendConst.x(),
1337 				DualSourceBlendTest::s_blendConst.y(),
1338 				DualSourceBlendTest::s_blendConst.z(),
1339 				DualSourceBlendTest::s_blendConst.w()
1340 			}
1341 		};
1342 
1343 		for (int quadNdx = 0; quadNdx < DualSourceBlendTest::QUAD_COUNT; quadNdx++)
1344 		{
1345 			colorBlendStateParams.attachmentCount	= 1u;
1346 			colorBlendStateParams.pAttachments		= &m_blendStates[quadNdx];
1347 			m_graphicsPipelines[quadNdx]			= makeGraphicsPipeline(vk,									// const DeviceInterface&                        vk
1348 																		   vkDevice,							// const VkDevice                                device
1349 																		   *m_pipelineLayout,					// const VkPipelineLayout                        pipelineLayout
1350 																		   *m_vertexShaderModule,				// const VkShaderModule                          vertexShaderModule
1351 																		   DE_NULL,								// const VkShaderModule                          tessellationControlModule
1352 																		   DE_NULL,								// const VkShaderModule                          tessellationEvalModule
1353 																		   DE_NULL,								// const VkShaderModule                          geometryShaderModule
1354 																		   *m_fragmentShaderModule,				// const VkShaderModule                          fragmentShaderModule
1355 																		   *m_renderPass,						// const VkRenderPass                            renderPass
1356 																		   viewports,							// const std::vector<VkViewport>&                viewports
1357 																		   scissors,							// const std::vector<VkRect2D>&                  scissors
1358 																		   VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
1359 																		   0u,									// const deUint32                                subpass
1360 																		   0u,									// const deUint32                                patchControlPoints
1361 																		   &vertexInputStateParams,				// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
1362 																		   DE_NULL,								// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1363 																		   DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
1364 																		   DE_NULL,								// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
1365 																		   &colorBlendStateParams);				// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
1366 		}
1367 	}
1368 
1369 	// Create vertex buffer
1370 	{
1371 		const VkBufferCreateInfo vertexBufferParams =
1372 		{
1373 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1374 			DE_NULL,									// const void*			pNext;
1375 			0u,											// VkBufferCreateFlags	flags;
1376 			1152u,										// VkDeviceSize			size;
1377 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
1378 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1379 			1u,											// deUint32				queueFamilyIndexCount;
1380 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
1381 		};
1382 
1383 		m_vertices			= createOverlappingQuadsDualSource();
1384 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
1385 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
1386 
1387 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
1388 
1389 		// Adjust vertex colors
1390 		if (!isFloatFormat(m_colorFormat))
1391 		{
1392 			const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(mapVkFormat(m_colorFormat));
1393 			for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
1394 			{
1395 				m_vertices[vertexNdx].color0 = (m_vertices[vertexNdx].color0 - formatInfo.lookupBias) / formatInfo.lookupScale;
1396 				m_vertices[vertexNdx].color1 = (m_vertices[vertexNdx].color1 - formatInfo.lookupBias) / formatInfo.lookupScale;
1397 			}
1398 		}
1399 
1400 		// Upload vertex data
1401 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBARGBA));
1402 
1403 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
1404 	}
1405 
1406 	// Create command pool
1407 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1408 
1409 	// Create command buffer
1410 	{
1411 		const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
1412 
1413 		// Color image layout transition
1414 		const VkImageMemoryBarrier imageLayoutBarrier =
1415 		{
1416 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
1417 			DE_NULL,																// const void*                pNext;
1418 			(VkAccessFlags)0,														// VkAccessFlags              srcAccessMask;
1419 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,									// VkAccessFlags              dstAccessMask;
1420 			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
1421 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,								// VkImageLayout              newLayout;
1422 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
1423 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
1424 			*m_colorImage,															// VkImage                    image;
1425 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }							// VkImageSubresourceRange    subresourceRange;
1426 		};
1427 
1428 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1429 
1430 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1431 
1432 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
1433 			0u, DE_NULL, 0u, DE_NULL, 1u, &imageLayoutBarrier);
1434 
1435 		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
1436 
1437 		const VkDeviceSize quadOffset = (m_vertices.size() / DualSourceBlendTest::QUAD_COUNT) * sizeof(Vertex4RGBARGBA);
1438 
1439 		for (int quadNdx = 0; quadNdx < DualSourceBlendTest::QUAD_COUNT; quadNdx++)
1440 		{
1441 			VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
1442 
1443 			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]);
1444 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1445 			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / DualSourceBlendTest::QUAD_COUNT), 1, 0, 0);
1446 		}
1447 
1448 		endRenderPass(vk, *m_cmdBuffer);
1449 		endCommandBuffer(vk, *m_cmdBuffer);
1450 	}
1451 }
1452 
~DualSourceBlendTestInstance(void)1453 DualSourceBlendTestInstance::~DualSourceBlendTestInstance (void)
1454 {
1455 }
1456 
iterate(void)1457 tcu::TestStatus DualSourceBlendTestInstance::iterate (void)
1458 {
1459 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1460 	const VkDevice				vkDevice	= m_context.getDevice();
1461 	const VkQueue				queue		= m_context.getUniversalQueue();
1462 
1463 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1464 
1465 	return verifyImage();
1466 }
1467 
verifyImage(void)1468 tcu::TestStatus DualSourceBlendTestInstance::verifyImage (void)
1469 {
1470 	const tcu::TextureFormat			tcuColorFormat		= mapVkFormat(m_colorFormat);
1471 	const tcu::TextureFormat			tcuColorFormat64	= mapVkFormat(VK_FORMAT_R64G64B64A64_SFLOAT);
1472 	const tcu::TextureFormat			tcuColorFormat8		= mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
1473 	const tcu::TextureFormat			tcuDepthFormat		= tcu::TextureFormat(); // Undefined depth/stencil format
1474 	const ColorVertexShaderDualSource	vertexShader;
1475 	const ColorFragmentShaderDualSource	fragmentShader		(tcuColorFormat, tcuDepthFormat);
1476 	const rr::Program					program				(&vertexShader, &fragmentShader);
1477 	ReferenceRenderer					refRenderer			(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
1478 	ReferenceRenderer					refRenderer64		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat64, tcuDepthFormat, &program);
1479 	ReferenceRenderer					refRenderer8		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat8, tcuDepthFormat, &program);
1480 	bool								compareOk			= false;
1481 	tcu::PixelBufferAccess				access				= refRenderer.getAccess();
1482 	tcu::PixelBufferAccess				access8				= refRenderer8.getAccess();
1483 	tcu::PixelBufferAccess				access64			= refRenderer64.getAccess();
1484 
1485 	// Render reference image
1486 	{
1487 		// read clear color
1488 		tcu::Vec4 discardColor		= access.getPixel(0, 0);
1489 		tcu::Vec4 discardColor8		= access8.getPixel(0, 0);
1490 		tcu::Vec4 discardColor64	= access64.getPixel(0, 0);
1491 
1492 		for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
1493 		{
1494 			const VkPipelineColorBlendAttachmentState& blendState = m_blendStates[quadNdx];
1495 
1496 			// Set blend state
1497 			rr::RenderState renderState					(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1498 			renderState.fragOps.blendMode				= rr::BLENDMODE_STANDARD;
1499 			renderState.fragOps.blendRGBState.srcFunc	= mapVkBlendFactor(blendState.srcColorBlendFactor);
1500 			renderState.fragOps.blendRGBState.dstFunc	= mapVkBlendFactor(blendState.dstColorBlendFactor);
1501 			renderState.fragOps.blendRGBState.equation	= mapVkBlendOp(blendState.colorBlendOp);
1502 			renderState.fragOps.blendAState.srcFunc		= mapVkBlendFactor(blendState.srcAlphaBlendFactor);
1503 			renderState.fragOps.blendAState.dstFunc		= mapVkBlendFactor(blendState.dstAlphaBlendFactor);
1504 			renderState.fragOps.blendAState.equation	= mapVkBlendOp(blendState.alphaBlendOp);
1505 			renderState.fragOps.blendColor				= DualSourceBlendTest::s_blendConst;
1506 			renderState.fragOps.colorMask				= mapVkColorComponentFlags(DualSourceBlendTest::s_colorWriteMasks[quadNdx]);
1507 
1508 			refRenderer.draw(renderState,
1509 							rr::PRIMITIVETYPE_TRIANGLES,
1510 							std::vector<Vertex4RGBARGBA>(m_vertices.begin() + quadNdx * 6,
1511 													 m_vertices.begin() + (quadNdx + 1) * 6));
1512 
1513 			if (isLegalExpandableFormat(tcuColorFormat.type))
1514 			{
1515 				refRenderer64.draw(renderState,
1516 								   rr::PRIMITIVETYPE_TRIANGLES,
1517 								   std::vector<Vertex4RGBARGBA>(m_vertices.begin() + quadNdx * 6,
1518 								   m_vertices.begin() + (quadNdx + 1) * 6));
1519 
1520 				if (isSmallerThan8BitFormat(tcuColorFormat.type))
1521 					refRenderer8.draw(renderState,
1522 									  rr::PRIMITIVETYPE_TRIANGLES,
1523 									  std::vector<Vertex4RGBARGBA>(m_vertices.begin() + quadNdx * 6,
1524 									  m_vertices.begin() + (quadNdx + 1) * 6));
1525 			}
1526 		}
1527 
1528 		// re-request the pixel access; copies various formats to accessable ones
1529 		// (if we don't do this, the above draws don't matter)
1530 		access = refRenderer.getAccess();
1531 		access8 = refRenderer8.getAccess();
1532 		access64 = refRenderer64.getAccess();
1533 
1534 		// Paint back the discarded pixels with the clear color. The reference
1535 		// renderer doesn't actually run the shader, and doesn't know about discard,
1536 		// so this is a way to get to the images we wanted.
1537 		for (int i = 0; i < access.getWidth(); i++)
1538 		{
1539 			access.setPixel(discardColor, i, 3);
1540 			if (isLegalExpandableFormat(tcuColorFormat.type))
1541 			{
1542 				access64.setPixel(discardColor64, i, 3);
1543 				if (isSmallerThan8BitFormat(tcuColorFormat.type))
1544 					access8.setPixel(discardColor8, i, 3);
1545 			}
1546 		}
1547 
1548 		for (int i = 0; i < access.getHeight(); i++)
1549 		{
1550 			access.setPixel(discardColor, 2, i);
1551 			if (isLegalExpandableFormat(tcuColorFormat.type))
1552 			{
1553 				access64.setPixel(discardColor64, 2, i);
1554 				if (isSmallerThan8BitFormat(tcuColorFormat.type))
1555 					access8.setPixel(discardColor8, 2, i);
1556 			}
1557 		}
1558 	}
1559 
1560 	// Compare result with reference image
1561 	{
1562 		const DeviceInterface&				vk							= m_context.getDeviceInterface();
1563 		const VkDevice						vkDevice					= m_context.getDevice();
1564 		const VkQueue						queue						= m_context.getUniversalQueue();
1565 		const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
1566 		SimpleAllocator						allocator					(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1567 		de::UniquePtr<tcu::TextureLevel>	result						(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
1568 		tcu::Vec4							threshold					(getFormatThreshold(tcuColorFormat));
1569 		tcu::TextureLevel					refLevel;
1570 
1571 		// For SRGB formats there is an extra precision loss due to doing
1572 		// the following conversions sRGB -> RGB -> blend -> RGB  -> sRGB with floats.
1573 		// Take that into account in the threshold. For example, VK_FORMAT_R8G8B8A8_SRGB
1574 		// threshold is 4/255f, but we changed it to be 10/255f.
1575 		if (tcu::isSRGB(tcuColorFormat))
1576 			threshold = 2.5f * threshold;
1577 
1578 		refLevel.setStorage(tcuColorFormat, m_renderSize.x(), m_renderSize.y(), 1);
1579 
1580 		compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1581 											   "FloatImageCompare",
1582 											   "Image comparison",
1583 											   access,
1584 											   result->getAccess(),
1585 											   threshold,
1586 											   tcu::COMPARE_LOG_RESULT);
1587 
1588 		if (isLegalExpandableFormat(tcuColorFormat.type))
1589 		{
1590 			if (!compareOk && isSmallerThan8BitFormat(tcuColorFormat.type))
1591 			{
1592 				// Convert to target format
1593 				tcu::copy(refLevel.getAccess(), access8);
1594 
1595 				compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1596 													   "FloatImageCompare",
1597 													   "Image comparison, 8 bit intermediate format",
1598 													   refLevel.getAccess(),
1599 													   result->getAccess(),
1600 													   threshold,
1601 													   tcu::COMPARE_LOG_RESULT);
1602 			}
1603 
1604 			if (!compareOk)
1605 			{
1606 				// Convert to target format
1607 				tcu::copy(refLevel.getAccess(), access64);
1608 
1609 				compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1610 													   "FloatImageCompare",
1611 													   "Image comparison, 64 bit intermediate format",
1612 													   refLevel.getAccess(),
1613 													   result->getAccess(),
1614 													   threshold,
1615 													   tcu::COMPARE_LOG_RESULT);
1616 			}
1617 		}
1618 	}
1619 
1620 	if (compareOk)
1621 		return tcu::TestStatus::pass("Result image matches reference");
1622 	else
1623 		return tcu::TestStatus::fail("Image mismatch");
1624 }
1625 
1626 // Clamping tests for colors and constants.
1627 
1628 struct ClampTestParams
1629 {
1630 	vk::VkFormat	colorFormat;
1631 	tcu::Vec4		quadColor;
1632 	tcu::Vec4		blendConstants;
1633 };
1634 
1635 class ClampTest : public vkt::TestCase
1636 {
1637 public:
1638 										ClampTest				(tcu::TestContext&							testContext,
1639 																 const std::string&							name,
1640 																 const std::string&							description,
1641 																 const ClampTestParams&						testParams);
~ClampTest(void)1642 	virtual								~ClampTest				(void) {}
1643 	virtual void						initPrograms			(SourceCollections& sourceCollections) const;
1644 	virtual void						checkSupport			(Context& context) const;
1645 	virtual TestInstance*				createInstance			(Context& context) const;
1646 
1647 private:
1648 	const ClampTestParams				m_params;
1649 };
1650 
1651 class ClampTestInstance : public vkt::TestInstance
1652 {
1653 public:
ClampTestInstance(Context & context,const ClampTestParams & testParams)1654 								ClampTestInstance		(Context& context, const ClampTestParams& testParams)
1655 									: vkt::TestInstance(context), m_params(testParams)
1656 									{}
~ClampTestInstance(void)1657 	virtual						~ClampTestInstance		(void) {}
1658 	virtual tcu::TestStatus		iterate					(void);
1659 
1660 private:
1661 	const ClampTestParams		m_params;
1662 };
1663 
ClampTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const ClampTestParams & testParams)1664 ClampTest::ClampTest (tcu::TestContext&			testContext,
1665 					  const std::string&		name,
1666 					  const std::string&		description,
1667 					  const ClampTestParams&	testParams)
1668 	: vkt::TestCase (testContext, name, description)
1669 	, m_params(testParams)
1670 {
1671 	// As per the spec:
1672 	//
1673 	//  If the color attachment is fixed-point, the components of the source and destination values and blend factors are each
1674 	//  clamped to [0,1] or [-1,1] respectively for an unsigned normalized or signed normalized color attachment prior to evaluating
1675 	//  the blend operations. If the color attachment is floating-point, no clamping occurs.
1676 	//
1677 	// We will only test signed and unsigned normalized formats, and avoid precision problems by having all channels have the same
1678 	// bit depth.
1679 	//
1680 	DE_ASSERT(isSnormFormat(m_params.colorFormat) || isUnormFormat(m_params.colorFormat));
1681 
1682 	const auto bitDepth = tcu::getTextureFormatBitDepth(mapVkFormat(m_params.colorFormat));
1683 	DE_UNREF(bitDepth); // For release builds.
1684 	DE_ASSERT(bitDepth[0] == bitDepth[1] && bitDepth[0] == bitDepth[2] && bitDepth[0] == bitDepth[3]);
1685 }
1686 
initPrograms(SourceCollections & sourceCollections) const1687 void ClampTest::initPrograms (SourceCollections& sourceCollections) const
1688 {
1689 	std::ostringstream fragmentSource;
1690 
1691 	sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
1692 		"#version 310 es\n"
1693 		"layout(location = 0) in highp vec4 position;\n"
1694 		"layout(location = 1) in highp vec4 color;\n"
1695 		"layout(location = 0) out highp vec4 vtxColor;\n"
1696 		"void main (void)\n"
1697 		"{\n"
1698 		"	gl_Position = position;\n"
1699 		"	vtxColor = color;\n"
1700 		"}\n");
1701 
1702 	fragmentSource << "#version 310 es\n"
1703 		"layout(location = 0) in highp vec4 vtxColor;\n"
1704 		"layout(location = 0) out highp vec4 fragColor;\n"
1705 		"void main (void)\n"
1706 		"{\n"
1707 		"	fragColor = vtxColor;\n"
1708 		"}\n";
1709 
1710 	sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
1711 }
1712 
checkSupport(Context & context) const1713 void ClampTest::checkSupport (Context& context) const
1714 {
1715 	if (!isSupportedBlendFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.colorFormat))
1716 		throw tcu::NotSupportedError(std::string("Unsupported color blending format: ") + getFormatName(m_params.colorFormat));
1717 }
1718 
createInstance(Context & context) const1719 TestInstance* ClampTest::createInstance(Context& context) const
1720 {
1721 	return new ClampTestInstance(context, m_params);
1722 }
1723 
iterate(void)1724 tcu::TestStatus ClampTestInstance::iterate (void)
1725 {
1726 	const vk::DeviceInterface&	vkd					= m_context.getDeviceInterface();
1727 	const vk::VkDevice			device				= m_context.getDevice();
1728 	vk::Allocator&				allocator			= m_context.getDefaultAllocator();
1729 	const vk::VkQueue			queue				= m_context.getUniversalQueue();
1730 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1731 	const vk::VkExtent3D		renderSize			= { 32u, 32u, 1u };
1732 
1733 	// Image.
1734 	const vk::VkImageCreateInfo	imageCreateInfo =
1735 	{
1736 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
1737 		nullptr,																		// const void*				pNext;
1738 		0u,																				// VkImageCreateFlags		flags;
1739 		vk::VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
1740 		m_params.colorFormat,															// VkFormat					format;
1741 		renderSize,																		// VkExtent3D				extent;
1742 		1u,																				// deUint32					mipLevels;
1743 		1u,																				// deUint32					arrayLayers;
1744 		vk::VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
1745 		vk::VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
1746 		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage;
1747 		vk::VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
1748 		1u,																				// deUint32					queueFamilyIndexCount;
1749 		&queueFamilyIndex,																// const deUint32*			pQueueFamilyIndices;
1750 		vk::VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			initialLayout;
1751 	};
1752 
1753 	vk::ImageWithMemory colorImage (vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any);
1754 
1755 	// Image view.
1756 	const vk::VkImageViewCreateInfo imageViewCreateInfo =
1757 	{
1758 		vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
1759 		nullptr,											// const void*				pNext;
1760 		0u,													// VkImageViewCreateFlags	flags;
1761 		colorImage.get(),									// VkImage					image;
1762 		vk::VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
1763 		m_params.colorFormat,								// VkFormat					format;
1764 		{													// VkComponentMapping		components;
1765 			vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1766 			vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1767 			vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1768 			vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1769 		},
1770 		{ vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
1771 	};
1772 
1773 	auto colorImageView = createImageView(vkd, device, &imageViewCreateInfo);
1774 
1775 	// Render pass.
1776 	auto renderPass = makeRenderPass(vkd, device, m_params.colorFormat);
1777 
1778 	// Frame buffer.
1779 	const vk::VkFramebufferCreateInfo framebufferParams =
1780 	{
1781 		vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType			sType;
1782 		nullptr,											// const void*				pNext;
1783 		0u,													// VkFramebufferCreateFlags	flags;
1784 		renderPass.get(),									// VkRenderPass				renderPass;
1785 		1u,													// deUint32					attachmentCount;
1786 		&colorImageView.get(),								// const VkImageView*		pAttachments;
1787 		renderSize.width,									// deUint32					width;
1788 		renderSize.height,									// deUint32					height;
1789 		1u,													// deUint32					layers;
1790 	};
1791 
1792 	auto framebuffer = createFramebuffer(vkd, device, &framebufferParams);
1793 
1794 	// Pipeline layout.
1795 	const vk::VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1796 	{
1797 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType					sType;
1798 		nullptr,											// const void*						pNext;
1799 		0u,													// VkPipelineLayoutCreateFlags		flags;
1800 		0u,													// deUint32							setLayoutCount;
1801 		nullptr,											// const VkDescriptorSetLayout*		pSetLayouts;
1802 		0u,													// deUint32							pushConstantRangeCount;
1803 		nullptr,											// const VkPushConstantRange*		pPushConstantRanges;
1804 	};
1805 
1806 	auto pipelineLayout = createPipelineLayout(vkd, device, &pipelineLayoutCreateInfo);
1807 
1808 	// Shader modules.
1809 	auto vertexShaderModule		= createShaderModule(vkd, device, m_context.getBinaryCollection().get("color_vert"), 0);
1810 	auto fragmentShaderModule	= createShaderModule(vkd, device, m_context.getBinaryCollection().get("color_frag"), 0);
1811 
1812 	// Graphics pipeline.
1813 	const vk::VkVertexInputBindingDescription vertexInputBindingDescription =
1814 	{
1815 		0u,									// deUint32					binding;
1816 		sizeof(Vertex4RGBA),				// deUint32					strideInBytes;
1817 		vk::VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputStepRate	inputRate;
1818 	};
1819 
1820 	const vk::VkVertexInputAttributeDescription	vertexInputAttributeDescriptions[2]	=
1821 	{
1822 		{
1823 			0u,									// deUint32	location;
1824 			0u,									// deUint32	binding;
1825 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
1826 			0u									// deUint32	offset;
1827 		},
1828 		{
1829 			1u,														// deUint32	location;
1830 			0u,														// deUint32	binding;
1831 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,						// VkFormat	format;
1832 			static_cast<deUint32>(offsetof(Vertex4RGBA, color)),	// deUint32	offset;
1833 		},
1834 	};
1835 
1836 	const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1837 	{
1838 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,					// VkStructureType							sType;
1839 		nullptr,																		// const void*								pNext;
1840 		0u,																				// VkPipelineVertexInputStateCreateFlags	flags;
1841 		1u,																				// deUint32									vertexBindingDescriptionCount;
1842 		&vertexInputBindingDescription,													// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1843 		static_cast<deUint32>(DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions)),	// deUint32									vertexAttributeDescriptionCount;
1844 		vertexInputAttributeDescriptions,												// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1845 	};
1846 
1847 	const std::vector<vk::VkViewport>	viewports	(1, makeViewport(renderSize));
1848 	const std::vector<vk::VkRect2D>		scissors	(1, makeRect2D(renderSize));
1849 
1850 	const vk::VkColorComponentFlags colorComponentFlags = (0u
1851 		| vk::VK_COLOR_COMPONENT_R_BIT
1852 		| vk::VK_COLOR_COMPONENT_G_BIT
1853 		| vk::VK_COLOR_COMPONENT_B_BIT
1854 		| vk::VK_COLOR_COMPONENT_A_BIT
1855 	);
1856 
1857 	// Color blend attachment state. Central aspect of the test.
1858 	const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1859 	{
1860 		VK_TRUE,							// VkBool32					blendEnable;
1861 		vk::VK_BLEND_FACTOR_CONSTANT_COLOR,	// VkBlendFactor			srcColorBlendFactor;
1862 		vk::VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstColorBlendFactor;
1863 		vk::VK_BLEND_OP_ADD,				// VkBlendOp				colorBlendOp;
1864 		vk::VK_BLEND_FACTOR_CONSTANT_ALPHA,	// VkBlendFactor			srcAlphaBlendFactor;
1865 		vk::VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstAlphaBlendFactor;
1866 		vk::VK_BLEND_OP_ADD,				// VkBlendOp				alphaBlendOp;
1867 		colorComponentFlags,				// VkColorComponentFlags	colorWriteMask;
1868 	};
1869 
1870 	const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1871 	{
1872 		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1873 		nullptr,														// const void*									pNext;
1874 		0u,																// VkPipelineColorBlendStateCreateFlags			flags;
1875 		false,															// VkBool32										logicOpEnable;
1876 		vk::VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1877 		1u,																// deUint32										attachmentCount;
1878 		&colorBlendAttachmentState,										// const VkPipelineColorBlendAttachmentState*	pAttachments;
1879 		{																// float										blendConstants[4];
1880 			m_params.blendConstants[0],
1881 			m_params.blendConstants[1],
1882 			m_params.blendConstants[2],
1883 			m_params.blendConstants[3],
1884 		},
1885 	};
1886 
1887 	auto graphicsPipeline = makeGraphicsPipeline(
1888 		vkd,										// const DeviceInterface&                        vk
1889 		device,										// const VkDevice                                device
1890 		pipelineLayout.get(),						// const VkPipelineLayout                        pipelineLayout
1891 		vertexShaderModule.get(),					// const VkShaderModule                          vertexShaderModule
1892 		DE_NULL,									// const VkShaderModule                          tessellationControlModule
1893 		DE_NULL,									// const VkShaderModule                          tessellationEvalModule
1894 		DE_NULL,									// const VkShaderModule                          geometryShaderModule
1895 		fragmentShaderModule.get(),					// const VkShaderModule                          fragmentShaderModule
1896 		renderPass.get(),							// const VkRenderPass                            renderPass
1897 		viewports,									// const std::vector<VkViewport>&                viewports
1898 		scissors,									// const std::vector<VkRect2D>&                  scissors
1899 		vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
1900 		0u,											// const deUint32                                subpass
1901 		0u,											// const deUint32                                patchControlPoints
1902 		&vertexInputStateParams,					// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
1903 		nullptr,									// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1904 		nullptr,									// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
1905 		nullptr,									// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
1906 		&colorBlendStateParams);					// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
1907 
1908 	// Vertex buffer
1909 	auto						quadTexture = createFullscreenQuad();
1910 	std::vector<Vertex4RGBA>	vertices;
1911 
1912 	// Keep position but replace texture coordinates with our own color.
1913 	vertices.reserve(quadTexture.size());
1914 	std::transform(begin(quadTexture), end(quadTexture), std::back_inserter(vertices),
1915 		[this](const decltype(quadTexture)::value_type& v) { return Vertex4RGBA{ v.position, this->m_params.quadColor }; });
1916 
1917 	const vk::VkDeviceSize			vtxBufferSize		= static_cast<vk::VkDeviceSize>(vertices.size() * sizeof(decltype(vertices)::value_type));
1918 	const vk::VkBufferCreateInfo	bufferCreateInfo	=
1919 	{
1920 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
1921 		nullptr,									// const void*			pNext;
1922 		0u,											// VkBufferCreateFlags	flags;
1923 		vtxBufferSize,								// VkDeviceSize			size;
1924 		vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,		// VkBufferUsageFlags	usage;
1925 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
1926 		1u,											// deUint32				queueFamilyIndexCount;
1927 		&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
1928 	};
1929 
1930 	vk::BufferWithMemory vertexBuffer(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible);
1931 
1932 	// Upload vertex data
1933 	deMemcpy(vertexBuffer.getAllocation().getHostPtr(), vertices.data(), static_cast<size_t>(vtxBufferSize));
1934 	flushAlloc(vkd, device, vertexBuffer.getAllocation());
1935 
1936 	// Create command pool
1937 	auto cmdPool = createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1938 
1939 	// Create and record command buffer
1940 	auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1941 	auto cmdBuffer		= cmdBufferPtr.get();
1942 
1943 	vk::VkClearValue clearValue;
1944 	clearValue.color.float32[0] = 0.0f;
1945 	clearValue.color.float32[1] = 0.0f;
1946 	clearValue.color.float32[2] = 0.0f;
1947 	clearValue.color.float32[3] = 1.0f;
1948 
1949 	const vk::VkDeviceSize vertexOffets[] = { 0u };
1950 
1951 	beginCommandBuffer(vkd, cmdBuffer, 0u);
1952 		beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), makeRect2D(renderSize), clearValue);
1953 			vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.get());
1954 			vkd.cmdBindVertexBuffers(cmdBuffer, 0, 1u, &vertexBuffer.get(), vertexOffets);
1955 			vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(vertices.size()), 1, 0, 0);
1956 		endRenderPass(vkd, cmdBuffer);
1957 	endCommandBuffer(vkd, cmdBuffer);
1958 
1959 	// Submit commands.
1960 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1961 
1962 	// Calculate reference final color.
1963 	const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_params.colorFormat);
1964 	const auto					formatInfo		= tcu::getTextureFormatInfo(tcuColorFormat);
1965 
1966 	tcu::Vec4 clampedBlendConstants	= m_params.blendConstants;
1967 	tcu::Vec4 clampedQuadColor		= m_params.quadColor;
1968 
1969 	for (int i = 0; i < tcu::Vec4::SIZE; ++i)
1970 	{
1971 		clampedBlendConstants[i]	= de::clamp(clampedBlendConstants[i],	formatInfo.valueMin[i], formatInfo.valueMax[i]);
1972 		clampedQuadColor[i]			= de::clamp(clampedQuadColor[i],		formatInfo.valueMin[i], formatInfo.valueMax[i]);
1973 	}
1974 
1975 	tcu::Vec4 referenceColor;
1976 	for (int i = 0; i < tcu::Vec4::SIZE; ++i)
1977 		referenceColor[i] = clampedBlendConstants[i] * clampedQuadColor[i];
1978 
1979 	// Compare result with reference color
1980 	const tcu::UVec2					renderSizeUV2		(renderSize.width, renderSize.height);
1981 	de::UniquePtr<tcu::TextureLevel>	result				(readColorAttachment(vkd, device, queue, queueFamilyIndex, allocator, colorImage.get(), m_params.colorFormat, renderSizeUV2).release());
1982 	const tcu::Vec4						threshold			(getFormatThreshold(tcuColorFormat));
1983 	const tcu::ConstPixelBufferAccess	pixelBufferAccess	= result->getAccess();
1984 
1985 	const bool compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "BlendClampCompare", "Blend clamping pixel comparison", referenceColor, pixelBufferAccess, threshold, tcu::COMPARE_LOG_ON_ERROR);
1986 
1987 	if (compareOk)
1988 		return tcu::TestStatus::pass("Pass");
1989 	else
1990 		return tcu::TestStatus::fail("Pixel mismatch");
1991 }
1992 
1993 } // anonymous
1994 
getBlendStateName(const VkPipelineColorBlendAttachmentState & blendState)1995 std::string getBlendStateName (const VkPipelineColorBlendAttachmentState& blendState)
1996 {
1997 	const char* shortBlendFactorNames[] =
1998 	{
1999 		"z",		// VK_BLEND_ZERO
2000 		"o",		// VK_BLEND_ONE
2001 		"sc",		// VK_BLEND_SRC_COLOR
2002 		"1msc",		// VK_BLEND_ONE_MINUS_SRC_COLOR
2003 		"dc",		// VK_BLEND_DEST_COLOR
2004 		"1mdc",		// VK_BLEND_ONE_MINUS_DEST_COLOR
2005 		"sa",		// VK_BLEND_SRC_ALPHA
2006 		"1msa",		// VK_BLEND_ONE_MINUS_SRC_ALPHA
2007 		"da",		// VK_BLEND_DEST_ALPHA
2008 		"1mda",		// VK_BLEND_ONE_MINUS_DEST_ALPHA
2009 		"cc",		// VK_BLEND_CONSTANT_COLOR
2010 		"1mcc",		// VK_BLEND_ONE_MINUS_CONSTANT_COLOR
2011 		"ca",		// VK_BLEND_CONSTANT_ALPHA
2012 		"1mca",		// VK_BLEND_ONE_MINUS_CONSTANT_ALPHA
2013 		"sas",		// VK_BLEND_SRC_ALPHA_SATURATE
2014 		"1ms1c",	// VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR
2015 		"1ms1a",	// VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA
2016 		"s1c",		// VK_BLEND_FACTOR_SRC1_COLOR
2017 		"s1a"		// VK_BLEND_FACTOR_SRC1_ALPHA
2018 	};
2019 
2020 	const char* blendOpNames[] =
2021 	{
2022 		"add",		// VK_BLEND_OP_ADD
2023 		"sub",		// VK_BLEND_OP_SUBTRACT
2024 		"rsub",		// VK_BLEND_OP_REVERSE_SUBTRACT
2025 		"min",		// VK_BLEND_OP_MIN
2026 		"max",		// VK_BLEND_OP_MAX
2027 	};
2028 
2029 	std::ostringstream shortName;
2030 
2031 	shortName << "color_" << shortBlendFactorNames[blendState.srcColorBlendFactor] << "_" << shortBlendFactorNames[blendState.dstColorBlendFactor] << "_" << blendOpNames[blendState.colorBlendOp];
2032 	shortName << "_alpha_" << shortBlendFactorNames[blendState.srcAlphaBlendFactor] << "_" << shortBlendFactorNames[blendState.dstAlphaBlendFactor] << "_" << blendOpNames[blendState.alphaBlendOp];
2033 
2034 	return shortName.str();
2035 }
2036 
getBlendStateSetName(const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])2037 std::string getBlendStateSetName (const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])
2038 {
2039 	std::ostringstream name;
2040 
2041 	for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
2042 	{
2043 		name << getBlendStateName(blendStates[quadNdx]);
2044 
2045 		if (quadNdx < BlendTest::QUAD_COUNT - 1)
2046 			name << "-";
2047 	}
2048 
2049 	return name.str();
2050 }
2051 
getBlendStateSetDescription(const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])2052 std::string getBlendStateSetDescription (const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])
2053 {
2054 	std::ostringstream description;
2055 
2056 	description << "Draws " << BlendTest::QUAD_COUNT << " quads with the following blend states:\n";
2057 
2058 	for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
2059 		description << blendStates[quadNdx] << "\n";
2060 
2061 	return description.str();
2062 }
2063 
getFormatCaseName(VkFormat format)2064 std::string getFormatCaseName (VkFormat format)
2065 {
2066 	const std::string fullName = getFormatName(format);
2067 
2068 	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
2069 
2070 	return de::toLower(fullName.substr(10));
2071 }
2072 
createBlendTests(tcu::TestContext & testCtx)2073 tcu::TestCaseGroup* createBlendTests (tcu::TestContext& testCtx)
2074 {
2075 	const deUint32 blendStatesPerFormat = 100 * BlendTest::QUAD_COUNT;
2076 
2077 	// Formats that are dEQP-compatible, non-integer and uncompressed
2078 	const VkFormat blendFormats[] =
2079 	{
2080 		VK_FORMAT_R4G4_UNORM_PACK8,
2081 		VK_FORMAT_R4G4B4A4_UNORM_PACK16,
2082 		VK_FORMAT_R5G6B5_UNORM_PACK16,
2083 		VK_FORMAT_R5G5B5A1_UNORM_PACK16,
2084 		VK_FORMAT_A1R5G5B5_UNORM_PACK16,
2085 		VK_FORMAT_R8_UNORM,
2086 		VK_FORMAT_R8_SNORM,
2087 		VK_FORMAT_R8_SRGB,
2088 		VK_FORMAT_R8G8_UNORM,
2089 		VK_FORMAT_R8G8_SNORM,
2090 		VK_FORMAT_R8G8_SRGB,
2091 		VK_FORMAT_R8G8B8_UNORM,
2092 		VK_FORMAT_R8G8B8_SNORM,
2093 		VK_FORMAT_R8G8B8_SRGB,
2094 		VK_FORMAT_R8G8B8A8_UNORM,
2095 		VK_FORMAT_R8G8B8A8_SNORM,
2096 		VK_FORMAT_R8G8B8A8_SRGB,
2097 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
2098 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2099 		VK_FORMAT_R16_UNORM,
2100 		VK_FORMAT_R16_SNORM,
2101 		VK_FORMAT_R16_SFLOAT,
2102 		VK_FORMAT_R16G16_UNORM,
2103 		VK_FORMAT_R16G16_SNORM,
2104 		VK_FORMAT_R16G16_SFLOAT,
2105 		VK_FORMAT_R16G16B16_UNORM,
2106 		VK_FORMAT_R16G16B16_SNORM,
2107 		VK_FORMAT_R16G16B16_SFLOAT,
2108 		VK_FORMAT_R16G16B16A16_UNORM,
2109 		VK_FORMAT_R16G16B16A16_SNORM,
2110 		VK_FORMAT_R16G16B16A16_SFLOAT,
2111 		VK_FORMAT_R32_SFLOAT,
2112 		VK_FORMAT_R32G32_SFLOAT,
2113 		VK_FORMAT_R32G32B32_SFLOAT,
2114 		VK_FORMAT_R32G32B32A32_SFLOAT,
2115 		VK_FORMAT_B10G11R11_UFLOAT_PACK32,
2116 		VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
2117 		VK_FORMAT_B4G4R4A4_UNORM_PACK16,
2118 		VK_FORMAT_B5G5R5A1_UNORM_PACK16,
2119 		VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
2120 		VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
2121 		VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
2122 	};
2123 
2124 	de::MovePtr<tcu::TestCaseGroup>				blendTests				(new tcu::TestCaseGroup(testCtx, "blend", "Blend tests"));
2125 	de::MovePtr<tcu::TestCaseGroup>				formatTests				(new tcu::TestCaseGroup(testCtx, "format", "Uses different blend formats"));
2126 	de::MovePtr<tcu::TestCaseGroup>				clampTests				(new tcu::TestCaseGroup(testCtx, "clamp", "Verifies clamping for normalized formats"));
2127 	de::MovePtr<tcu::TestCaseGroup>				dualSourceBlendTests	(new tcu::TestCaseGroup(testCtx, "dual_source", "Blend tests taking into account dual-source blend factors"));
2128 	de::MovePtr<tcu::TestCaseGroup>				dualSourceFormatTests	(new tcu::TestCaseGroup(testCtx, "format", "Uses different blend formats"));
2129 
2130 
2131 	BlendStateUniqueRandomIterator				blendStateItr			(blendStatesPerFormat, 123);
2132 	BlendStateUniqueRandomIteratorDualSource	dualSourceBlendStateItr	(blendStatesPerFormat, 123);
2133 
2134 	for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(blendFormats); formatNdx++)
2135 	{
2136 		const VkFormat					format			= blendFormats[formatNdx];
2137 
2138 		// Blend tests
2139 		{
2140 			de::MovePtr<tcu::TestCaseGroup>	formatTest		(new tcu::TestCaseGroup(testCtx,
2141 																					getFormatCaseName(format).c_str(),
2142 																					(std::string("Uses format ") + getFormatName(format)).c_str()));
2143 			de::MovePtr<tcu::TestCaseGroup>	blendStateTests;
2144 			{
2145 				std::ostringstream blendStateDescription;
2146 				blendStateDescription << "Combines blend factors, operators and channel write masks. The constant color used in all tests is " << BlendTest::s_blendConst;
2147 				blendStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", blendStateDescription.str().c_str()));
2148 			}
2149 
2150 			blendStateItr.reset();
2151 
2152 			while (blendStateItr.hasNext())
2153 			{
2154 				VkPipelineColorBlendAttachmentState quadBlendConfigs[BlendTest::QUAD_COUNT];
2155 
2156 				for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
2157 				{
2158 					quadBlendConfigs[quadNdx]					= blendStateItr.next();
2159 					quadBlendConfigs[quadNdx].colorWriteMask	= BlendTest::s_colorWriteMasks[quadNdx];
2160 				}
2161 
2162 				blendStateTests->addChild(new BlendTest(testCtx,
2163 														getBlendStateSetName(quadBlendConfigs),
2164 														getBlendStateSetDescription(quadBlendConfigs),
2165 														format,
2166 														quadBlendConfigs));
2167 			}
2168 			formatTest->addChild(blendStateTests.release());
2169 			formatTests->addChild(formatTest.release());
2170 		}
2171 
2172 		// Dual-Source blending tests
2173 		{
2174 			de::MovePtr<tcu::TestCaseGroup>	formatTest		(new tcu::TestCaseGroup(testCtx,
2175 																					getFormatCaseName(format).c_str(),
2176 																					(std::string("Uses format ") + getFormatName(format)).c_str()));
2177 			de::MovePtr<tcu::TestCaseGroup>	blendStateTests;
2178 			{
2179 				std::ostringstream blendStateDescription;
2180 				blendStateDescription << "Combines blend factors, operators and channel write masks. The constant color used in all tests is " << BlendTest::s_blendConst;
2181 				blendStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", blendStateDescription.str().c_str()));
2182 			}
2183 
2184 			dualSourceBlendStateItr.reset();
2185 
2186 			while (dualSourceBlendStateItr.hasNext())
2187 			{
2188 				VkPipelineColorBlendAttachmentState quadBlendConfigs[BlendTest::QUAD_COUNT];
2189 				deBool isDualSourceBlendTest = DE_FALSE;
2190 				for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
2191 				{
2192 					quadBlendConfigs[quadNdx]					= dualSourceBlendStateItr.next();
2193 					quadBlendConfigs[quadNdx].colorWriteMask	= BlendTest::s_colorWriteMasks[quadNdx];
2194 					isDualSourceBlendTest =
2195 						isDualSourceBlendTest ||
2196 						isSrc1BlendFactor(quadBlendConfigs[quadNdx].srcColorBlendFactor) ||
2197 						isSrc1BlendFactor(quadBlendConfigs[quadNdx].dstColorBlendFactor) ||
2198 						isSrc1BlendFactor(quadBlendConfigs[quadNdx].srcAlphaBlendFactor) ||
2199 						isSrc1BlendFactor(quadBlendConfigs[quadNdx].dstAlphaBlendFactor);
2200 				}
2201 
2202 				// Skip tests that don't have dual-source blend factors as they are already tested.
2203 				if (!isDualSourceBlendTest)
2204 					continue;
2205 
2206 				blendStateTests->addChild(new DualSourceBlendTest(testCtx,
2207 																  getBlendStateSetName(quadBlendConfigs),
2208 																  getBlendStateSetDescription(quadBlendConfigs),
2209 																  format,
2210 																  quadBlendConfigs));
2211 			}
2212 			formatTest->addChild(blendStateTests.release());
2213 			dualSourceFormatTests->addChild(formatTest.release());
2214 		}
2215 	}
2216 
2217 	// Subselection of formats that are easy to test for clamping.
2218 	const vk::VkFormat clampFormats[] =
2219 	{
2220 		vk::VK_FORMAT_R8G8B8A8_UNORM,
2221 		vk::VK_FORMAT_R8G8B8A8_SNORM,
2222 		vk::VK_FORMAT_B8G8R8A8_UNORM,
2223 		vk::VK_FORMAT_B8G8R8A8_SNORM,
2224 		vk::VK_FORMAT_R16G16B16A16_UNORM,
2225 		vk::VK_FORMAT_R16G16B16A16_SNORM,
2226 	};
2227 
2228 	for (int formatIdx = 0; formatIdx < DE_LENGTH_OF_ARRAY(clampFormats); ++formatIdx)
2229 	{
2230 		const auto& format = clampFormats[formatIdx];
2231 		ClampTestParams testParams;
2232 
2233 		testParams.colorFormat = format;
2234 
2235 		if (isUnormFormat(format))
2236 		{
2237 			testParams.quadColor[0] = 2.0f;
2238 			testParams.quadColor[1] = 0.5f;
2239 			testParams.quadColor[2] = 1.0f;
2240 			testParams.quadColor[3] = -1.0f;
2241 
2242 			testParams.blendConstants[0] = 0.5f;
2243 			testParams.blendConstants[1] = 2.0f;
2244 			testParams.blendConstants[2] = -1.0f;
2245 			testParams.blendConstants[3] = 1.0f;
2246 		}
2247 		else
2248 		{
2249 			testParams.quadColor[0] = 2.0f;
2250 			testParams.quadColor[1] = 0.5f;
2251 			testParams.quadColor[2] = 1.0f;
2252 			testParams.quadColor[3] = -2.0f;
2253 
2254 			testParams.blendConstants[0] = 0.5f;
2255 			testParams.blendConstants[1] = 2.0f;
2256 			testParams.blendConstants[2] = -2.0f;
2257 			testParams.blendConstants[3] = 1.0f;
2258 		}
2259 
2260 		clampTests->addChild(new ClampTest(testCtx, getFormatCaseName(format), std::string("Using format ") + getFormatName(format), testParams));
2261 	}
2262 
2263 	blendTests->addChild(formatTests.release());
2264 	blendTests->addChild(clampTests.release());
2265 
2266 	dualSourceBlendTests->addChild(dualSourceFormatTests.release());
2267 	blendTests->addChild(dualSourceBlendTests.release());
2268 
2269 	return blendTests.release();
2270 }
2271 
2272 } // pipeline
2273 } // vkt
2274