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