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