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