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