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