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 class StencilTest : public vkt::TestCase
90 {
91 public:
92 enum
93 {
94 QUAD_COUNT = 4
95 };
96
97 struct StencilStateConfig
98 {
99 deUint32 frontReadMask;
100 deUint32 frontWriteMask;
101 deUint32 frontRef;
102
103 deUint32 backReadMask;
104 deUint32 backWriteMask;
105 deUint32 backRef;
106 };
107
108 const static StencilStateConfig s_stencilStateConfigs[QUAD_COUNT];
109 const static float s_quadDepths[QUAD_COUNT];
110
111
112 StencilTest (tcu::TestContext& testContext,
113 const std::string& name,
114 const std::string& description,
115 PipelineConstructionType pipelineConstructionType,
116 VkFormat stencilFormat,
117 const VkStencilOpState& stencilOpStateFront,
118 const VkStencilOpState& stencilOpStateBack,
119 const bool colorAttachmentEnable,
120 const bool separateDepthStencilLayouts);
121 virtual ~StencilTest (void) = default;
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 PipelineConstructionType m_pipelineConstructionType;
128 VkFormat m_stencilFormat;
129 const VkStencilOpState m_stencilOpStateFront;
130 const VkStencilOpState m_stencilOpStateBack;
131 const bool m_colorAttachmentEnable;
132 const bool m_separateDepthStencilLayouts;
133 };
134
135 class StencilTestInstance : public vkt::TestInstance
136 {
137 public:
138 StencilTestInstance (Context& context,
139 PipelineConstructionType pipelineConstructionType,
140 VkFormat stencilFormat,
141 const VkStencilOpState& stencilOpStatesFront,
142 const VkStencilOpState& stencilOpStatesBack,
143 const bool colorAttachmentEnable,
144 const bool separateDepthStencilLayouts);
145 virtual ~StencilTestInstance (void) = default;
146 virtual tcu::TestStatus iterate (void);
147
148 private:
149 tcu::TestStatus verifyImage (void);
150
151 VkStencilOpState m_stencilOpStateFront;
152 VkStencilOpState m_stencilOpStateBack;
153 const bool m_colorAttachmentEnable;
154 const bool m_separateDepthStencilLayouts;
155 const tcu::UVec2 m_renderSize;
156 const VkFormat m_colorFormat;
157 const VkFormat m_stencilFormat;
158 VkImageSubresourceRange m_stencilImageSubresourceRange;
159
160 VkImageCreateInfo m_colorImageCreateInfo;
161 Move<VkImage> m_colorImage;
162 de::MovePtr<Allocation> m_colorImageAlloc;
163 Move<VkImage> m_stencilImage;
164 de::MovePtr<Allocation> m_stencilImageAlloc;
165 Move<VkImageView> m_colorAttachmentView;
166 Move<VkImageView> m_stencilAttachmentView;
167 Move<VkRenderPass> m_renderPass;
168 Move<VkFramebuffer> m_framebuffer;
169
170 Move<VkShaderModule> m_vertexShaderModule;
171 Move<VkShaderModule> m_fragmentShaderModule;
172
173 Move<VkBuffer> m_vertexBuffer;
174 std::vector<Vertex4RGBA> m_vertices;
175 de::MovePtr<Allocation> m_vertexBufferAlloc;
176
177 Move<VkPipelineLayout> m_pipelineLayout;
178 GraphicsPipelineWrapper m_graphicsPipelines[StencilTest::QUAD_COUNT];
179
180 Move<VkCommandPool> m_cmdPool;
181 Move<VkCommandBuffer> m_cmdBuffer;
182 };
183
184 const VkStencilOp stencilOps[] =
185 {
186 VK_STENCIL_OP_KEEP,
187 VK_STENCIL_OP_ZERO,
188 VK_STENCIL_OP_REPLACE,
189 VK_STENCIL_OP_INCREMENT_AND_CLAMP,
190 VK_STENCIL_OP_DECREMENT_AND_CLAMP,
191 VK_STENCIL_OP_INVERT,
192 VK_STENCIL_OP_INCREMENT_AND_WRAP,
193 VK_STENCIL_OP_DECREMENT_AND_WRAP
194 };
195
196 const VkCompareOp compareOps[] =
197 {
198 VK_COMPARE_OP_NEVER,
199 VK_COMPARE_OP_LESS,
200 VK_COMPARE_OP_EQUAL,
201 VK_COMPARE_OP_LESS_OR_EQUAL,
202 VK_COMPARE_OP_GREATER,
203 VK_COMPARE_OP_NOT_EQUAL,
204 VK_COMPARE_OP_GREATER_OR_EQUAL,
205 VK_COMPARE_OP_ALWAYS
206 };
207
208 // StencilOpStateUniqueRandomIterator
209
210 const deUint32 StencilOpStateUniqueRandomIterator::s_stencilOpsLength = DE_LENGTH_OF_ARRAY(stencilOps);
211 const deUint32 StencilOpStateUniqueRandomIterator::s_stencilOpsLength2 = s_stencilOpsLength * s_stencilOpsLength;
212 const deUint32 StencilOpStateUniqueRandomIterator::s_stencilOpsLength3 = s_stencilOpsLength2 * s_stencilOpsLength;
213 const deUint32 StencilOpStateUniqueRandomIterator::s_compareOpsLength = DE_LENGTH_OF_ARRAY(compareOps);
214 const deUint32 StencilOpStateUniqueRandomIterator::s_totalStencilOpStates = s_stencilOpsLength3 * s_compareOpsLength;
215
StencilOpStateUniqueRandomIterator(int seed)216 StencilOpStateUniqueRandomIterator::StencilOpStateUniqueRandomIterator (int seed)
217 : UniqueRandomIterator<VkStencilOpState>(s_totalStencilOpStates, s_totalStencilOpStates, seed)
218 {
219 }
220
getIndexedValue(deUint32 index)221 VkStencilOpState StencilOpStateUniqueRandomIterator::getIndexedValue (deUint32 index)
222 {
223 const deUint32 stencilCompareOpIndex = index / s_stencilOpsLength3;
224 const deUint32 stencilCompareOpSeqIndex = stencilCompareOpIndex * s_stencilOpsLength3;
225
226 const deUint32 stencilDepthFailOpIndex = (index - stencilCompareOpSeqIndex) / s_stencilOpsLength2;
227 const deUint32 stencilDepthFailOpSeqIndex = stencilDepthFailOpIndex * s_stencilOpsLength2;
228
229 const deUint32 stencilPassOpIndex = (index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex) / s_stencilOpsLength;
230 const deUint32 stencilPassOpSeqIndex = stencilPassOpIndex * s_stencilOpsLength;
231
232 const deUint32 stencilFailOpIndex = index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex - stencilPassOpSeqIndex;
233
234 const VkStencilOpState stencilOpState =
235 {
236 stencilOps[stencilFailOpIndex], // VkStencilOp failOp;
237 stencilOps[stencilPassOpIndex], // VkStencilOp passOp;
238 stencilOps[stencilDepthFailOpIndex], // VkStencilOp depthFailOp;
239 compareOps[stencilCompareOpIndex], // VkCompareOp compareOp;
240 0x0, // deUint32 compareMask;
241 0x0, // deUint32 writeMask;
242 0x0 // deUint32 reference;
243 };
244
245 return stencilOpState;
246 }
247
248
249 // StencilTest
250
251 const StencilTest::StencilStateConfig StencilTest::s_stencilStateConfigs[QUAD_COUNT] =
252 {
253 // frontReadMask frontWriteMask frontRef backReadMask backWriteMask backRef
254 { 0xFF, 0xFF, 0xAB, 0xF0, 0xFF, 0xFF },
255 { 0xFF, 0xF0, 0xCD, 0xF0, 0xF0, 0xEF },
256 { 0xF0, 0x0F, 0xEF, 0xFF, 0x0F, 0xCD },
257 { 0xF0, 0x01, 0xFF, 0xFF, 0x01, 0xAB }
258 };
259
260 const float StencilTest::s_quadDepths[QUAD_COUNT] =
261 {
262 0.1f,
263 0.0f,
264 0.3f,
265 0.2f
266 };
267
StencilTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,PipelineConstructionType pipelineConstructionType,VkFormat stencilFormat,const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack,const bool colorAttachmentEnable,const bool separateDepthStencilLayouts)268 StencilTest::StencilTest (tcu::TestContext& testContext,
269 const std::string& name,
270 const std::string& description,
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, description)
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 checkPipelineLibraryRequirements(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.getDeviceInterface(), context.getDevice(), pipelineConstructionType },
366 { context.getDeviceInterface(), context.getDevice(), pipelineConstructionType },
367 { context.getDeviceInterface(), context.getDevice(), pipelineConstructionType },
368 { context.getDeviceInterface(), context.getDevice(), 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 = makeRenderPass(vk, vkDevice, m_colorFormat, m_stencilFormat);
478
479 // Create framebuffer
480 {
481 std::vector<VkImageView> attachmentBindInfos;
482
483 if (m_colorAttachmentEnable)
484 attachmentBindInfos.push_back(*m_colorAttachmentView);
485
486 attachmentBindInfos.push_back(*m_stencilAttachmentView);
487
488 const VkFramebufferCreateInfo framebufferParams =
489 {
490 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
491 DE_NULL, // const void* pNext;
492 0u, // VkFramebufferCreateFlags flags;
493 *m_renderPass, // VkRenderPass renderPass;
494 (deUint32)attachmentBindInfos.size(), // deUint32 attachmentCount;
495 attachmentBindInfos.data(), // const VkImageView* pAttachments;
496 (deUint32)m_renderSize.x(), // deUint32 width;
497 (deUint32)m_renderSize.y(), // deUint32 height;
498 1u // deUint32 layers;
499 };
500
501 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
502 }
503
504 // Create pipeline layout
505 {
506 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
507 {
508 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
509 DE_NULL, // const void* pNext;
510 0u, // VkPipelineLayoutCreateFlags flags;
511 0u, // deUint32 setLayoutCount;
512 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
513 0u, // deUint32 pushConstantRangeCount;
514 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
515 };
516
517 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
518 }
519
520 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
521 if (m_colorAttachmentEnable)
522 m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
523
524 // Create pipeline
525 {
526 const VkVertexInputBindingDescription vertexInputBindingDescription
527 {
528 0u, // deUint32 binding;
529 sizeof(Vertex4RGBA), // deUint32 strideInBytes;
530 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
531 };
532
533 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2]
534 {
535 {
536 0u, // deUint32 location;
537 0u, // deUint32 binding;
538 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
539 0u // deUint32 offsetInBytes;
540 },
541 {
542 1u, // deUint32 location;
543 0u, // deUint32 binding;
544 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
545 DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offsetInBytes;
546 }
547 };
548
549 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams
550 {
551 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
552 DE_NULL, // const void* pNext;
553 0u, // VkPipelineVertexInputStateCreateFlags flags;
554 1u, // deUint32 vertexBindingDescriptionCount;
555 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
556 2u, // deUint32 vertexAttributeDescriptionCount;
557 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
558 };
559
560 const std::vector<VkViewport> viewports { makeViewport(m_renderSize) };
561 const std::vector<VkRect2D> scissors { makeRect2D(m_renderSize) };
562
563 const bool isDepthEnabled = (vk::mapVkFormat(m_stencilFormat).order != tcu::TextureFormat::S);
564
565 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams
566 {
567 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
568 DE_NULL, // const void* pNext;
569 0u, // VkPipelineDepthStencilStateCreateFlags flags;
570 isDepthEnabled, // VkBool32 depthTestEnable;
571 isDepthEnabled, // VkBool32 depthWriteEnable;
572 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
573 false, // VkBool32 depthBoundsTestEnable;
574 true, // VkBool32 stencilTestEnable;
575 m_stencilOpStateFront, // VkStencilOpState front;
576 m_stencilOpStateBack, // VkStencilOpState back;
577 0.0f, // float minDepthBounds;
578 1.0f // float maxDepthBounds;
579 };
580
581 // Make sure rasterization is not disabled when the fragment shader is missing.
582 const vk::VkPipelineRasterizationStateCreateInfo rasterizationStateParams
583 {
584 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
585 nullptr, // const void* pNext;
586 0u, // VkPipelineRasterizationStateCreateFlags flags;
587 VK_FALSE, // VkBool32 depthClampEnable;
588 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
589 vk::VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
590 vk::VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
591 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
592 VK_FALSE, // VkBool32 depthBiasEnable;
593 0.0f, // float depthBiasConstantFactor;
594 0.0f, // float depthBiasClamp;
595 0.0f, // float depthBiasSlopeFactor;
596 1.0f, // float lineWidth;
597 };
598
599 const vk::VkPipelineColorBlendAttachmentState blendState
600 {
601 VK_FALSE,
602 VK_BLEND_FACTOR_ONE,
603 VK_BLEND_FACTOR_ONE,
604 VK_BLEND_OP_ADD,
605 VK_BLEND_FACTOR_ONE,
606 VK_BLEND_FACTOR_ONE,
607 VK_BLEND_OP_ADD,
608 VK_COLOR_COMPONENT_R_BIT |
609 VK_COLOR_COMPONENT_G_BIT |
610 VK_COLOR_COMPONENT_B_BIT |
611 VK_COLOR_COMPONENT_A_BIT,
612
613 };
614 const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateParams
615 {
616 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
617 DE_NULL, // const void* pNext
618 0u, // VkPipelineColorBlendStateCreateFlags flags
619 VK_FALSE, // VkBool32 logicOpEnable
620 vk::VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp
621 m_colorAttachmentEnable ? 1u : 0u, // deUint32 attachmentCount
622 &blendState, // const VkPipelineColorBlendAttachmentState* pAttachments
623 { 1.0f, 1.0f, 1.0f, 1.0f } // float blendConstants[4]
624 };
625
626 // Setup different stencil masks and refs in each quad
627 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
628 {
629 const StencilTest::StencilStateConfig& config = StencilTest::s_stencilStateConfigs[quadNdx];
630 VkStencilOpState& front = depthStencilStateParams.front;
631 VkStencilOpState& back = depthStencilStateParams.back;
632
633 front.compareMask = config.frontReadMask;
634 front.writeMask = config.frontWriteMask;
635 front.reference = config.frontRef;
636
637 back.compareMask = config.backReadMask;
638 back.writeMask = config.backWriteMask;
639 back.reference = config.backRef;
640
641 m_graphicsPipelines[quadNdx].setDefaultRasterizerDiscardEnable(!m_colorAttachmentEnable)
642 .setDefaultMultisampleState()
643 .setupVertexInputState(&vertexInputStateParams)
644 .setupPreRasterizationShaderState(viewports,
645 scissors,
646 *m_pipelineLayout,
647 *m_renderPass,
648 0u,
649 *m_vertexShaderModule,
650 &rasterizationStateParams)
651 .setupFragmentShaderState(*m_pipelineLayout, *m_renderPass, 0u, *m_fragmentShaderModule, &depthStencilStateParams)
652 .setupFragmentOutputState(*m_renderPass, 0, &colorBlendStateParams)
653 .setMonolithicPipelineLayout(*m_pipelineLayout)
654 .buildPipeline();
655 }
656 }
657
658 // Create vertex buffer
659 {
660 const VkBufferCreateInfo vertexBufferParams =
661 {
662 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
663 DE_NULL, // const void* pNext;
664 0u, // VkBufferCreateFlags flags;
665 1024u, // VkDeviceSize size;
666 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
667 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
668 1u, // deUint32 queueFamilyIndexCount;
669 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
670 };
671
672 m_vertices = createOverlappingQuads();
673 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
674 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
675
676 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
677
678 // Adjust depths
679 for (int quadNdx = 0; quadNdx < 4; quadNdx++)
680 for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
681 m_vertices[quadNdx * 6 + vertexNdx].position.z() = StencilTest::s_quadDepths[quadNdx];
682
683 // Load vertices into vertex buffer
684 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
685 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
686 }
687
688 // Create command pool
689 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
690
691 // Create command buffer
692 {
693 const VkImageMemoryBarrier colorImageBarrier =
694 {
695 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
696 DE_NULL, // const void* pNext;
697 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
698 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
699 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
700 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
701 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
702 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
703 *m_colorImage, // VkImage image;
704 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
705 };
706
707 VkImageSubresourceRange stencilImageBarrierSubresourceRange = m_stencilImageSubresourceRange;
708 VkImageLayout newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
709 if (m_separateDepthStencilLayouts)
710 {
711 stencilImageBarrierSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
712 newLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
713 }
714
715 const VkImageMemoryBarrier stencilImageBarrier =
716 {
717 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
718 DE_NULL, // const void* pNext;
719 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
720 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
721 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
722 newLayout, // VkImageLayout newLayout;
723 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
724 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
725 *m_stencilImage, // VkImage image;
726 stencilImageBarrierSubresourceRange, // VkImageSubresourceRange subresourceRange;
727 };
728
729 std::vector<VkClearValue> attachmentClearValues;
730 std::vector<VkImageMemoryBarrier> imageLayoutBarriers;
731
732 if (m_colorAttachmentEnable)
733 {
734 attachmentClearValues.push_back(defaultClearValue(m_colorFormat));
735 imageLayoutBarriers.push_back(colorImageBarrier);
736 }
737
738 attachmentClearValues.push_back(defaultClearValue(m_stencilFormat));
739 imageLayoutBarriers.push_back(stencilImageBarrier);
740
741 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
742
743 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
744
745 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,
746 0u, DE_NULL, 0u, DE_NULL, (deUint32)imageLayoutBarriers.size(), imageLayoutBarriers.data());
747
748 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), (deUint32)attachmentClearValues.size(), attachmentClearValues.data());
749
750 const VkDeviceSize quadOffset = (m_vertices.size() / StencilTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
751
752 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
753 {
754 VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
755
756 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipelines[quadNdx].getPipeline());
757 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
758 vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / StencilTest::QUAD_COUNT), 1, 0, 0);
759 }
760
761 endRenderPass(vk, *m_cmdBuffer);
762 endCommandBuffer(vk, *m_cmdBuffer);
763 }
764 }
765
iterate(void)766 tcu::TestStatus StencilTestInstance::iterate (void)
767 {
768 const DeviceInterface& vk = m_context.getDeviceInterface();
769 const VkDevice vkDevice = m_context.getDevice();
770 const VkQueue queue = m_context.getUniversalQueue();
771
772 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
773
774 return verifyImage();
775 }
776
verifyImage(void)777 tcu::TestStatus StencilTestInstance::verifyImage (void)
778 {
779 const tcu::TextureFormat tcuColorFormat = mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
780 const tcu::TextureFormat tcuStencilFormat = mapVkFormat(m_stencilFormat);
781 const ColorVertexShader vertexShader;
782 const ColorFragmentShader fragmentShader (tcuColorFormat, tcuStencilFormat);
783 const rr::Program program (&vertexShader, &fragmentShader);
784 ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
785 bool colorCompareOk = false;
786 bool stencilCompareOk = false;
787
788 // Render reference image
789 {
790 // Set depth state
791 rr::RenderState renderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
792
793 renderState.fragOps.depthTestEnabled = true;
794 renderState.fragOps.depthFunc = mapVkCompareOp(VK_COMPARE_OP_LESS);
795 renderState.fragOps.stencilTestEnabled = true;
796
797 rr::StencilState& refStencilFront = renderState.fragOps.stencilStates[rr::FACETYPE_FRONT];
798 rr::StencilState& refStencilBack = renderState.fragOps.stencilStates[rr::FACETYPE_BACK];
799
800 refStencilFront.sFail = mapVkStencilOp(m_stencilOpStateFront.failOp);
801 refStencilFront.dpFail = mapVkStencilOp(m_stencilOpStateFront.depthFailOp);
802 refStencilFront.dpPass = mapVkStencilOp(m_stencilOpStateFront.passOp);
803 refStencilFront.func = mapVkCompareOp(m_stencilOpStateFront.compareOp);
804
805 refStencilBack.sFail = mapVkStencilOp(m_stencilOpStateBack.failOp);
806 refStencilBack.dpPass = mapVkStencilOp(m_stencilOpStateBack.passOp);
807 refStencilBack.dpFail = mapVkStencilOp(m_stencilOpStateBack.depthFailOp);
808 refStencilBack.func = mapVkCompareOp(m_stencilOpStateBack.compareOp);
809
810 // Reverse winding of vertices, as Vulkan screen coordinates start at upper left
811 std::vector<Vertex4RGBA> cwVertices(m_vertices);
812 for (size_t vertexNdx = 0; vertexNdx < cwVertices.size() - 2; vertexNdx += 3)
813 {
814 const Vertex4RGBA cwVertex1 = cwVertices[vertexNdx + 1];
815
816 cwVertices[vertexNdx + 1] = cwVertices[vertexNdx + 2];
817 cwVertices[vertexNdx + 2] = cwVertex1;
818 }
819
820 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
821 {
822 refStencilFront.ref = (int)StencilTest::s_stencilStateConfigs[quadNdx].frontRef;
823 refStencilFront.compMask = StencilTest::s_stencilStateConfigs[quadNdx].frontReadMask;
824 refStencilFront.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].frontWriteMask;
825
826 refStencilBack.ref = (int)StencilTest::s_stencilStateConfigs[quadNdx].backRef;
827 refStencilBack.compMask = StencilTest::s_stencilStateConfigs[quadNdx].backReadMask;
828 refStencilBack.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].backWriteMask;
829
830 refRenderer.draw(renderState,
831 rr::PRIMITIVETYPE_TRIANGLES,
832 std::vector<Vertex4RGBA>(cwVertices.begin() + quadNdx * 6,
833 cwVertices.begin() + (quadNdx + 1) * 6));
834 }
835 }
836
837 // Compare result with reference image
838 if (m_colorAttachmentEnable)
839 {
840 const DeviceInterface& vk = m_context.getDeviceInterface();
841 const VkDevice vkDevice = m_context.getDevice();
842 const VkQueue queue = m_context.getUniversalQueue();
843 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
844 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
845 de::UniquePtr<tcu::TextureLevel> result (readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
846
847 colorCompareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
848 "IntImageCompare",
849 "Image comparison",
850 refRenderer.getAccess(),
851 result->getAccess(),
852 tcu::UVec4(2, 2, 2, 2),
853 tcu::IVec3(1, 1, 0),
854 true,
855 tcu::COMPARE_LOG_RESULT);
856 }
857 else
858 {
859 colorCompareOk = true;
860 }
861
862 // Compare stencil result with reference image
863 {
864 const DeviceInterface& vk = m_context.getDeviceInterface();
865 const VkDevice vkDevice = m_context.getDevice();
866 const VkQueue queue = m_context.getUniversalQueue();
867 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
868 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
869 de::UniquePtr<tcu::TextureLevel> result (readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_stencilImage, m_stencilFormat, m_renderSize).release());
870
871 {
872 const tcu::PixelBufferAccess stencilAccess (tcu::getEffectiveDepthStencilAccess(refRenderer.getDepthStencilAccess(), tcu::Sampler::MODE_STENCIL));
873 stencilCompareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
874 "StencilImageCompare",
875 "Stencil image comparison",
876 stencilAccess,
877 result->getAccess(),
878 tcu::UVec4(2, 2, 2, 2),
879 tcu::IVec3(1, 1, 0),
880 true,
881 tcu::COMPARE_LOG_RESULT);
882 }
883 }
884
885 if (colorCompareOk && stencilCompareOk)
886 return tcu::TestStatus::pass("Result image matches reference");
887 else
888 return tcu::TestStatus::fail("Image mismatch");
889 }
890
891
892 // Utilities for test names
893
getShortName(VkStencilOp stencilOp)894 const char* getShortName (VkStencilOp stencilOp)
895 {
896 switch (stencilOp)
897 {
898 case VK_STENCIL_OP_KEEP: return "keep";
899 case VK_STENCIL_OP_ZERO: return "zero";
900 case VK_STENCIL_OP_REPLACE: return "repl";
901 case VK_STENCIL_OP_INCREMENT_AND_CLAMP: return "incc";
902 case VK_STENCIL_OP_DECREMENT_AND_CLAMP: return "decc";
903 case VK_STENCIL_OP_INVERT: return "inv";
904 case VK_STENCIL_OP_INCREMENT_AND_WRAP: return "wrap";
905 case VK_STENCIL_OP_DECREMENT_AND_WRAP: return "decw";
906
907 default:
908 DE_FATAL("Invalid VkStencilOpState value");
909 }
910 return DE_NULL;
911 }
912
getStencilStateSetDescription(const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack)913 std::string getStencilStateSetDescription(const VkStencilOpState& stencilOpStateFront,
914 const VkStencilOpState& stencilOpStateBack)
915 {
916 std::ostringstream desc;
917
918 desc << "\nFront faces:\n" << stencilOpStateFront;
919 desc << "Back faces:\n" << stencilOpStateBack;
920
921 return desc.str();
922 }
923
getFormatCaseName(VkFormat format)924 std::string getFormatCaseName (VkFormat format)
925 {
926 const std::string fullName = getFormatName(format);
927
928 DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
929
930 return de::toLower(fullName.substr(10));
931 }
932
933 } // anonymous
934
createStencilTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)935 tcu::TestCaseGroup* createStencilTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
936 {
937 const VkFormat stencilFormats[] =
938 {
939 VK_FORMAT_S8_UINT,
940 VK_FORMAT_D16_UNORM_S8_UINT,
941 VK_FORMAT_D24_UNORM_S8_UINT,
942 VK_FORMAT_D32_SFLOAT_S8_UINT
943 };
944
945 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(compareOps) == 8);
946 DE_STATIC_ASSERT(vk::VK_COMPARE_OP_LAST == 8);
947
948 static const char* compareOpNames[8] =
949 {
950 "comp_never",
951 "comp_less",
952 "comp_equal",
953 "comp_less_or_equal",
954 "comp_greater",
955 "comp_not_equal",
956 "comp_greater_or_equal",
957 "comp_always"
958 };
959
960 de::MovePtr<tcu::TestCaseGroup> stencilTests (new tcu::TestCaseGroup(testCtx, "stencil", "Stencil tests"));
961 de::MovePtr<tcu::TestCaseGroup> noColorAttachmentTests (new tcu::TestCaseGroup(testCtx, "nocolor", "Stencil tests with no color attachment"));
962 const bool colorAttachmentEnabled[] = { true, false };
963
964 for (deUint32 colorAttachmentEnabledIdx = 0; colorAttachmentEnabledIdx < DE_LENGTH_OF_ARRAY(colorAttachmentEnabled); colorAttachmentEnabledIdx++)
965 {
966 const bool colorEnabled = colorAttachmentEnabled[colorAttachmentEnabledIdx];
967 de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Uses different stencil formats"));
968 StencilOpStateUniqueRandomIterator stencilOpItr (123);
969
970 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(stencilFormats); formatNdx++)
971 {
972 const VkFormat stencilFormat = stencilFormats[formatNdx];
973 const bool hasDepth = tcu::hasDepthComponent(mapVkFormat(stencilFormat).order);
974 const bool hasStencil = tcu::hasStencilComponent(mapVkFormat(stencilFormat).order);
975 const int separateLayoutsLoopCount = (hasDepth && hasStencil) ? 2 : 1;
976
977 for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount; ++separateDepthStencilLayouts)
978 {
979 const bool useSeparateDepthStencilLayouts = bool(separateDepthStencilLayouts);
980
981 de::MovePtr<tcu::TestCaseGroup> formatTest (new tcu::TestCaseGroup(testCtx,
982 (getFormatCaseName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : "")).c_str(),
983 (std::string("Uses format ") + getFormatName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? " with separate depth/stencil layouts" : "")).c_str()));
984
985 de::MovePtr<tcu::TestCaseGroup> stencilStateTests;
986 {
987 std::ostringstream desc;
988 desc << "Draws 4 quads with the following depths and dynamic stencil states: ";
989
990 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
991 {
992 const StencilTest::StencilStateConfig& stencilConfig = StencilTest::s_stencilStateConfigs[quadNdx];
993
994 desc << "(" << quadNdx << ") "
995 << "z = " << StencilTest::s_quadDepths[quadNdx] << ", "
996 << "frontReadMask = " << stencilConfig.frontReadMask << ", "
997 << "frontWriteMask = " << stencilConfig.frontWriteMask << ", "
998 << "frontRef = " << stencilConfig.frontRef << ", "
999 << "backReadMask = " << stencilConfig.backReadMask << ", "
1000 << "backWriteMask = " << stencilConfig.backWriteMask << ", "
1001 << "backRef = " << stencilConfig.backRef;
1002 }
1003
1004 stencilStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", desc.str().c_str()));
1005 }
1006
1007 stencilOpItr.reset();
1008
1009 for (deUint32 failOpNdx = 0u; failOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); failOpNdx++)
1010 {
1011 const std::string failOpName = std::string("fail_") + getShortName(stencilOps[failOpNdx]);
1012 de::MovePtr<tcu::TestCaseGroup> failOpTest (new tcu::TestCaseGroup(testCtx, failOpName.c_str(), ""));
1013
1014 for (deUint32 passOpNdx = 0u; passOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); passOpNdx++)
1015 {
1016 const std::string passOpName = std::string("pass_") + getShortName(stencilOps[passOpNdx]);
1017 de::MovePtr<tcu::TestCaseGroup> passOpTest (new tcu::TestCaseGroup(testCtx, passOpName.c_str(), ""));
1018
1019 for (deUint32 dFailOpNdx = 0u; dFailOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); dFailOpNdx++)
1020 {
1021 const std::string dFailOpName = std::string("dfail_") + getShortName(stencilOps[dFailOpNdx]);
1022 de::MovePtr<tcu::TestCaseGroup> dFailOpTest (new tcu::TestCaseGroup(testCtx, dFailOpName.c_str(), ""));
1023
1024 for (deUint32 compareOpNdx = 0u; compareOpNdx < DE_LENGTH_OF_ARRAY(compareOps); compareOpNdx++)
1025 {
1026 // Iterate front set of stencil state in ascending order
1027 const VkStencilOpState stencilStateFront =
1028 {
1029 stencilOps[failOpNdx], // failOp
1030 stencilOps[passOpNdx], // passOp
1031 stencilOps[dFailOpNdx], // depthFailOp
1032 compareOps[compareOpNdx], // compareOp
1033 0x0, // compareMask
1034 0x0, // writeMask
1035 0x0 // reference
1036 };
1037
1038 // Iterate back set of stencil state in random order
1039 const VkStencilOpState stencilStateBack = stencilOpItr.next();
1040 const std::string caseName = compareOpNames[compareOpNdx];
1041 const std::string caseDesc = getStencilStateSetDescription(stencilStateFront, stencilStateBack);
1042
1043 dFailOpTest->addChild(new StencilTest(testCtx, caseName, caseDesc, pipelineConstructionType, stencilFormat, stencilStateFront, stencilStateBack, colorEnabled, useSeparateDepthStencilLayouts));
1044 }
1045 passOpTest->addChild(dFailOpTest.release());
1046 }
1047 failOpTest->addChild(passOpTest.release());
1048 }
1049 stencilStateTests->addChild(failOpTest.release());
1050 }
1051
1052 formatTest->addChild(stencilStateTests.release());
1053 formatTests->addChild(formatTest.release());
1054 }
1055 }
1056
1057 if (colorEnabled)
1058 stencilTests->addChild(formatTests.release());
1059 else
1060 noColorAttachmentTests->addChild(formatTests.release());
1061 }
1062
1063 stencilTests->addChild(noColorAttachmentTests.release());
1064
1065 return stencilTests.release();
1066 }
1067
1068 } // pipeline
1069 } // vkt
1070