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