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