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