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