1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Imagination Technologies Ltd.
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Stencil Tests
25 *//*--------------------------------------------------------------------*/
26
27 #include "vktPipelineStencilTests.hpp"
28 #include "vktPipelineClearUtil.hpp"
29 #include "vktPipelineImageUtil.hpp"
30 #include "vktPipelineVertexUtil.hpp"
31 #include "vktPipelineReferenceRenderer.hpp"
32 #include "vktPipelineUniqueRandomIterator.hpp"
33 #include "vktTestCase.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkRef.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43 #include "tcuImageCompare.hpp"
44 #include "deMemory.h"
45 #include "deRandom.hpp"
46 #include "deStringUtil.hpp"
47 #include "deUniquePtr.hpp"
48
49 #include <algorithm>
50 #include <sstream>
51 #include <vector>
52
53 namespace vkt
54 {
55 namespace pipeline
56 {
57
58 using namespace vk;
59
60 namespace
61 {
62
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)63 bool isSupportedDepthStencilFormat(const InstanceInterface &instanceInterface, VkPhysicalDevice device, VkFormat format)
64 {
65 VkFormatProperties formatProps;
66
67 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
68
69 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
70 }
71
72 class StencilOpStateUniqueRandomIterator : public UniqueRandomIterator<VkStencilOpState>
73 {
74 public:
75 StencilOpStateUniqueRandomIterator(int seed);
~StencilOpStateUniqueRandomIterator(void)76 virtual ~StencilOpStateUniqueRandomIterator(void)
77 {
78 }
79 virtual VkStencilOpState getIndexedValue(uint32_t index);
80
81 private:
82 // Pre-calculated constants
83 const static uint32_t s_stencilOpsLength;
84 const static uint32_t s_stencilOpsLength2;
85 const static uint32_t s_stencilOpsLength3;
86 const static uint32_t s_compareOpsLength;
87
88 // Total number of cross-combinations of (stencilFailOp x stencilPassOp x stencilDepthFailOp x stencilCompareOp)
89 const static uint32_t s_totalStencilOpStates;
90 };
91
92 class StencilTest : public vkt::TestCase
93 {
94 public:
95 enum
96 {
97 QUAD_COUNT = 4
98 };
99
100 struct StencilStateConfig
101 {
102 uint32_t frontReadMask;
103 uint32_t frontWriteMask;
104 uint32_t frontRef;
105
106 uint32_t backReadMask;
107 uint32_t backWriteMask;
108 uint32_t backRef;
109 };
110
111 const static StencilStateConfig s_stencilStateConfigs[QUAD_COUNT];
112 const static float s_quadDepths[QUAD_COUNT];
113
114 StencilTest(tcu::TestContext &testContext, const std::string &name,
115 PipelineConstructionType pipelineConstructionType, VkFormat stencilFormat,
116 const VkStencilOpState &stencilOpStateFront, const VkStencilOpState &stencilOpStateBack,
117 const bool colorAttachmentEnable, const bool separateDepthStencilLayouts);
118 virtual ~StencilTest(void) = default;
119 virtual void initPrograms(SourceCollections &sourceCollections) const;
120 virtual void checkSupport(Context &context) const;
121 virtual TestInstance *createInstance(Context &context) const;
122
123 private:
124 PipelineConstructionType m_pipelineConstructionType;
125 VkFormat m_stencilFormat;
126 const VkStencilOpState m_stencilOpStateFront;
127 const VkStencilOpState m_stencilOpStateBack;
128 const bool m_colorAttachmentEnable;
129 const bool m_separateDepthStencilLayouts;
130 };
131
132 class StencilTestInstance : public vkt::TestInstance
133 {
134 public:
135 StencilTestInstance(Context &context, PipelineConstructionType pipelineConstructionType, VkFormat stencilFormat,
136 const VkStencilOpState &stencilOpStatesFront, const VkStencilOpState &stencilOpStatesBack,
137 const bool colorAttachmentEnable, const bool separateDepthStencilLayouts);
138 virtual ~StencilTestInstance(void) = default;
139 virtual tcu::TestStatus iterate(void);
140
141 private:
142 tcu::TestStatus verifyImage(void);
143
144 VkStencilOpState m_stencilOpStateFront;
145 VkStencilOpState m_stencilOpStateBack;
146 const bool m_colorAttachmentEnable;
147 const bool m_separateDepthStencilLayouts;
148 const tcu::UVec2 m_renderSize;
149 const VkFormat m_colorFormat;
150 const VkFormat m_stencilFormat;
151 VkImageSubresourceRange m_stencilImageSubresourceRange;
152
153 VkImageCreateInfo m_colorImageCreateInfo;
154 Move<VkImage> m_colorImage;
155 de::MovePtr<Allocation> m_colorImageAlloc;
156 Move<VkImage> m_stencilImage;
157 de::MovePtr<Allocation> m_stencilImageAlloc;
158 Move<VkImageView> m_colorAttachmentView;
159 Move<VkImageView> m_stencilAttachmentView;
160 RenderPassWrapper m_renderPass;
161 Move<VkFramebuffer> m_framebuffer;
162
163 ShaderWrapper m_vertexShaderModule;
164 ShaderWrapper m_fragmentShaderModule;
165
166 Move<VkBuffer> m_vertexBuffer;
167 std::vector<Vertex4RGBA> m_vertices;
168 de::MovePtr<Allocation> m_vertexBufferAlloc;
169
170 PipelineLayoutWrapper m_pipelineLayout;
171 GraphicsPipelineWrapper m_graphicsPipelines[StencilTest::QUAD_COUNT];
172
173 Move<VkCommandPool> m_cmdPool;
174 Move<VkCommandBuffer> m_cmdBuffer;
175 };
176
177 const VkStencilOp stencilOps[] = {VK_STENCIL_OP_KEEP,
178 VK_STENCIL_OP_ZERO,
179 VK_STENCIL_OP_REPLACE,
180 VK_STENCIL_OP_INCREMENT_AND_CLAMP,
181 VK_STENCIL_OP_DECREMENT_AND_CLAMP,
182 VK_STENCIL_OP_INVERT,
183 VK_STENCIL_OP_INCREMENT_AND_WRAP,
184 VK_STENCIL_OP_DECREMENT_AND_WRAP};
185
186 const VkCompareOp compareOps[] = {VK_COMPARE_OP_NEVER,
187 VK_COMPARE_OP_LESS,
188 VK_COMPARE_OP_EQUAL,
189 VK_COMPARE_OP_LESS_OR_EQUAL,
190 VK_COMPARE_OP_GREATER,
191 VK_COMPARE_OP_NOT_EQUAL,
192 VK_COMPARE_OP_GREATER_OR_EQUAL,
193 VK_COMPARE_OP_ALWAYS};
194
195 // StencilOpStateUniqueRandomIterator
196
197 const uint32_t StencilOpStateUniqueRandomIterator::s_stencilOpsLength = DE_LENGTH_OF_ARRAY(stencilOps);
198 const uint32_t StencilOpStateUniqueRandomIterator::s_stencilOpsLength2 = s_stencilOpsLength * s_stencilOpsLength;
199 const uint32_t StencilOpStateUniqueRandomIterator::s_stencilOpsLength3 = s_stencilOpsLength2 * s_stencilOpsLength;
200 const uint32_t StencilOpStateUniqueRandomIterator::s_compareOpsLength = DE_LENGTH_OF_ARRAY(compareOps);
201 const uint32_t StencilOpStateUniqueRandomIterator::s_totalStencilOpStates = s_stencilOpsLength3 * s_compareOpsLength;
202
StencilOpStateUniqueRandomIterator(int seed)203 StencilOpStateUniqueRandomIterator::StencilOpStateUniqueRandomIterator(int seed)
204 : UniqueRandomIterator<VkStencilOpState>(s_totalStencilOpStates, s_totalStencilOpStates, seed)
205 {
206 }
207
getIndexedValue(uint32_t index)208 VkStencilOpState StencilOpStateUniqueRandomIterator::getIndexedValue(uint32_t index)
209 {
210 const uint32_t stencilCompareOpIndex = index / s_stencilOpsLength3;
211 const uint32_t stencilCompareOpSeqIndex = stencilCompareOpIndex * s_stencilOpsLength3;
212
213 const uint32_t stencilDepthFailOpIndex = (index - stencilCompareOpSeqIndex) / s_stencilOpsLength2;
214 const uint32_t stencilDepthFailOpSeqIndex = stencilDepthFailOpIndex * s_stencilOpsLength2;
215
216 const uint32_t stencilPassOpIndex =
217 (index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex) / s_stencilOpsLength;
218 const uint32_t stencilPassOpSeqIndex = stencilPassOpIndex * s_stencilOpsLength;
219
220 const uint32_t stencilFailOpIndex =
221 index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex - stencilPassOpSeqIndex;
222
223 const VkStencilOpState stencilOpState = {
224 stencilOps[stencilFailOpIndex], // VkStencilOp failOp;
225 stencilOps[stencilPassOpIndex], // VkStencilOp passOp;
226 stencilOps[stencilDepthFailOpIndex], // VkStencilOp depthFailOp;
227 compareOps[stencilCompareOpIndex], // VkCompareOp compareOp;
228 0x0, // uint32_t compareMask;
229 0x0, // uint32_t writeMask;
230 0x0 // uint32_t reference;
231 };
232
233 return stencilOpState;
234 }
235
236 // StencilTest
237
238 const StencilTest::StencilStateConfig StencilTest::s_stencilStateConfigs[QUAD_COUNT] = {
239 // frontReadMask frontWriteMask frontRef backReadMask backWriteMask backRef
240 {0xFF, 0xFF, 0xAB, 0xF0, 0xFF, 0xFF},
241 {0xFF, 0xF0, 0xCD, 0xF0, 0xF0, 0xEF},
242 {0xF0, 0x0F, 0xEF, 0xFF, 0x0F, 0xCD},
243 {0xF0, 0x01, 0xFF, 0xFF, 0x01, 0xAB}};
244
245 const float StencilTest::s_quadDepths[QUAD_COUNT] = {0.1f, 0.0f, 0.3f, 0.2f};
246
StencilTest(tcu::TestContext & testContext,const std::string & name,PipelineConstructionType pipelineConstructionType,VkFormat stencilFormat,const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack,const bool colorAttachmentEnable,const bool separateDepthStencilLayouts)247 StencilTest::StencilTest(tcu::TestContext &testContext, const std::string &name,
248 PipelineConstructionType pipelineConstructionType, VkFormat stencilFormat,
249 const VkStencilOpState &stencilOpStateFront, const VkStencilOpState &stencilOpStateBack,
250 const bool colorAttachmentEnable, const bool separateDepthStencilLayouts)
251 : vkt::TestCase(testContext, name)
252 , m_pipelineConstructionType(pipelineConstructionType)
253 , m_stencilFormat(stencilFormat)
254 , m_stencilOpStateFront(stencilOpStateFront)
255 , m_stencilOpStateBack(stencilOpStateBack)
256 , m_colorAttachmentEnable(colorAttachmentEnable)
257 , m_separateDepthStencilLayouts(separateDepthStencilLayouts)
258 {
259 }
260
checkSupport(Context & context) const261 void StencilTest::checkSupport(Context &context) const
262 {
263 if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_stencilFormat))
264 throw tcu::NotSupportedError(std::string("Unsupported depth/stencil format: ") +
265 getFormatName(m_stencilFormat));
266
267 if (m_separateDepthStencilLayouts &&
268 !context.isDeviceFunctionalitySupported("VK_KHR_separate_depth_stencil_layouts"))
269 TCU_THROW(NotSupportedError, "VK_KHR_separate_depth_stencil_layouts is not supported");
270
271 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
272 m_pipelineConstructionType);
273
274 #ifndef CTS_USES_VULKANSC
275 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
276 !context.getPortabilitySubsetFeatures().separateStencilMaskRef)
277 TCU_THROW(
278 NotSupportedError,
279 "VK_KHR_portability_subset: Separate stencil mask references are not supported by this implementation");
280 #endif // CTS_USES_VULKANSC
281 }
282
createInstance(Context & context) const283 TestInstance *StencilTest::createInstance(Context &context) const
284 {
285 return new StencilTestInstance(context, m_pipelineConstructionType, m_stencilFormat, m_stencilOpStateFront,
286 m_stencilOpStateBack, m_colorAttachmentEnable, m_separateDepthStencilLayouts);
287 }
288
initPrograms(SourceCollections & sourceCollections) const289 void StencilTest::initPrograms(SourceCollections &sourceCollections) const
290 {
291 if (m_colorAttachmentEnable)
292 {
293 sourceCollections.glslSources.add("color_vert")
294 << glu::VertexSource("#version 310 es\n"
295 "layout(location = 0) in vec4 position;\n"
296 "layout(location = 1) in vec4 color;\n"
297 "layout(location = 0) out highp vec4 vtxColor;\n"
298 "void main (void)\n"
299 "{\n"
300 " gl_Position = position;\n"
301 " vtxColor = color;\n"
302 "}\n");
303
304 sourceCollections.glslSources.add("color_frag")
305 << glu::FragmentSource("#version 310 es\n"
306 "layout(location = 0) in highp vec4 vtxColor;\n"
307 "layout(location = 0) out highp vec4 fragColor;\n"
308 "void main (void)\n"
309 "{\n"
310 " fragColor = vtxColor;\n"
311 "}\n");
312 }
313 else
314 {
315 sourceCollections.glslSources.add("color_vert") << glu::VertexSource("#version 310 es\n"
316 "layout(location = 0) in vec4 position;\n"
317 "layout(location = 1) in vec4 color;\n"
318 "void main (void)\n"
319 "{\n"
320 " gl_Position = position;\n"
321 "}\n");
322 }
323 }
324
325 // StencilTestInstance
326
StencilTestInstance(Context & context,PipelineConstructionType pipelineConstructionType,VkFormat stencilFormat,const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack,const bool colorAttachmentEnable,const bool separateDepthStencilLayouts)327 StencilTestInstance::StencilTestInstance(Context &context, PipelineConstructionType pipelineConstructionType,
328 VkFormat stencilFormat, const VkStencilOpState &stencilOpStateFront,
329 const VkStencilOpState &stencilOpStateBack, const bool colorAttachmentEnable,
330 const bool separateDepthStencilLayouts)
331 : vkt::TestInstance(context)
332 , m_stencilOpStateFront(stencilOpStateFront)
333 , m_stencilOpStateBack(stencilOpStateBack)
334 , m_colorAttachmentEnable(colorAttachmentEnable)
335 , m_separateDepthStencilLayouts(separateDepthStencilLayouts)
336 , m_renderSize(32, 32)
337 , m_colorFormat(colorAttachmentEnable ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED)
338 , m_stencilFormat(stencilFormat)
339 , m_graphicsPipelines{{context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
340 context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
341 {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
342 context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
343 {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
344 context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
345 {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
346 context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType}}
347 {
348 const DeviceInterface &vk = context.getDeviceInterface();
349 const VkDevice vkDevice = context.getDevice();
350 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
351 SimpleAllocator memAlloc(
352 vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
353 const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
354 VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
355
356 // Create color image
357 if (m_colorAttachmentEnable)
358 {
359 const VkImageCreateInfo colorImageParams = {
360 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
361 DE_NULL, // const void* pNext;
362 0u, // VkImageCreateFlags flags;
363 VK_IMAGE_TYPE_2D, // VkImageType imageType;
364 m_colorFormat, // VkFormat format;
365 {m_renderSize.x(), m_renderSize.y(), 1u}, // VkExtent3D extent;
366 1u, // uint32_t mipLevels;
367 1u, // uint32_t arrayLayers;
368 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
369 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
370 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
371 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
372 1u, // uint32_t queueFamilyIndexCount;
373 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
374 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
375 };
376
377 m_colorImageCreateInfo = colorImageParams;
378 m_colorImage = createImage(vk, vkDevice, &m_colorImageCreateInfo);
379
380 // Allocate and bind color image memory
381 m_colorImageAlloc =
382 memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
383 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(),
384 m_colorImageAlloc->getOffset()));
385 }
386
387 // Create stencil image
388 {
389 const VkImageUsageFlags usageFlags =
390 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
391
392 const VkImageCreateInfo stencilImageParams = {
393 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
394 DE_NULL, // const void* pNext;
395 0u, // VkImageCreateFlags flags;
396 VK_IMAGE_TYPE_2D, // VkImageType imageType;
397 m_stencilFormat, // VkFormat format;
398 {m_renderSize.x(), m_renderSize.y(), 1u}, // VkExtent3D extent;
399 1u, // uint32_t mipLevels;
400 1u, // uint32_t arrayLayers;
401 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
402 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
403 usageFlags, // VkImageUsageFlags usage;
404 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
405 1u, // uint32_t queueFamilyIndexCount;
406 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
407 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
408 };
409
410 m_stencilImage = createImage(vk, vkDevice, &stencilImageParams);
411
412 // Allocate and bind stencil image memory
413 m_stencilImageAlloc =
414 memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_stencilImage), MemoryRequirement::Any);
415 VK_CHECK(vk.bindImageMemory(vkDevice, *m_stencilImage, m_stencilImageAlloc->getMemory(),
416 m_stencilImageAlloc->getOffset()));
417
418 const VkImageAspectFlags aspect = (mapVkFormat(m_stencilFormat).order == tcu::TextureFormat::DS ?
419 VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT :
420 VK_IMAGE_ASPECT_STENCIL_BIT);
421 m_stencilImageSubresourceRange =
422 makeImageSubresourceRange(aspect, 0u, stencilImageParams.mipLevels, 0u, stencilImageParams.arrayLayers);
423 }
424
425 // Create color attachment view
426 if (m_colorAttachmentEnable)
427 {
428 const VkImageViewCreateInfo colorAttachmentViewParams = {
429 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
430 DE_NULL, // const void* pNext;
431 0u, // VkImageViewCreateFlags flags;
432 *m_colorImage, // VkImage image;
433 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
434 m_colorFormat, // VkFormat format;
435 componentMappingRGBA, // VkComponentMapping components;
436 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
437 };
438
439 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
440 }
441
442 // Create stencil attachment view
443 {
444 const VkImageViewCreateInfo stencilAttachmentViewParams = {
445 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
446 DE_NULL, // const void* pNext;
447 0u, // VkImageViewCreateFlags flags;
448 *m_stencilImage, // VkImage image;
449 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
450 m_stencilFormat, // VkFormat format;
451 componentMappingRGBA, // VkComponentMapping components;
452 m_stencilImageSubresourceRange, // VkImageSubresourceRange subresourceRange;
453 };
454
455 m_stencilAttachmentView = createImageView(vk, vkDevice, &stencilAttachmentViewParams);
456 }
457
458 // Create render pass
459 m_renderPass = RenderPassWrapper(pipelineConstructionType, vk, vkDevice, m_colorFormat, m_stencilFormat);
460
461 // Create framebuffer
462 {
463 std::vector<VkImage> images;
464 std::vector<VkImageView> attachmentBindInfos;
465
466 if (m_colorAttachmentEnable)
467 {
468 images.push_back(*m_colorImage);
469 attachmentBindInfos.push_back(*m_colorAttachmentView);
470 }
471
472 images.push_back(*m_stencilImage);
473 attachmentBindInfos.push_back(*m_stencilAttachmentView);
474
475 const VkFramebufferCreateInfo framebufferParams = {
476 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
477 DE_NULL, // const void* pNext;
478 0u, // VkFramebufferCreateFlags flags;
479 *m_renderPass, // VkRenderPass renderPass;
480 (uint32_t)attachmentBindInfos.size(), // uint32_t attachmentCount;
481 attachmentBindInfos.data(), // const VkImageView* pAttachments;
482 (uint32_t)m_renderSize.x(), // uint32_t width;
483 (uint32_t)m_renderSize.y(), // uint32_t height;
484 1u // uint32_t layers;
485 };
486
487 m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
488 }
489
490 // Create pipeline layout
491 {
492 const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
493 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
494 DE_NULL, // const void* pNext;
495 0u, // VkPipelineLayoutCreateFlags flags;
496 0u, // uint32_t setLayoutCount;
497 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
498 0u, // uint32_t pushConstantRangeCount;
499 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
500 };
501
502 m_pipelineLayout = PipelineLayoutWrapper(pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
503 }
504
505 m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
506 if (m_colorAttachmentEnable)
507 m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
508
509 // Create pipeline
510 {
511 const VkVertexInputBindingDescription vertexInputBindingDescription{
512 0u, // uint32_t binding;
513 sizeof(Vertex4RGBA), // uint32_t strideInBytes;
514 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
515 };
516
517 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2]{
518 {
519 0u, // uint32_t location;
520 0u, // uint32_t binding;
521 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
522 0u // uint32_t offsetInBytes;
523 },
524 {
525 1u, // uint32_t location;
526 0u, // uint32_t binding;
527 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
528 offsetof(Vertex4RGBA, color), // uint32_t offsetInBytes;
529 }};
530
531 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams{
532 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
533 DE_NULL, // const void* pNext;
534 0u, // VkPipelineVertexInputStateCreateFlags flags;
535 1u, // uint32_t vertexBindingDescriptionCount;
536 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
537 2u, // uint32_t vertexAttributeDescriptionCount;
538 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
539 };
540
541 const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
542 const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
543
544 const bool isDepthEnabled = (vk::mapVkFormat(m_stencilFormat).order != tcu::TextureFormat::S);
545
546 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams{
547 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
548 DE_NULL, // const void* pNext;
549 0u, // VkPipelineDepthStencilStateCreateFlags flags;
550 isDepthEnabled, // VkBool32 depthTestEnable;
551 isDepthEnabled, // VkBool32 depthWriteEnable;
552 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
553 false, // VkBool32 depthBoundsTestEnable;
554 true, // VkBool32 stencilTestEnable;
555 m_stencilOpStateFront, // VkStencilOpState front;
556 m_stencilOpStateBack, // VkStencilOpState back;
557 0.0f, // float minDepthBounds;
558 1.0f // float maxDepthBounds;
559 };
560
561 // Make sure rasterization is not disabled when the fragment shader is missing.
562 const vk::VkPipelineRasterizationStateCreateInfo rasterizationStateParams{
563 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
564 nullptr, // const void* pNext;
565 0u, // VkPipelineRasterizationStateCreateFlags flags;
566 VK_FALSE, // VkBool32 depthClampEnable;
567 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
568 vk::VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
569 vk::VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
570 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
571 VK_FALSE, // VkBool32 depthBiasEnable;
572 0.0f, // float depthBiasConstantFactor;
573 0.0f, // float depthBiasClamp;
574 0.0f, // float depthBiasSlopeFactor;
575 1.0f, // float lineWidth;
576 };
577
578 const vk::VkPipelineColorBlendAttachmentState blendState{
579 VK_FALSE,
580 VK_BLEND_FACTOR_ONE,
581 VK_BLEND_FACTOR_ONE,
582 VK_BLEND_OP_ADD,
583 VK_BLEND_FACTOR_ONE,
584 VK_BLEND_FACTOR_ONE,
585 VK_BLEND_OP_ADD,
586 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
587
588 };
589 const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateParams{
590 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
591 DE_NULL, // const void* pNext
592 0u, // VkPipelineColorBlendStateCreateFlags flags
593 VK_FALSE, // VkBool32 logicOpEnable
594 vk::VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp
595 m_colorAttachmentEnable ? 1u : 0u, // uint32_t attachmentCount
596 &blendState, // const VkPipelineColorBlendAttachmentState* pAttachments
597 {1.0f, 1.0f, 1.0f, 1.0f} // float blendConstants[4]
598 };
599
600 // Setup different stencil masks and refs in each quad
601 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
602 {
603 const StencilTest::StencilStateConfig &config = StencilTest::s_stencilStateConfigs[quadNdx];
604 VkStencilOpState &front = depthStencilStateParams.front;
605 VkStencilOpState &back = depthStencilStateParams.back;
606
607 front.compareMask = config.frontReadMask;
608 front.writeMask = config.frontWriteMask;
609 front.reference = config.frontRef;
610
611 back.compareMask = config.backReadMask;
612 back.writeMask = config.backWriteMask;
613 back.reference = config.backRef;
614
615 m_graphicsPipelines[quadNdx]
616 .setDefaultRasterizerDiscardEnable(!m_colorAttachmentEnable)
617 .setDefaultMultisampleState()
618 .setupVertexInputState(&vertexInputStateParams)
619 .setupPreRasterizationShaderState(viewports, scissors, m_pipelineLayout, *m_renderPass, 0u,
620 m_vertexShaderModule, &rasterizationStateParams)
621 .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule,
622 &depthStencilStateParams)
623 .setupFragmentOutputState(*m_renderPass, 0,
624 (m_colorAttachmentEnable ? &colorBlendStateParams : DE_NULL))
625 .setMonolithicPipelineLayout(m_pipelineLayout)
626 .buildPipeline();
627 }
628 }
629
630 // Create vertex buffer
631 {
632 const VkBufferCreateInfo vertexBufferParams = {
633 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
634 DE_NULL, // const void* pNext;
635 0u, // VkBufferCreateFlags flags;
636 1024u, // VkDeviceSize size;
637 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
638 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
639 1u, // uint32_t queueFamilyIndexCount;
640 &queueFamilyIndex // const uint32_t* pQueueFamilyIndices;
641 };
642
643 m_vertices = createOverlappingQuads();
644 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
645 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),
646 MemoryRequirement::HostVisible);
647
648 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
649 m_vertexBufferAlloc->getOffset()));
650
651 // Adjust depths
652 for (int quadNdx = 0; quadNdx < 4; quadNdx++)
653 for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
654 m_vertices[quadNdx * 6 + vertexNdx].position.z() = StencilTest::s_quadDepths[quadNdx];
655
656 // Load vertices into vertex buffer
657 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
658 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
659 }
660
661 // Create command pool
662 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
663
664 // Create command buffer
665 {
666 const VkImageMemoryBarrier colorImageBarrier = {
667 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
668 DE_NULL, // const void* pNext;
669 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
670 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
671 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
672 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
673 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
674 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
675 *m_colorImage, // VkImage image;
676 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
677 };
678
679 VkImageSubresourceRange stencilImageBarrierSubresourceRange = m_stencilImageSubresourceRange;
680 VkImageLayout newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
681 if (m_separateDepthStencilLayouts)
682 {
683 stencilImageBarrierSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
684 newLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
685 }
686
687 const VkImageMemoryBarrier stencilImageBarrier = {
688 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
689 DE_NULL, // const void* pNext;
690 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
691 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
692 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
693 newLayout, // VkImageLayout newLayout;
694 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
695 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
696 *m_stencilImage, // VkImage image;
697 stencilImageBarrierSubresourceRange, // VkImageSubresourceRange subresourceRange;
698 };
699
700 std::vector<VkClearValue> attachmentClearValues;
701 std::vector<VkImageMemoryBarrier> imageLayoutBarriers;
702
703 if (m_colorAttachmentEnable)
704 {
705 attachmentClearValues.push_back(defaultClearValue(m_colorFormat));
706 imageLayoutBarriers.push_back(colorImageBarrier);
707 }
708
709 attachmentClearValues.push_back(defaultClearValue(m_stencilFormat));
710 imageLayoutBarriers.push_back(stencilImageBarrier);
711
712 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
713
714 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
715
716 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
717 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
718 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
719 (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, (uint32_t)imageLayoutBarriers.size(),
720 imageLayoutBarriers.data());
721
722 m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
723 (uint32_t)attachmentClearValues.size(), attachmentClearValues.data());
724
725 const VkDeviceSize quadOffset = (m_vertices.size() / StencilTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
726
727 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
728 {
729 VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
730
731 m_graphicsPipelines[quadNdx].bind(*m_cmdBuffer);
732 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
733 vk.cmdDraw(*m_cmdBuffer, (uint32_t)(m_vertices.size() / StencilTest::QUAD_COUNT), 1, 0, 0);
734 }
735
736 m_renderPass.end(vk, *m_cmdBuffer);
737 endCommandBuffer(vk, *m_cmdBuffer);
738 }
739 }
740
iterate(void)741 tcu::TestStatus StencilTestInstance::iterate(void)
742 {
743 const DeviceInterface &vk = m_context.getDeviceInterface();
744 const VkDevice vkDevice = m_context.getDevice();
745 const VkQueue queue = m_context.getUniversalQueue();
746
747 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
748
749 return verifyImage();
750 }
751
verifyImage(void)752 tcu::TestStatus StencilTestInstance::verifyImage(void)
753 {
754 const tcu::TextureFormat tcuColorFormat = mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
755 const tcu::TextureFormat tcuStencilFormat = mapVkFormat(m_stencilFormat);
756 const ColorVertexShader vertexShader;
757 const ColorFragmentShader fragmentShader(tcuColorFormat, tcuStencilFormat);
758 const rr::Program program(&vertexShader, &fragmentShader);
759 ReferenceRenderer refRenderer(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
760 bool colorCompareOk = false;
761 bool stencilCompareOk = false;
762
763 // Render reference image
764 {
765 // Set depth state
766 rr::RenderState renderState(refRenderer.getViewportState(),
767 m_context.getDeviceProperties().limits.subPixelPrecisionBits);
768
769 renderState.fragOps.depthTestEnabled = true;
770 renderState.fragOps.depthFunc = mapVkCompareOp(VK_COMPARE_OP_LESS);
771 renderState.fragOps.stencilTestEnabled = true;
772
773 rr::StencilState &refStencilFront = renderState.fragOps.stencilStates[rr::FACETYPE_FRONT];
774 rr::StencilState &refStencilBack = renderState.fragOps.stencilStates[rr::FACETYPE_BACK];
775
776 refStencilFront.sFail = mapVkStencilOp(m_stencilOpStateFront.failOp);
777 refStencilFront.dpFail = mapVkStencilOp(m_stencilOpStateFront.depthFailOp);
778 refStencilFront.dpPass = mapVkStencilOp(m_stencilOpStateFront.passOp);
779 refStencilFront.func = mapVkCompareOp(m_stencilOpStateFront.compareOp);
780
781 refStencilBack.sFail = mapVkStencilOp(m_stencilOpStateBack.failOp);
782 refStencilBack.dpPass = mapVkStencilOp(m_stencilOpStateBack.passOp);
783 refStencilBack.dpFail = mapVkStencilOp(m_stencilOpStateBack.depthFailOp);
784 refStencilBack.func = mapVkCompareOp(m_stencilOpStateBack.compareOp);
785
786 // Reverse winding of vertices, as Vulkan screen coordinates start at upper left
787 std::vector<Vertex4RGBA> cwVertices(m_vertices);
788 for (size_t vertexNdx = 0; vertexNdx < cwVertices.size() - 2; vertexNdx += 3)
789 {
790 const Vertex4RGBA cwVertex1 = cwVertices[vertexNdx + 1];
791
792 cwVertices[vertexNdx + 1] = cwVertices[vertexNdx + 2];
793 cwVertices[vertexNdx + 2] = cwVertex1;
794 }
795
796 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
797 {
798 refStencilFront.ref = (int)StencilTest::s_stencilStateConfigs[quadNdx].frontRef;
799 refStencilFront.compMask = StencilTest::s_stencilStateConfigs[quadNdx].frontReadMask;
800 refStencilFront.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].frontWriteMask;
801
802 refStencilBack.ref = (int)StencilTest::s_stencilStateConfigs[quadNdx].backRef;
803 refStencilBack.compMask = StencilTest::s_stencilStateConfigs[quadNdx].backReadMask;
804 refStencilBack.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].backWriteMask;
805
806 refRenderer.draw(
807 renderState, rr::PRIMITIVETYPE_TRIANGLES,
808 std::vector<Vertex4RGBA>(cwVertices.begin() + quadNdx * 6, cwVertices.begin() + (quadNdx + 1) * 6));
809 }
810 }
811
812 // Compare result with reference image
813 if (m_colorAttachmentEnable)
814 {
815 const DeviceInterface &vk = m_context.getDeviceInterface();
816 const VkDevice vkDevice = m_context.getDevice();
817 const VkQueue queue = m_context.getUniversalQueue();
818 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
819 SimpleAllocator allocator(
820 vk, vkDevice,
821 getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
822 de::UniquePtr<tcu::TextureLevel> result(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator,
823 *m_colorImage, m_colorFormat, m_renderSize)
824 .release());
825
826 colorCompareOk = tcu::intThresholdPositionDeviationCompare(
827 m_context.getTestContext().getLog(), "IntImageCompare", "Image comparison", refRenderer.getAccess(),
828 result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
829 }
830 else
831 {
832 colorCompareOk = true;
833 }
834
835 // Compare stencil result with reference image
836 {
837 const DeviceInterface &vk = m_context.getDeviceInterface();
838 const VkDevice vkDevice = m_context.getDevice();
839 const VkQueue queue = m_context.getUniversalQueue();
840 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
841 SimpleAllocator allocator(
842 vk, vkDevice,
843 getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
844 de::UniquePtr<tcu::TextureLevel> result(readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator,
845 *m_stencilImage, m_stencilFormat, m_renderSize)
846 .release());
847
848 {
849 const tcu::PixelBufferAccess stencilAccess(
850 tcu::getEffectiveDepthStencilAccess(refRenderer.getDepthStencilAccess(), tcu::Sampler::MODE_STENCIL));
851 stencilCompareOk = tcu::intThresholdPositionDeviationCompare(
852 m_context.getTestContext().getLog(), "StencilImageCompare", "Stencil image comparison", stencilAccess,
853 result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
854 }
855 }
856
857 if (colorCompareOk && stencilCompareOk)
858 return tcu::TestStatus::pass("Result image matches reference");
859 else
860 return tcu::TestStatus::fail("Image mismatch");
861 }
862
863 // Utilities for test names
864
getShortName(VkStencilOp stencilOp)865 const char *getShortName(VkStencilOp stencilOp)
866 {
867 switch (stencilOp)
868 {
869 case VK_STENCIL_OP_KEEP:
870 return "keep";
871 case VK_STENCIL_OP_ZERO:
872 return "zero";
873 case VK_STENCIL_OP_REPLACE:
874 return "repl";
875 case VK_STENCIL_OP_INCREMENT_AND_CLAMP:
876 return "incc";
877 case VK_STENCIL_OP_DECREMENT_AND_CLAMP:
878 return "decc";
879 case VK_STENCIL_OP_INVERT:
880 return "inv";
881 case VK_STENCIL_OP_INCREMENT_AND_WRAP:
882 return "wrap";
883 case VK_STENCIL_OP_DECREMENT_AND_WRAP:
884 return "decw";
885
886 default:
887 DE_FATAL("Invalid VkStencilOpState value");
888 }
889 return DE_NULL;
890 }
891
getFormatCaseName(VkFormat format)892 std::string getFormatCaseName(VkFormat format)
893 {
894 const std::string fullName = getFormatName(format);
895
896 DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
897
898 return de::toLower(fullName.substr(10));
899 }
900
901 } // namespace
902
createStencilTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)903 tcu::TestCaseGroup *createStencilTests(tcu::TestContext &testCtx, PipelineConstructionType pipelineConstructionType)
904 {
905 const VkFormat stencilFormats[] = {VK_FORMAT_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT,
906 VK_FORMAT_D32_SFLOAT_S8_UINT};
907
908 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(compareOps) == 8);
909 DE_STATIC_ASSERT(vk::VK_COMPARE_OP_LAST == 8);
910
911 static const char *compareOpNames[8] = {"comp_never",
912 "comp_less",
913 "comp_equal",
914 "comp_less_or_equal",
915 "comp_greater",
916 "comp_not_equal",
917 "comp_greater_or_equal",
918 "comp_always"};
919
920 // Stencil tests
921 de::MovePtr<tcu::TestCaseGroup> stencilTests(new tcu::TestCaseGroup(testCtx, "stencil"));
922 // Stencil tests with no color attachment
923 de::MovePtr<tcu::TestCaseGroup> noColorAttachmentTests(new tcu::TestCaseGroup(testCtx, "nocolor"));
924 const bool colorAttachmentEnabled[] = {true, false};
925
926 for (uint32_t colorAttachmentEnabledIdx = 0; colorAttachmentEnabledIdx < DE_LENGTH_OF_ARRAY(colorAttachmentEnabled);
927 colorAttachmentEnabledIdx++)
928 {
929 const bool colorEnabled = colorAttachmentEnabled[colorAttachmentEnabledIdx];
930 de::MovePtr<tcu::TestCaseGroup> formatTests(new tcu::TestCaseGroup(testCtx, "format"));
931 StencilOpStateUniqueRandomIterator stencilOpItr(123);
932
933 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(stencilFormats); formatNdx++)
934 {
935 const VkFormat stencilFormat = stencilFormats[formatNdx];
936 const bool hasDepth = tcu::hasDepthComponent(mapVkFormat(stencilFormat).order);
937 const bool hasStencil = tcu::hasStencilComponent(mapVkFormat(stencilFormat).order);
938 const int separateLayoutsLoopCount = (hasDepth && hasStencil) ? 2 : 1;
939
940 for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount;
941 ++separateDepthStencilLayouts)
942 {
943 const bool useSeparateDepthStencilLayouts = bool(separateDepthStencilLayouts);
944
945 de::MovePtr<tcu::TestCaseGroup> formatTest(new tcu::TestCaseGroup(
946 testCtx,
947 (getFormatCaseName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : ""))
948 .c_str()));
949
950 de::MovePtr<tcu::TestCaseGroup> stencilStateTests;
951 {
952 std::ostringstream desc;
953 desc << "Draws 4 quads with the following depths and dynamic stencil states: ";
954
955 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
956 {
957 const StencilTest::StencilStateConfig &stencilConfig =
958 StencilTest::s_stencilStateConfigs[quadNdx];
959
960 desc << "(" << quadNdx << ") "
961 << "z = " << StencilTest::s_quadDepths[quadNdx] << ", "
962 << "frontReadMask = " << stencilConfig.frontReadMask << ", "
963 << "frontWriteMask = " << stencilConfig.frontWriteMask << ", "
964 << "frontRef = " << stencilConfig.frontRef << ", "
965 << "backReadMask = " << stencilConfig.backReadMask << ", "
966 << "backWriteMask = " << stencilConfig.backWriteMask << ", "
967 << "backRef = " << stencilConfig.backRef;
968 }
969
970 stencilStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states"));
971 }
972
973 stencilOpItr.reset();
974
975 for (uint32_t failOpNdx = 0u; failOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); failOpNdx++)
976 {
977 const std::string failOpName = std::string("fail_") + getShortName(stencilOps[failOpNdx]);
978 de::MovePtr<tcu::TestCaseGroup> failOpTest(new tcu::TestCaseGroup(testCtx, failOpName.c_str()));
979
980 for (uint32_t passOpNdx = 0u; passOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); passOpNdx++)
981 {
982 const std::string passOpName = std::string("pass_") + getShortName(stencilOps[passOpNdx]);
983 de::MovePtr<tcu::TestCaseGroup> passOpTest(new tcu::TestCaseGroup(testCtx, passOpName.c_str()));
984
985 for (uint32_t dFailOpNdx = 0u; dFailOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); dFailOpNdx++)
986 {
987 const std::string dFailOpName =
988 std::string("dfail_") + getShortName(stencilOps[dFailOpNdx]);
989 de::MovePtr<tcu::TestCaseGroup> dFailOpTest(
990 new tcu::TestCaseGroup(testCtx, dFailOpName.c_str()));
991
992 for (uint32_t compareOpNdx = 0u; compareOpNdx < DE_LENGTH_OF_ARRAY(compareOps);
993 compareOpNdx++)
994 {
995 // Iterate front set of stencil state in ascending order
996 const VkStencilOpState stencilStateFront = {
997 stencilOps[failOpNdx], // failOp
998 stencilOps[passOpNdx], // passOp
999 stencilOps[dFailOpNdx], // depthFailOp
1000 compareOps[compareOpNdx], // compareOp
1001 0x0, // compareMask
1002 0x0, // writeMask
1003 0x0 // reference
1004 };
1005
1006 // Iterate back set of stencil state in random order
1007 const VkStencilOpState stencilStateBack = stencilOpItr.next();
1008 const std::string caseName = compareOpNames[compareOpNdx];
1009
1010 dFailOpTest->addChild(new StencilTest(
1011 testCtx, caseName, pipelineConstructionType, stencilFormat, stencilStateFront,
1012 stencilStateBack, colorEnabled, useSeparateDepthStencilLayouts));
1013 }
1014 passOpTest->addChild(dFailOpTest.release());
1015 }
1016 failOpTest->addChild(passOpTest.release());
1017 }
1018 stencilStateTests->addChild(failOpTest.release());
1019 }
1020
1021 formatTest->addChild(stencilStateTests.release());
1022 formatTests->addChild(formatTest.release());
1023 }
1024 }
1025
1026 if (colorEnabled)
1027 stencilTests->addChild(formatTests.release());
1028 else
1029 noColorAttachmentTests->addChild(formatTests.release());
1030 }
1031
1032 stencilTests->addChild(noColorAttachmentTests.release());
1033
1034 return stencilTests.release();
1035 }
1036
1037 } // namespace pipeline
1038 } // namespace vkt
1039