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