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