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