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