1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2020 The Khronos Group Inc.
6 * Copyright (c) 2020 Valve Corporation.
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 Logic Operators Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktPipelineLogicOpTests.hpp"
26 #include "vktPipelineImageUtil.hpp"
27
28 #include "vkQueryUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkImageWithMemory.hpp"
35
36 #include "tcuVectorUtil.hpp"
37 #include "tcuImageCompare.hpp"
38 #include "tcuTestLog.hpp"
39
40 #include <string>
41 #include <limits>
42
43 namespace vkt
44 {
45 namespace pipeline
46 {
47
48 using namespace vk;
49
50 namespace
51 {
52
isSupportedColorAttachmentFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)53 bool isSupportedColorAttachmentFormat (const InstanceInterface& instanceInterface,
54 VkPhysicalDevice device,
55 VkFormat format)
56 {
57 VkFormatProperties formatProps;
58 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
59
60 // Format also needs to be INT, UINT, or SINT but as we are the ones setting the
61 // color attachment format we only need to check that it is a valid color attachment
62 // format here.
63 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
64 }
65
66 struct TestParams
67 {
68 VkLogicOp logicOp; // Operation.
69 tcu::UVec4 fbColor; // Framebuffer color.
70 tcu::UVec4 quadColor; // Geometry color.
71 VkFormat format; // Framebuffer format.
72 std::string name; // Logic operator test name.
73 };
74
calcOpResult(VkLogicOp op,deUint32 src,deUint32 dst)75 deUint32 calcOpResult(VkLogicOp op, deUint32 src, deUint32 dst)
76 {
77 // See section 29.2 "Logical Operations" in the spec.
78 //
79 // AND: SRC & DST = 1010 & 1100 = 1000 = 0x8
80 // AND_REVERSE: SRC & ~DST = 0011 & 1010 = 0010 = 0x2
81 // COPY: SRC = 1010 = 1010 = 0xa
82 // AND_INVERTED: ~SRC & DST = 0101 & 1100 = 0100 = 0x4
83 // NO_OP: DST = 1010 = 1010 = 0xa
84 // XOR: SRC ^ DST = 1010 ^ 1100 = 0110 = 0x6
85 // OR: SRC | DST = 1010 | 1100 = 1110 = 0xe
86 // NOR: ~(SRC | DST) = ~(1010 | 1100) = 0001 = 0x1
87 // EQUIVALENT: ~(SRC ^ DST) = ~(1010 ^ 1100) = 1001 = 0x9
88 // INVERT: ~DST = ~1100 = 0011 = 0x3
89 // OR_REVERSE: SRC | ~DST = 1010 | 0011 = 1011 = 0xb
90 // COPY_INVERTED: ~SRC = 0101 = 0101 = 0x5
91 // OR_INVERTED: ~SRC | DST = 0101 | 1100 = 1101 = 0xd
92 // NAND: ~(SRC & DST) = ~(1010 &1100) = 0111 = 0x7
93 // SET: = 1111 = 1111 = 0xf (sets all bits)
94
95 switch (op)
96 {
97 case VK_LOGIC_OP_CLEAR: return (0u);
98 case VK_LOGIC_OP_AND: return (src & dst);
99 case VK_LOGIC_OP_AND_REVERSE: return (src & ~dst);
100 case VK_LOGIC_OP_COPY: return (src);
101 case VK_LOGIC_OP_AND_INVERTED: return (~src & dst);
102 case VK_LOGIC_OP_NO_OP: return (dst);
103 case VK_LOGIC_OP_XOR: return (src ^ dst);
104 case VK_LOGIC_OP_OR: return (src | dst);
105 case VK_LOGIC_OP_NOR: return (~(src | dst));
106 case VK_LOGIC_OP_EQUIVALENT: return (~(src ^ dst));
107 case VK_LOGIC_OP_INVERT: return (~dst);
108 case VK_LOGIC_OP_OR_REVERSE: return (src | ~dst);
109 case VK_LOGIC_OP_COPY_INVERTED: return (~src);
110 case VK_LOGIC_OP_OR_INVERTED: return (~src | dst);
111 case VK_LOGIC_OP_NAND: return (~(src & dst));
112 case VK_LOGIC_OP_SET: return (std::numeric_limits<deUint32>::max());
113 default: DE_ASSERT(false); break;
114 }
115
116 DE_ASSERT(false);
117 return 0u;
118 }
119
120 // Gets a bitmask to filter out unused bits according to the channel size (e.g. 0xFFu for 8-bit channels).
121 // channelSize in bytes.
getChannelMask(int channelSize)122 deUint32 getChannelMask (int channelSize)
123 {
124 DE_ASSERT(channelSize >= 1 && channelSize <= 4);
125
126 deUint64 mask = 1u;
127 mask <<= (channelSize * 8);
128 --mask;
129
130 return static_cast<deUint32>(mask);
131 }
132
133 class LogicOpTest : public vkt::TestCase
134 {
135 public:
136 LogicOpTest (tcu::TestContext& testCtx,
137 const std::string& name,
138 const std::string& description,
139 const TestParams &testParams);
140 virtual ~LogicOpTest (void);
141 virtual void initPrograms (SourceCollections& sourceCollections) const;
142 virtual void checkSupport (Context& context) const;
143 virtual TestInstance* createInstance (Context& context) const;
144
145 private:
146 TestParams m_params;
147 };
148
LogicOpTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestParams & testParams)149 LogicOpTest::LogicOpTest (tcu::TestContext& testCtx,
150 const std::string& name,
151 const std::string& description,
152 const TestParams& testParams)
153 : vkt::TestCase (testCtx, name, description)
154 , m_params (testParams)
155 {
156 DE_ASSERT(m_params.format != VK_FORMAT_UNDEFINED);
157 }
158
~LogicOpTest(void)159 LogicOpTest::~LogicOpTest (void)
160 {
161 }
162
checkSupport(Context & ctx) const163 void LogicOpTest::checkSupport (Context &ctx) const
164 {
165 const auto& features = ctx.getDeviceFeatures();
166
167 if (!features.logicOp)
168 TCU_THROW(NotSupportedError, "Logic operations not supported");
169
170 if (!isSupportedColorAttachmentFormat(ctx.getInstanceInterface(), ctx.getPhysicalDevice(), m_params.format))
171 TCU_THROW(NotSupportedError, "Unsupported color attachment format: " + std::string(getFormatName(m_params.format)));
172 }
173
initPrograms(SourceCollections & sourceCollections) const174 void LogicOpTest::initPrograms (SourceCollections& sourceCollections) const
175 {
176 sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
177 "#version 430\n"
178 "vec2 vdata[] = vec2[] (\n"
179 "vec2(-1.0, -1.0),\n"
180 "vec2(1.0, -1.0),\n"
181 "vec2(-1.0, 1.0),\n"
182 "vec2(1.0, 1.0));\n"
183 "void main (void)\n"
184 "{\n"
185 " gl_Position = vec4(vdata[gl_VertexIndex], 0.0, 1.0);\n"
186 "}\n");
187
188 sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(
189 "#version 430\n"
190 "layout(push_constant) uniform quadColor {\n"
191 " uvec4 val;\n"
192 "} QUAD_COLOR;\n"
193 "layout(location = 0) out uvec4 fragColor;\n"
194 "void main (void)\n"
195 "{\n"
196 " fragColor = QUAD_COLOR.val;\n"
197 "}\n");
198 }
199
200 class LogicOpTestInstance : public vkt::TestInstance
201 {
202 public:
203 LogicOpTestInstance(Context& context,
204 const TestParams& params);
205 ~LogicOpTestInstance(void);
206 virtual tcu::TestStatus iterate(void);
207
208 private:
209 tcu::TestStatus verifyImage(void);
210
211 TestParams m_params;
212
213 // Derived from m_params.
214 const tcu::TextureFormat m_tcuFormat;
215 const int m_numChannels;
216 const int m_channelSize;
217 const deUint32 m_channelMask;
218
219 const tcu::UVec2 m_renderSize;
220
221 VkImageCreateInfo m_colorImageCreateInfo;
222 de::MovePtr<ImageWithMemory> m_colorImage;
223 Move<VkImageView> m_colorAttachmentView;
224
225 Move<VkRenderPass> m_renderPass;
226 Move<VkFramebuffer> m_framebuffer;
227
228 Move<VkShaderModule> m_vertexShaderModule;
229 Move<VkShaderModule> m_fragmentShaderModule;
230
231 Move<VkPipelineLayout> m_pipelineLayout;
232 Move<VkPipeline> m_graphicsPipeline;
233
234 Move<VkCommandPool> m_cmdPool;
235 Move<VkCommandBuffer> m_cmdBuffer;
236 };
237
LogicOpTestInstance(Context & ctx,const TestParams & testParams)238 LogicOpTestInstance::LogicOpTestInstance (Context &ctx, const TestParams &testParams)
239 : vkt::TestInstance (ctx)
240 , m_params (testParams)
241 , m_tcuFormat (mapVkFormat(m_params.format))
242 , m_numChannels (tcu::getNumUsedChannels(m_tcuFormat.order))
243 , m_channelSize (tcu::getChannelSize(m_tcuFormat.type))
244 , m_channelMask (getChannelMask(m_channelSize))
245 , m_renderSize (32u, 32u)
246 {
247 DE_ASSERT(isUintFormat(m_params.format));
248
249 const DeviceInterface& vk = m_context.getDeviceInterface();
250 const VkDevice vkDevice = m_context.getDevice();
251 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
252 Allocator& memAlloc = m_context.getDefaultAllocator();
253 constexpr auto kPushConstantSize = static_cast<deUint32>(sizeof(m_params.quadColor));
254
255 // create color image
256 {
257 const VkImageCreateInfo colorImageParams =
258 {
259 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
260 DE_NULL, // const void* pNext;
261 0u, // VkImageCreateFlags flags;
262 VK_IMAGE_TYPE_2D, // VkImageType imageType;
263 m_params.format, // VkFormat format;
264 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
265 1u, // deUint32 mipLevels;
266 1u, // deUint32 arrayLayers;
267 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
268 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
269 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
270 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
271 1u, // deUint32 queueFamilyIndexCount;
272 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
273 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
274 };
275
276 m_colorImageCreateInfo = colorImageParams;
277 m_colorImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, vkDevice, memAlloc, m_colorImageCreateInfo, MemoryRequirement::Any));
278
279 // create color attachment view
280 const VkImageViewCreateInfo colorAttachmentViewParams =
281 {
282 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
283 DE_NULL, // const void* pNext;
284 0u, // VkImageViewCreateFlags flags;
285 m_colorImage->get(), // VkImage image;
286 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
287 m_params.format, // VkFormat format;
288 { VK_COMPONENT_SWIZZLE_IDENTITY,
289 VK_COMPONENT_SWIZZLE_IDENTITY,
290 VK_COMPONENT_SWIZZLE_IDENTITY,
291 VK_COMPONENT_SWIZZLE_IDENTITY },
292 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
293 };
294
295 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
296 }
297
298 m_renderPass = makeRenderPass(vk, vkDevice, m_params.format);
299 m_framebuffer = makeFramebuffer(vk, vkDevice, *m_renderPass, m_colorAttachmentView.get(), m_renderSize.x(), m_renderSize.y());
300
301 // create pipeline layout
302 {
303 const VkPushConstantRange pcRange =
304 {
305 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
306 0u, // deUint32 offset;
307 kPushConstantSize, // deUint32 size;
308 };
309
310 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
311 {
312 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
313 DE_NULL, // const void* pNext;
314 0u, // VkPipelineLayoutCreateFlags flags;
315 0u, // deUint32 setLayoutCount;
316 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
317 1u, // deUint32 pushConstantRangeCount;
318 &pcRange, // const VkPushConstantRange* pPushConstantRanges;
319 };
320
321 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
322 }
323
324 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
325 m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
326
327 // create pipeline
328 {
329 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = initVulkanStructure();
330
331 const std::vector<VkViewport> viewports (1, makeViewport(m_renderSize));
332 const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize));
333
334 VkColorComponentFlags colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
335 VK_COLOR_COMPONENT_G_BIT |
336 VK_COLOR_COMPONENT_B_BIT |
337 VK_COLOR_COMPONENT_A_BIT;
338
339 const VkPipelineColorBlendAttachmentState blendAttachmentState =
340 {
341 VK_FALSE, // VkBool32 blendEnable;
342 (VkBlendFactor) 0, // VkBlendFactor srcColorBlendFactor;
343 (VkBlendFactor) 0, // VkBlendFactor dstColorBlendFactor;
344 (VkBlendOp) 0, // VkBlendOp colorBlendOp;
345 (VkBlendFactor) 0, // VkBlendFactor srcAlphaBlendFactor;
346 (VkBlendFactor) 0, // VkBlendFactor dstAlphaBlendFactor;
347 (VkBlendOp) 0, // VkBlendOp alphaBlendOp;
348 colorWriteMask, // VkColorComponentFlags colorWriteMask;
349 };
350
351 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
352 {
353 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
354 DE_NULL, // const void* pNext;
355 DE_NULL, // VkPipelineColorBlendStateCreateFlags flags;
356 VK_TRUE, // VkBool32 logicOpEnable;
357 m_params.logicOp, // VkLogicOp logicOp;
358 1u, // uint32_t attachmentCount;
359 &blendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
360 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
361 };
362
363 m_graphicsPipeline = makeGraphicsPipeline(vk,
364 vkDevice, // const VkDevice device
365 *m_pipelineLayout, // const VkPipelineLayout pipelineLayout
366 *m_vertexShaderModule, // const VkShaderModule vertexShaderModule
367 DE_NULL, // const VkShaderModule tessellationControlModule
368 DE_NULL, // const VkShaderModule tessellationEvalModule
369 DE_NULL, // const VkShaderModule geometryShaderModule
370 *m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule
371 *m_renderPass, // const VkRenderPass renderPass
372 viewports, // const std::vector<VkViewport>& viewports
373 scissors, // const std::vector<VkRect2D>& scissors
374 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // const VkPrimitiveTopology topology
375 0u, // const deUint32 subpass
376 0u, // const deUint32 patchControlPoints
377 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
378 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
379 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
380 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
381 &colorBlendStateParams); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
382 }
383
384 // create command pool
385 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
386
387 // allocate and record command buffer
388 {
389 // Prepare clear color value and quad color taking into account the channel mask.
390 VkClearValue attachmentClearValue;
391 tcu::UVec4 quadColor(0u, 0u, 0u, 0u);
392
393 deMemset(&attachmentClearValue.color, 0, sizeof(attachmentClearValue.color));
394 for (int c = 0; c < m_numChannels; ++c)
395 attachmentClearValue.color.uint32[c] = (m_params.fbColor[c] & m_channelMask);
396
397 for (int c = 0; c < m_numChannels; ++c)
398 quadColor[c] = (m_params.quadColor[c] & m_channelMask);
399
400 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
401
402 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
403 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
404
405 // Update push constant values
406 vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, kPushConstantSize, &quadColor);
407
408 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
409 vk.cmdDraw(*m_cmdBuffer, 4u, 1u, 0u, 0u);
410 endRenderPass(vk, *m_cmdBuffer);
411 endCommandBuffer(vk, *m_cmdBuffer);
412 }
413 }
414
~LogicOpTestInstance(void)415 LogicOpTestInstance::~LogicOpTestInstance (void)
416 {
417 }
418
iterate(void)419 tcu::TestStatus LogicOpTestInstance::iterate (void)
420 {
421 const DeviceInterface& vk = m_context.getDeviceInterface();
422 const VkDevice vkDevice = m_context.getDevice();
423 const VkQueue queue = m_context.getUniversalQueue();
424
425 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
426 return verifyImage();
427 }
428
verifyImage(void)429 tcu::TestStatus LogicOpTestInstance::verifyImage (void)
430 {
431 const DeviceInterface& vk = m_context.getDeviceInterface();
432 const VkDevice vkDevice = m_context.getDevice();
433 const VkQueue queue = m_context.getUniversalQueue();
434 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
435 Allocator& allocator = m_context.getDefaultAllocator();
436 auto& log = m_context.getTestContext().getLog();
437
438 const auto result = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, m_colorImage->get(), m_params.format, m_renderSize).release();
439 const auto resultAccess = result->getAccess();
440 const int iWidth = static_cast<int>(m_renderSize.x());
441 const int iHeight = static_cast<int>(m_renderSize.y());
442 tcu::UVec4 expectedColor (0u, 0u, 0u, 0u); // Overwritten below.
443 tcu::TextureLevel referenceTexture (m_tcuFormat, iWidth, iHeight);
444 auto referenceAccess = referenceTexture.getAccess();
445 tcu::UVec4 threshold (0u, 0u, 0u, 0u); // Exact results.
446
447 // Calculate proper expected color values.
448 for (int c = 0; c < m_numChannels; ++c)
449 {
450 expectedColor[c] = calcOpResult(m_params.logicOp, m_params.quadColor[c], m_params.fbColor[c]);
451 expectedColor[c] &= m_channelMask;
452 }
453
454 for (int y = 0; y < iHeight; ++y)
455 for (int x = 0; x < iWidth; ++x)
456 referenceAccess.setPixel(expectedColor, x, y);
457
458 // Check result.
459 bool resultOk = tcu::intThresholdCompare(log, "TestResults", "Test Result Images", referenceAccess, resultAccess, threshold, tcu::COMPARE_LOG_ON_ERROR);
460
461 if (!resultOk)
462 TCU_FAIL("Result does not match expected values; check log for details");
463
464 return tcu::TestStatus::pass("Pass");
465 }
466
createInstance(Context & context) const467 TestInstance *LogicOpTest::createInstance (Context& context) const
468 {
469 return new LogicOpTestInstance(context, m_params);
470 }
471
getSimpleFormatName(VkFormat format)472 std::string getSimpleFormatName (VkFormat format)
473 {
474 return de::toLower(std::string(getFormatName(format)).substr(std::string("VK_FORMAT_").size()));
475 }
476
477 } // anonymous namespace
478
createLogicOpTests(tcu::TestContext & testCtx)479 tcu::TestCaseGroup* createLogicOpTests (tcu::TestContext& testCtx)
480 {
481 de::MovePtr<tcu::TestCaseGroup> logicOpTests (new tcu::TestCaseGroup(testCtx, "logic_op", "Logical Operations tests"));
482
483 // 4 bits are enough to check all possible combinations of logical operation inputs at once, for example s AND d:
484 //
485 // 1 0 1 0
486 // AND 1 1 0 0
487 // ------------
488 // 1 0 0 0
489 //
490 // However, we will choose color values such that both higher bits and lower bits are used, and the implementation will not be
491 // able to mix channels by mistake.
492 //
493 // 0011 0101 1010 1100
494 // 3 5 a c
495 // 0101 0011 1100 1010
496 // 5 3 c a
497
498 const tcu::UVec4 kQuadColor = { 0x35acU, 0x5ac3U, 0xac35U, 0xc35aU };
499 const tcu::UVec4 kFbColor = { 0x53caU, 0x3ca5U, 0xca53U, 0xa53cU };
500
501 // Note: the format will be chosen and changed later.
502 std::vector<TestParams> logicOpTestParams =
503 {
504 { VK_LOGIC_OP_CLEAR, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "clear" },
505 { VK_LOGIC_OP_AND, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "and" },
506 { VK_LOGIC_OP_AND_REVERSE, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "and_reverse" },
507 { VK_LOGIC_OP_COPY, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "copy" },
508 { VK_LOGIC_OP_AND_INVERTED, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "and_inverted" },
509 { VK_LOGIC_OP_NO_OP, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "no_op" },
510 { VK_LOGIC_OP_XOR, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "xor" },
511 { VK_LOGIC_OP_OR, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "or" },
512 { VK_LOGIC_OP_NOR, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "nor" },
513 { VK_LOGIC_OP_EQUIVALENT, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "equivalent" },
514 { VK_LOGIC_OP_INVERT, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "invert" },
515 { VK_LOGIC_OP_OR_REVERSE, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "or_reverse" },
516 { VK_LOGIC_OP_COPY_INVERTED, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "copy_inverted" },
517 { VK_LOGIC_OP_OR_INVERTED, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "or_inverted" },
518 { VK_LOGIC_OP_NAND, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "nand" },
519 { VK_LOGIC_OP_SET, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "set" },
520 };
521
522 const VkFormat formatList[] =
523 {
524 VK_FORMAT_R8_UINT,
525 VK_FORMAT_R8G8_UINT,
526 VK_FORMAT_R8G8B8_UINT,
527 VK_FORMAT_B8G8R8_UINT,
528 VK_FORMAT_R8G8B8A8_UINT,
529 VK_FORMAT_B8G8R8A8_UINT,
530 VK_FORMAT_R16_UINT,
531 VK_FORMAT_R16G16_UINT,
532 VK_FORMAT_R16G16B16_UINT,
533 VK_FORMAT_R16G16B16A16_UINT,
534 VK_FORMAT_R32_UINT,
535 VK_FORMAT_R32G32_UINT,
536 VK_FORMAT_R32G32B32_UINT,
537 VK_FORMAT_R32G32B32A32_UINT,
538 };
539
540 for (int formatIdx = 0; formatIdx < DE_LENGTH_OF_ARRAY(formatList); ++formatIdx)
541 {
542 const auto& format = formatList[formatIdx];
543 const auto formatName = getSimpleFormatName(format);
544 const auto formatDesc = "Logical operator tests with format " + formatName;
545
546 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatDesc.c_str()));
547
548 for (auto& params : logicOpTestParams)
549 {
550 params.format = format;
551 formatGroup->addChild(new LogicOpTest(testCtx, params.name, "Tests the " + params.name + " logical operator", params));
552 }
553
554 logicOpTests->addChild(formatGroup.release());
555 }
556
557 return logicOpTests.release();
558 }
559
560 } // pipeline namespace
561 } // vkt namespace
562