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 "vktPipelineClearUtil.hpp"
28 #include "vktPipelineImageUtil.hpp"
29 #include "vktPipelineVertexUtil.hpp"
30 #include "vktPipelineReferenceRenderer.hpp"
31 #include "vktPipelineUniqueRandomIterator.hpp"
32 #include "vktTestCase.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkRef.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42 #include "vkBarrierUtil.hpp"
43 #include "tcuImageCompare.hpp"
44 #include "deMemory.h"
45 #include "deStringUtil.hpp"
46 #include "deUniquePtr.hpp"
47
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 {
76 }
77 virtual VkStencilOpState getIndexedValue(uint32_t index);
78
79 private:
80 // Pre-calculated constants
81 const static uint32_t s_stencilOpsLength;
82 const static uint32_t s_stencilOpsLength2;
83 const static uint32_t s_stencilOpsLength3;
84 const static uint32_t s_compareOpsLength;
85
86 // Total number of cross-combinations of (stencilFailOp x stencilPassOp x stencilDepthFailOp x stencilCompareOp)
87 const static uint32_t s_totalStencilOpStates;
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 uint32_t frontReadMask;
101 uint32_t frontWriteMask;
102 uint32_t frontRef;
103
104 uint32_t backReadMask;
105 uint32_t backWriteMask;
106 uint32_t backRef;
107 };
108
109 const static StencilStateConfig s_stencilStateConfigs[QUAD_COUNT];
110 const static float s_quadDepths[QUAD_COUNT];
111
112 StencilTest(tcu::TestContext &testContext, const std::string &name,
113 PipelineConstructionType pipelineConstructionType, VkFormat stencilFormat,
114 const VkStencilOpState &stencilOpStateFront, const VkStencilOpState &stencilOpStateBack,
115 const bool colorAttachmentEnable, const bool separateDepthStencilLayouts);
116 virtual ~StencilTest(void) = default;
117 virtual void initPrograms(SourceCollections &sourceCollections) const;
118 virtual void checkSupport(Context &context) const;
119 virtual TestInstance *createInstance(Context &context) const;
120
121 private:
122 PipelineConstructionType m_pipelineConstructionType;
123 VkFormat m_stencilFormat;
124 const VkStencilOpState m_stencilOpStateFront;
125 const VkStencilOpState m_stencilOpStateBack;
126 const bool m_colorAttachmentEnable;
127 const bool m_separateDepthStencilLayouts;
128 };
129
130 class StencilTestInstance : public vkt::TestInstance
131 {
132 public:
133 StencilTestInstance(Context &context, PipelineConstructionType pipelineConstructionType, VkFormat stencilFormat,
134 const VkStencilOpState &stencilOpStatesFront, const VkStencilOpState &stencilOpStatesBack,
135 const bool colorAttachmentEnable, const bool separateDepthStencilLayouts);
136 virtual ~StencilTestInstance(void) = default;
137 virtual tcu::TestStatus iterate(void);
138
139 private:
140 tcu::TestStatus verifyImage(void);
141
142 VkStencilOpState m_stencilOpStateFront;
143 VkStencilOpState m_stencilOpStateBack;
144 const bool m_colorAttachmentEnable;
145 const bool m_separateDepthStencilLayouts;
146 const tcu::UVec2 m_renderSize;
147 const VkFormat m_colorFormat;
148 const VkFormat m_stencilFormat;
149 VkImageSubresourceRange m_stencilImageSubresourceRange;
150
151 VkImageCreateInfo m_colorImageCreateInfo;
152 Move<VkImage> m_colorImage;
153 de::MovePtr<Allocation> m_colorImageAlloc;
154 Move<VkImage> m_stencilImage;
155 de::MovePtr<Allocation> m_stencilImageAlloc;
156 Move<VkImageView> m_colorAttachmentView;
157 Move<VkImageView> m_stencilAttachmentView;
158 RenderPassWrapper m_renderPass;
159 Move<VkFramebuffer> m_framebuffer;
160
161 ShaderWrapper m_vertexShaderModule;
162 ShaderWrapper m_fragmentShaderModule;
163
164 Move<VkBuffer> m_vertexBuffer;
165 std::vector<Vertex4RGBA> m_vertices;
166 de::MovePtr<Allocation> m_vertexBufferAlloc;
167
168 PipelineLayoutWrapper m_pipelineLayout;
169 GraphicsPipelineWrapper m_graphicsPipelines[StencilTest::QUAD_COUNT];
170
171 Move<VkCommandPool> m_cmdPool;
172 Move<VkCommandBuffer> m_cmdBuffer;
173 };
174
175 const VkStencilOp stencilOps[] = {VK_STENCIL_OP_KEEP,
176 VK_STENCIL_OP_ZERO,
177 VK_STENCIL_OP_REPLACE,
178 VK_STENCIL_OP_INCREMENT_AND_CLAMP,
179 VK_STENCIL_OP_DECREMENT_AND_CLAMP,
180 VK_STENCIL_OP_INVERT,
181 VK_STENCIL_OP_INCREMENT_AND_WRAP,
182 VK_STENCIL_OP_DECREMENT_AND_WRAP};
183
184 const VkCompareOp compareOps[] = {VK_COMPARE_OP_NEVER,
185 VK_COMPARE_OP_LESS,
186 VK_COMPARE_OP_EQUAL,
187 VK_COMPARE_OP_LESS_OR_EQUAL,
188 VK_COMPARE_OP_GREATER,
189 VK_COMPARE_OP_NOT_EQUAL,
190 VK_COMPARE_OP_GREATER_OR_EQUAL,
191 VK_COMPARE_OP_ALWAYS};
192
193 // StencilOpStateUniqueRandomIterator
194
195 const uint32_t StencilOpStateUniqueRandomIterator::s_stencilOpsLength = DE_LENGTH_OF_ARRAY(stencilOps);
196 const uint32_t StencilOpStateUniqueRandomIterator::s_stencilOpsLength2 = s_stencilOpsLength * s_stencilOpsLength;
197 const uint32_t StencilOpStateUniqueRandomIterator::s_stencilOpsLength3 = s_stencilOpsLength2 * s_stencilOpsLength;
198 const uint32_t StencilOpStateUniqueRandomIterator::s_compareOpsLength = DE_LENGTH_OF_ARRAY(compareOps);
199 const uint32_t StencilOpStateUniqueRandomIterator::s_totalStencilOpStates = s_stencilOpsLength3 * s_compareOpsLength;
200
StencilOpStateUniqueRandomIterator(int seed)201 StencilOpStateUniqueRandomIterator::StencilOpStateUniqueRandomIterator(int seed)
202 : UniqueRandomIterator<VkStencilOpState>(s_totalStencilOpStates, s_totalStencilOpStates, seed)
203 {
204 }
205
getIndexedValue(uint32_t index)206 VkStencilOpState StencilOpStateUniqueRandomIterator::getIndexedValue(uint32_t index)
207 {
208 const uint32_t stencilCompareOpIndex = index / s_stencilOpsLength3;
209 const uint32_t stencilCompareOpSeqIndex = stencilCompareOpIndex * s_stencilOpsLength3;
210
211 const uint32_t stencilDepthFailOpIndex = (index - stencilCompareOpSeqIndex) / s_stencilOpsLength2;
212 const uint32_t stencilDepthFailOpSeqIndex = stencilDepthFailOpIndex * s_stencilOpsLength2;
213
214 const uint32_t stencilPassOpIndex =
215 (index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex) / s_stencilOpsLength;
216 const uint32_t stencilPassOpSeqIndex = stencilPassOpIndex * s_stencilOpsLength;
217
218 const uint32_t stencilFailOpIndex =
219 index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex - stencilPassOpSeqIndex;
220
221 const VkStencilOpState stencilOpState = {
222 stencilOps[stencilFailOpIndex], // VkStencilOp failOp;
223 stencilOps[stencilPassOpIndex], // VkStencilOp passOp;
224 stencilOps[stencilDepthFailOpIndex], // VkStencilOp depthFailOp;
225 compareOps[stencilCompareOpIndex], // VkCompareOp compareOp;
226 0x0, // uint32_t compareMask;
227 0x0, // uint32_t writeMask;
228 0x0 // uint32_t reference;
229 };
230
231 return stencilOpState;
232 }
233
234 // StencilTest
235
236 const StencilTest::StencilStateConfig StencilTest::s_stencilStateConfigs[QUAD_COUNT] = {
237 // frontReadMask frontWriteMask frontRef backReadMask backWriteMask backRef
238 {0xFF, 0xFF, 0xAB, 0xF0, 0xFF, 0xFF},
239 {0xFF, 0xF0, 0xCD, 0xF0, 0xF0, 0xEF},
240 {0xF0, 0x0F, 0xEF, 0xFF, 0x0F, 0xCD},
241 {0xF0, 0x01, 0xFF, 0xFF, 0x01, 0xAB}};
242
243 const float StencilTest::s_quadDepths[QUAD_COUNT] = {0.1f, 0.0f, 0.3f, 0.2f};
244
StencilTest(tcu::TestContext & testContext,const std::string & name,PipelineConstructionType pipelineConstructionType,VkFormat stencilFormat,const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack,const bool colorAttachmentEnable,const bool separateDepthStencilLayouts)245 StencilTest::StencilTest(tcu::TestContext &testContext, const std::string &name,
246 PipelineConstructionType pipelineConstructionType, VkFormat stencilFormat,
247 const VkStencilOpState &stencilOpStateFront, const VkStencilOpState &stencilOpStateBack,
248 const bool colorAttachmentEnable, const bool separateDepthStencilLayouts)
249 : vkt::TestCase(testContext, name)
250 , m_pipelineConstructionType(pipelineConstructionType)
251 , m_stencilFormat(stencilFormat)
252 , m_stencilOpStateFront(stencilOpStateFront)
253 , m_stencilOpStateBack(stencilOpStateBack)
254 , m_colorAttachmentEnable(colorAttachmentEnable)
255 , m_separateDepthStencilLayouts(separateDepthStencilLayouts)
256 {
257 }
258
checkSupport(Context & context) const259 void StencilTest::checkSupport(Context &context) const
260 {
261 if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_stencilFormat))
262 throw tcu::NotSupportedError(std::string("Unsupported depth/stencil format: ") +
263 getFormatName(m_stencilFormat));
264
265 if (m_separateDepthStencilLayouts &&
266 !context.isDeviceFunctionalitySupported("VK_KHR_separate_depth_stencil_layouts"))
267 TCU_THROW(NotSupportedError, "VK_KHR_separate_depth_stencil_layouts is not supported");
268
269 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
270 m_pipelineConstructionType);
271
272 #ifndef CTS_USES_VULKANSC
273 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
274 !context.getPortabilitySubsetFeatures().separateStencilMaskRef)
275 TCU_THROW(
276 NotSupportedError,
277 "VK_KHR_portability_subset: Separate stencil mask references are not supported by this implementation");
278 #endif // CTS_USES_VULKANSC
279 }
280
createInstance(Context & context) const281 TestInstance *StencilTest::createInstance(Context &context) const
282 {
283 return new StencilTestInstance(context, m_pipelineConstructionType, m_stencilFormat, m_stencilOpStateFront,
284 m_stencilOpStateBack, m_colorAttachmentEnable, m_separateDepthStencilLayouts);
285 }
286
initPrograms(SourceCollections & sourceCollections) const287 void StencilTest::initPrograms(SourceCollections &sourceCollections) const
288 {
289 if (m_colorAttachmentEnable)
290 {
291 sourceCollections.glslSources.add("color_vert")
292 << glu::VertexSource("#version 310 es\n"
293 "layout(location = 0) in vec4 position;\n"
294 "layout(location = 1) in vec4 color;\n"
295 "layout(location = 0) out highp vec4 vtxColor;\n"
296 "void main (void)\n"
297 "{\n"
298 " gl_Position = position;\n"
299 " vtxColor = color;\n"
300 "}\n");
301
302 sourceCollections.glslSources.add("color_frag")
303 << glu::FragmentSource("#version 310 es\n"
304 "layout(location = 0) in highp vec4 vtxColor;\n"
305 "layout(location = 0) out highp vec4 fragColor;\n"
306 "void main (void)\n"
307 "{\n"
308 " fragColor = vtxColor;\n"
309 "}\n");
310 }
311 else
312 {
313 sourceCollections.glslSources.add("color_vert") << glu::VertexSource("#version 310 es\n"
314 "layout(location = 0) in vec4 position;\n"
315 "layout(location = 1) in vec4 color;\n"
316 "void main (void)\n"
317 "{\n"
318 " gl_Position = position;\n"
319 "}\n");
320 }
321 }
322
323 // StencilTestInstance
324
StencilTestInstance(Context & context,PipelineConstructionType pipelineConstructionType,VkFormat stencilFormat,const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack,const bool colorAttachmentEnable,const bool separateDepthStencilLayouts)325 StencilTestInstance::StencilTestInstance(Context &context, PipelineConstructionType pipelineConstructionType,
326 VkFormat stencilFormat, const VkStencilOpState &stencilOpStateFront,
327 const VkStencilOpState &stencilOpStateBack, const bool colorAttachmentEnable,
328 const bool separateDepthStencilLayouts)
329 : vkt::TestInstance(context)
330 , m_stencilOpStateFront(stencilOpStateFront)
331 , m_stencilOpStateBack(stencilOpStateBack)
332 , m_colorAttachmentEnable(colorAttachmentEnable)
333 , m_separateDepthStencilLayouts(separateDepthStencilLayouts)
334 , m_renderSize(32, 32)
335 , m_colorFormat(colorAttachmentEnable ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED)
336 , m_stencilFormat(stencilFormat)
337 , m_graphicsPipelines{{context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
338 context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
339 {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
340 context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
341 {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
342 context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
343 {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
344 context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType}}
345 {
346 const DeviceInterface &vk = context.getDeviceInterface();
347 const VkDevice vkDevice = context.getDevice();
348 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
349 SimpleAllocator memAlloc(
350 vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
351 const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
352 VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
353
354 // Create color image
355 if (m_colorAttachmentEnable)
356 {
357 const VkImageCreateInfo colorImageParams = {
358 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
359 nullptr, // const void* pNext;
360 0u, // VkImageCreateFlags flags;
361 VK_IMAGE_TYPE_2D, // VkImageType imageType;
362 m_colorFormat, // VkFormat format;
363 {m_renderSize.x(), m_renderSize.y(), 1u}, // VkExtent3D extent;
364 1u, // uint32_t mipLevels;
365 1u, // uint32_t arrayLayers;
366 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
367 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
368 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
369 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
370 1u, // uint32_t queueFamilyIndexCount;
371 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
372 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
373 };
374
375 m_colorImageCreateInfo = colorImageParams;
376 m_colorImage = createImage(vk, vkDevice, &m_colorImageCreateInfo);
377
378 // Allocate and bind color image memory
379 m_colorImageAlloc =
380 memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
381 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(),
382 m_colorImageAlloc->getOffset()));
383 }
384
385 // Create stencil image
386 {
387 const VkImageUsageFlags usageFlags =
388 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
389
390 const VkImageCreateInfo stencilImageParams = {
391 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
392 nullptr, // const void* pNext;
393 0u, // VkImageCreateFlags flags;
394 VK_IMAGE_TYPE_2D, // VkImageType imageType;
395 m_stencilFormat, // VkFormat format;
396 {m_renderSize.x(), m_renderSize.y(), 1u}, // VkExtent3D extent;
397 1u, // uint32_t mipLevels;
398 1u, // uint32_t arrayLayers;
399 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
400 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
401 usageFlags, // VkImageUsageFlags usage;
402 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
403 1u, // uint32_t queueFamilyIndexCount;
404 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
405 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
406 };
407
408 m_stencilImage = createImage(vk, vkDevice, &stencilImageParams);
409
410 // Allocate and bind stencil image memory
411 m_stencilImageAlloc =
412 memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_stencilImage), MemoryRequirement::Any);
413 VK_CHECK(vk.bindImageMemory(vkDevice, *m_stencilImage, m_stencilImageAlloc->getMemory(),
414 m_stencilImageAlloc->getOffset()));
415
416 const VkImageAspectFlags aspect = (mapVkFormat(m_stencilFormat).order == tcu::TextureFormat::DS ?
417 VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT :
418 VK_IMAGE_ASPECT_STENCIL_BIT);
419 m_stencilImageSubresourceRange =
420 makeImageSubresourceRange(aspect, 0u, stencilImageParams.mipLevels, 0u, stencilImageParams.arrayLayers);
421 }
422
423 // Create color attachment view
424 if (m_colorAttachmentEnable)
425 {
426 const VkImageViewCreateInfo colorAttachmentViewParams = {
427 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
428 nullptr, // const void* pNext;
429 0u, // VkImageViewCreateFlags flags;
430 *m_colorImage, // VkImage image;
431 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
432 m_colorFormat, // VkFormat format;
433 componentMappingRGBA, // VkComponentMapping components;
434 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
435 };
436
437 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
438 }
439
440 // Create stencil attachment view
441 {
442 const VkImageViewCreateInfo stencilAttachmentViewParams = {
443 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
444 nullptr, // const void* pNext;
445 0u, // VkImageViewCreateFlags flags;
446 *m_stencilImage, // VkImage image;
447 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
448 m_stencilFormat, // VkFormat format;
449 componentMappingRGBA, // VkComponentMapping components;
450 m_stencilImageSubresourceRange, // VkImageSubresourceRange subresourceRange;
451 };
452
453 m_stencilAttachmentView = createImageView(vk, vkDevice, &stencilAttachmentViewParams);
454 }
455
456 // Create render pass
457 m_renderPass = RenderPassWrapper(pipelineConstructionType, vk, vkDevice, m_colorFormat, m_stencilFormat);
458
459 // Create framebuffer
460 {
461 std::vector<VkImage> images;
462 std::vector<VkImageView> attachmentBindInfos;
463
464 if (m_colorAttachmentEnable)
465 {
466 images.push_back(*m_colorImage);
467 attachmentBindInfos.push_back(*m_colorAttachmentView);
468 }
469
470 images.push_back(*m_stencilImage);
471 attachmentBindInfos.push_back(*m_stencilAttachmentView);
472
473 const VkFramebufferCreateInfo framebufferParams = {
474 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
475 nullptr, // const void* pNext;
476 0u, // VkFramebufferCreateFlags flags;
477 *m_renderPass, // VkRenderPass renderPass;
478 (uint32_t)attachmentBindInfos.size(), // uint32_t attachmentCount;
479 attachmentBindInfos.data(), // const VkImageView* pAttachments;
480 (uint32_t)m_renderSize.x(), // uint32_t width;
481 (uint32_t)m_renderSize.y(), // uint32_t height;
482 1u // uint32_t layers;
483 };
484
485 m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
486 }
487
488 // Create pipeline layout
489 {
490 const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
491 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
492 nullptr, // const void* pNext;
493 0u, // VkPipelineLayoutCreateFlags flags;
494 0u, // uint32_t setLayoutCount;
495 nullptr, // const VkDescriptorSetLayout* pSetLayouts;
496 0u, // uint32_t pushConstantRangeCount;
497 nullptr // const VkPushConstantRange* pPushConstantRanges;
498 };
499
500 m_pipelineLayout = PipelineLayoutWrapper(pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
501 }
502
503 m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
504 if (m_colorAttachmentEnable)
505 m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
506
507 // Create pipeline
508 {
509 const VkVertexInputBindingDescription vertexInputBindingDescription{
510 0u, // uint32_t binding;
511 sizeof(Vertex4RGBA), // uint32_t strideInBytes;
512 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
513 };
514
515 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2]{
516 {
517 0u, // uint32_t location;
518 0u, // uint32_t binding;
519 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
520 0u // uint32_t offsetInBytes;
521 },
522 {
523 1u, // uint32_t location;
524 0u, // uint32_t binding;
525 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
526 offsetof(Vertex4RGBA, color), // uint32_t offsetInBytes;
527 }};
528
529 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams{
530 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
531 nullptr, // const void* pNext;
532 0u, // VkPipelineVertexInputStateCreateFlags flags;
533 1u, // uint32_t vertexBindingDescriptionCount;
534 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
535 2u, // uint32_t vertexAttributeDescriptionCount;
536 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
537 };
538
539 const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
540 const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
541
542 const bool isDepthEnabled = (vk::mapVkFormat(m_stencilFormat).order != tcu::TextureFormat::S);
543
544 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams{
545 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
546 nullptr, // const void* pNext;
547 0u, // VkPipelineDepthStencilStateCreateFlags flags;
548 isDepthEnabled, // VkBool32 depthTestEnable;
549 isDepthEnabled, // VkBool32 depthWriteEnable;
550 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
551 false, // VkBool32 depthBoundsTestEnable;
552 true, // VkBool32 stencilTestEnable;
553 m_stencilOpStateFront, // VkStencilOpState front;
554 m_stencilOpStateBack, // VkStencilOpState back;
555 0.0f, // float minDepthBounds;
556 1.0f // float maxDepthBounds;
557 };
558
559 // Make sure rasterization is not disabled when the fragment shader is missing.
560 const vk::VkPipelineRasterizationStateCreateInfo rasterizationStateParams{
561 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
562 nullptr, // const void* pNext;
563 0u, // VkPipelineRasterizationStateCreateFlags flags;
564 VK_FALSE, // VkBool32 depthClampEnable;
565 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
566 vk::VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
567 vk::VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
568 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
569 VK_FALSE, // VkBool32 depthBiasEnable;
570 0.0f, // float depthBiasConstantFactor;
571 0.0f, // float depthBiasClamp;
572 0.0f, // float depthBiasSlopeFactor;
573 1.0f, // float lineWidth;
574 };
575
576 const vk::VkPipelineColorBlendAttachmentState blendState{
577 VK_FALSE,
578 VK_BLEND_FACTOR_ONE,
579 VK_BLEND_FACTOR_ONE,
580 VK_BLEND_OP_ADD,
581 VK_BLEND_FACTOR_ONE,
582 VK_BLEND_FACTOR_ONE,
583 VK_BLEND_OP_ADD,
584 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
585
586 };
587 const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateParams{
588 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
589 nullptr, // const void* pNext
590 0u, // VkPipelineColorBlendStateCreateFlags flags
591 VK_FALSE, // VkBool32 logicOpEnable
592 vk::VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp
593 m_colorAttachmentEnable ? 1u : 0u, // uint32_t attachmentCount
594 &blendState, // const VkPipelineColorBlendAttachmentState* pAttachments
595 {1.0f, 1.0f, 1.0f, 1.0f} // float blendConstants[4]
596 };
597
598 // Setup different stencil masks and refs in each quad
599 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
600 {
601 const StencilTest::StencilStateConfig &config = StencilTest::s_stencilStateConfigs[quadNdx];
602 VkStencilOpState &front = depthStencilStateParams.front;
603 VkStencilOpState &back = depthStencilStateParams.back;
604
605 front.compareMask = config.frontReadMask;
606 front.writeMask = config.frontWriteMask;
607 front.reference = config.frontRef;
608
609 back.compareMask = config.backReadMask;
610 back.writeMask = config.backWriteMask;
611 back.reference = config.backRef;
612
613 m_graphicsPipelines[quadNdx]
614 .setDefaultRasterizerDiscardEnable(!m_colorAttachmentEnable)
615 .setDefaultMultisampleState()
616 .setupVertexInputState(&vertexInputStateParams)
617 .setupPreRasterizationShaderState(viewports, scissors, m_pipelineLayout, *m_renderPass, 0u,
618 m_vertexShaderModule, &rasterizationStateParams)
619 .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule,
620 &depthStencilStateParams)
621 .setupFragmentOutputState(*m_renderPass, 0,
622 (m_colorAttachmentEnable ? &colorBlendStateParams : nullptr))
623 .setMonolithicPipelineLayout(m_pipelineLayout)
624 .buildPipeline();
625 }
626 }
627
628 // Create vertex buffer
629 {
630 const VkBufferCreateInfo vertexBufferParams = {
631 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
632 nullptr, // const void* pNext;
633 0u, // VkBufferCreateFlags flags;
634 1024u, // VkDeviceSize size;
635 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
636 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
637 1u, // uint32_t queueFamilyIndexCount;
638 &queueFamilyIndex // const uint32_t* pQueueFamilyIndices;
639 };
640
641 m_vertices = createOverlappingQuads();
642 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
643 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),
644 MemoryRequirement::HostVisible);
645
646 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
647 m_vertexBufferAlloc->getOffset()));
648
649 // Adjust depths
650 for (int quadNdx = 0; quadNdx < 4; quadNdx++)
651 for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
652 m_vertices[quadNdx * 6 + vertexNdx].position.z() = StencilTest::s_quadDepths[quadNdx];
653
654 // Load vertices into vertex buffer
655 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
656 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
657 }
658
659 // Create command pool
660 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
661
662 // Create command buffer
663 {
664 const VkImageMemoryBarrier colorImageBarrier = {
665 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
666 nullptr, // const void* pNext;
667 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
668 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
669 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
670 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
671 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
672 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
673 *m_colorImage, // VkImage image;
674 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
675 };
676
677 VkImageSubresourceRange stencilImageBarrierSubresourceRange = m_stencilImageSubresourceRange;
678 VkImageLayout newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
679 if (m_separateDepthStencilLayouts)
680 {
681 stencilImageBarrierSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
682 newLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
683 }
684
685 const VkImageMemoryBarrier stencilImageBarrier = {
686 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
687 nullptr, // const void* pNext;
688 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
689 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
690 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
691 newLayout, // VkImageLayout newLayout;
692 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
693 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
694 *m_stencilImage, // VkImage image;
695 stencilImageBarrierSubresourceRange, // VkImageSubresourceRange subresourceRange;
696 };
697
698 std::vector<VkClearValue> attachmentClearValues;
699 std::vector<VkImageMemoryBarrier> imageLayoutBarriers;
700
701 if (m_colorAttachmentEnable)
702 {
703 attachmentClearValues.push_back(defaultClearValue(m_colorFormat));
704 imageLayoutBarriers.push_back(colorImageBarrier);
705 }
706
707 attachmentClearValues.push_back(defaultClearValue(m_stencilFormat));
708 imageLayoutBarriers.push_back(stencilImageBarrier);
709
710 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
711
712 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
713
714 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
715 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
716 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
717 (VkDependencyFlags)0, 0u, nullptr, 0u, nullptr, (uint32_t)imageLayoutBarriers.size(),
718 imageLayoutBarriers.data());
719
720 m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
721 (uint32_t)attachmentClearValues.size(), attachmentClearValues.data());
722
723 const VkDeviceSize quadOffset = (m_vertices.size() / StencilTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
724
725 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
726 {
727 VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
728
729 m_graphicsPipelines[quadNdx].bind(*m_cmdBuffer);
730 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
731 vk.cmdDraw(*m_cmdBuffer, (uint32_t)(m_vertices.size() / StencilTest::QUAD_COUNT), 1, 0, 0);
732 }
733
734 m_renderPass.end(vk, *m_cmdBuffer);
735 endCommandBuffer(vk, *m_cmdBuffer);
736 }
737 }
738
iterate(void)739 tcu::TestStatus StencilTestInstance::iterate(void)
740 {
741 const DeviceInterface &vk = m_context.getDeviceInterface();
742 const VkDevice vkDevice = m_context.getDevice();
743 const VkQueue queue = m_context.getUniversalQueue();
744
745 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
746
747 return verifyImage();
748 }
749
verifyImage(void)750 tcu::TestStatus StencilTestInstance::verifyImage(void)
751 {
752 const tcu::TextureFormat tcuColorFormat = mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
753 const tcu::TextureFormat tcuStencilFormat = mapVkFormat(m_stencilFormat);
754 const ColorVertexShader vertexShader;
755 const ColorFragmentShader fragmentShader(tcuColorFormat, tcuStencilFormat);
756 const rr::Program program(&vertexShader, &fragmentShader);
757 ReferenceRenderer refRenderer(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
758 bool colorCompareOk = false;
759 bool stencilCompareOk = false;
760
761 // Render reference image
762 {
763 // Set depth state
764 rr::RenderState renderState(refRenderer.getViewportState(),
765 m_context.getDeviceProperties().limits.subPixelPrecisionBits);
766
767 renderState.fragOps.depthTestEnabled = true;
768 renderState.fragOps.depthFunc = mapVkCompareOp(VK_COMPARE_OP_LESS);
769 renderState.fragOps.stencilTestEnabled = true;
770
771 rr::StencilState &refStencilFront = renderState.fragOps.stencilStates[rr::FACETYPE_FRONT];
772 rr::StencilState &refStencilBack = renderState.fragOps.stencilStates[rr::FACETYPE_BACK];
773
774 refStencilFront.sFail = mapVkStencilOp(m_stencilOpStateFront.failOp);
775 refStencilFront.dpFail = mapVkStencilOp(m_stencilOpStateFront.depthFailOp);
776 refStencilFront.dpPass = mapVkStencilOp(m_stencilOpStateFront.passOp);
777 refStencilFront.func = mapVkCompareOp(m_stencilOpStateFront.compareOp);
778
779 refStencilBack.sFail = mapVkStencilOp(m_stencilOpStateBack.failOp);
780 refStencilBack.dpPass = mapVkStencilOp(m_stencilOpStateBack.passOp);
781 refStencilBack.dpFail = mapVkStencilOp(m_stencilOpStateBack.depthFailOp);
782 refStencilBack.func = mapVkCompareOp(m_stencilOpStateBack.compareOp);
783
784 // Reverse winding of vertices, as Vulkan screen coordinates start at upper left
785 std::vector<Vertex4RGBA> cwVertices(m_vertices);
786 for (size_t vertexNdx = 0; vertexNdx < cwVertices.size() - 2; vertexNdx += 3)
787 {
788 const Vertex4RGBA cwVertex1 = cwVertices[vertexNdx + 1];
789
790 cwVertices[vertexNdx + 1] = cwVertices[vertexNdx + 2];
791 cwVertices[vertexNdx + 2] = cwVertex1;
792 }
793
794 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
795 {
796 refStencilFront.ref = (int)StencilTest::s_stencilStateConfigs[quadNdx].frontRef;
797 refStencilFront.compMask = StencilTest::s_stencilStateConfigs[quadNdx].frontReadMask;
798 refStencilFront.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].frontWriteMask;
799
800 refStencilBack.ref = (int)StencilTest::s_stencilStateConfigs[quadNdx].backRef;
801 refStencilBack.compMask = StencilTest::s_stencilStateConfigs[quadNdx].backReadMask;
802 refStencilBack.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].backWriteMask;
803
804 refRenderer.draw(
805 renderState, rr::PRIMITIVETYPE_TRIANGLES,
806 std::vector<Vertex4RGBA>(cwVertices.begin() + quadNdx * 6, cwVertices.begin() + (quadNdx + 1) * 6));
807 }
808 }
809
810 // Compare result with reference image
811 if (m_colorAttachmentEnable)
812 {
813 const DeviceInterface &vk = m_context.getDeviceInterface();
814 const VkDevice vkDevice = m_context.getDevice();
815 const VkQueue queue = m_context.getUniversalQueue();
816 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
817 SimpleAllocator allocator(
818 vk, vkDevice,
819 getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
820 de::UniquePtr<tcu::TextureLevel> result(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator,
821 *m_colorImage, m_colorFormat, m_renderSize)
822 .release());
823
824 colorCompareOk = tcu::intThresholdPositionDeviationCompare(
825 m_context.getTestContext().getLog(), "IntImageCompare", "Image comparison", refRenderer.getAccess(),
826 result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
827 }
828 else
829 {
830 colorCompareOk = true;
831 }
832
833 // Compare stencil result with reference image
834 {
835 const DeviceInterface &vk = m_context.getDeviceInterface();
836 const VkDevice vkDevice = m_context.getDevice();
837 const VkQueue queue = m_context.getUniversalQueue();
838 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
839 SimpleAllocator allocator(
840 vk, vkDevice,
841 getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
842 de::UniquePtr<tcu::TextureLevel> result(readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator,
843 *m_stencilImage, m_stencilFormat, m_renderSize)
844 .release());
845
846 {
847 const tcu::PixelBufferAccess stencilAccess(
848 tcu::getEffectiveDepthStencilAccess(refRenderer.getDepthStencilAccess(), tcu::Sampler::MODE_STENCIL));
849 stencilCompareOk = tcu::intThresholdPositionDeviationCompare(
850 m_context.getTestContext().getLog(), "StencilImageCompare", "Stencil image comparison", stencilAccess,
851 result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, 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 struct NoStencilAttachmentParams
862 {
863 PipelineConstructionType pipelineConstructionType;
864 VkFormat format;
865 bool dynamicRendering;
866 bool dynamicEnable;
867
useDynamicRenderingvkt::pipeline::__anon7d94880a0111::NoStencilAttachmentParams868 bool useDynamicRendering(void) const
869 {
870 return (dynamicRendering || isConstructionTypeShaderObject(pipelineConstructionType));
871 }
872 };
873
874 class NoStencilAttachmentCase : public vkt::TestCase
875 {
876 public:
NoStencilAttachmentCase(tcu::TestContext & testCtx,const std::string & name,const NoStencilAttachmentParams & params)877 NoStencilAttachmentCase(tcu::TestContext &testCtx, const std::string &name, const NoStencilAttachmentParams ¶ms)
878 : vkt::TestCase(testCtx, name)
879 , m_params(params)
880 {
881 }
~NoStencilAttachmentCase(void)882 virtual ~NoStencilAttachmentCase(void)
883 {
884 }
885
886 void checkSupport(Context &context) const override;
887 void initPrograms(vk::SourceCollections &programCollection) const override;
888 TestInstance *createInstance(Context &context) const override;
889
890 static void getImageCreateInfo(VkImageCreateInfo *createInfo, const VkFormat format);
891 static tcu::Vec4 getClearColor(void);
892 static tcu::Vec4 getGeometryColor(void);
893
894 protected:
895 const NoStencilAttachmentParams m_params;
896 };
897
898 class NoStencilAttachmentInstance : public vkt::TestInstance
899 {
900 public:
NoStencilAttachmentInstance(Context & context,const NoStencilAttachmentParams & params)901 NoStencilAttachmentInstance(Context &context, const NoStencilAttachmentParams ¶ms)
902 : vkt::TestInstance(context)
903 , m_params(params)
904 {
905 }
~NoStencilAttachmentInstance(void)906 virtual ~NoStencilAttachmentInstance(void)
907 {
908 }
909
910 tcu::TestStatus iterate(void) override;
911
912 protected:
913 const NoStencilAttachmentParams m_params;
914 };
915
getImageCreateInfo(VkImageCreateInfo * createInfo_,const VkFormat format)916 void NoStencilAttachmentCase::getImageCreateInfo(VkImageCreateInfo *createInfo_, const VkFormat format)
917 {
918 const VkImageUsageFlags mainUsage = (isDepthStencilFormat(format) ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT :
919 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
920 const VkImageUsageFlags usage = (mainUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
921
922 *createInfo_ = {
923 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
924 nullptr, // const void* pNext;
925 0u, // VkImageCreateFlags flags;
926 VK_IMAGE_TYPE_2D, // VkImageType imageType;
927 format, // VkFormat format;
928 makeExtent3D(32u, 32u, 1u), // VkExtent3D extent;
929 1u, // uint32_t mipLevels;
930 1u, // uint32_t arrayLayers;
931 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
932 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
933 usage, // VkImageUsageFlags usage;
934 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
935 0u, // uint32_t queueFamilyIndexCount;
936 nullptr, // const uint32_t* pQueueFamilyIndices;
937 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
938 };
939 }
940
getClearColor(void)941 tcu::Vec4 NoStencilAttachmentCase::getClearColor(void)
942 {
943 return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
944 }
945
getGeometryColor(void)946 tcu::Vec4 NoStencilAttachmentCase::getGeometryColor(void)
947 {
948 return tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
949 }
950
checkSupport(Context & context) const951 void NoStencilAttachmentCase::checkSupport(Context &context) const
952 {
953 const auto &vki = context.getInstanceInterface();
954 const auto physicalDevice = context.getPhysicalDevice();
955
956 checkPipelineConstructionRequirements(vki, physicalDevice, m_params.pipelineConstructionType);
957
958 if (m_params.dynamicRendering)
959 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
960
961 if (m_params.dynamicEnable && !isConstructionTypeShaderObject(m_params.pipelineConstructionType))
962 context.requireDeviceFunctionality("VK_EXT_extended_dynamic_state");
963
964 VkImageCreateInfo createInfo;
965 VkImageFormatProperties imgFormatProperties;
966
967 getImageCreateInfo(&createInfo, m_params.format);
968
969 const auto result = vki.getPhysicalDeviceImageFormatProperties(
970 physicalDevice, createInfo.format, createInfo.imageType, createInfo.tiling, createInfo.usage, createInfo.flags,
971 &imgFormatProperties);
972
973 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
974 TCU_THROW(NotSupportedError, "Format does not support the required features");
975
976 VK_CHECK(result);
977 }
978
initPrograms(SourceCollections & dst) const979 void NoStencilAttachmentCase::initPrograms(SourceCollections &dst) const
980 {
981 std::ostringstream vert;
982 vert << "#version 460\n"
983 << "vec2 positions[3] = vec2[](\n"
984 << " vec2(-1.0, -1.0),\n"
985 << " vec2( 3.0, -1.0),\n"
986 << " vec2(-1.0, 3.0)\n"
987 << ");\n"
988 << "layout (push_constant, std430) uniform PushConstantBlock {\n"
989 << " float depth;\n"
990 << "} pc;\n"
991 << "void main (void) {\n"
992 << " gl_Position = vec4(positions[gl_VertexIndex % 3], pc.depth, 1.0);\n"
993 << "}\n";
994 dst.glslSources.add("vert") << glu::VertexSource(vert.str());
995
996 std::ostringstream frag;
997 frag << "#version 460\n"
998 << "layout (location=0) out vec4 outColor;\n"
999 << "void main (void) {\n"
1000 << " outColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
1001 << "}\n";
1002 dst.glslSources.add("frag") << glu::FragmentSource(frag.str());
1003 }
1004
createInstance(Context & context) const1005 TestInstance *NoStencilAttachmentCase::createInstance(Context &context) const
1006 {
1007 return new NoStencilAttachmentInstance(context, m_params);
1008 }
1009
1010 // The goal here is indicating the stencil attachment is not present, either because there is no stencil aspect in the depth/stencil
1011 // format or because (when using dynamic rendering) the stencil attachment and format are null/unused respectively. Despite this
1012 // setup, in the depth/stencil pipeline state or dynamic state, we will indicate the stencil test is enabled.
1013 //
1014 // According to the spec, if there is no stencil attachment, the stencil test should not modify coverage and should be effectively
1015 // disabled.
iterate(void)1016 tcu::TestStatus NoStencilAttachmentInstance::iterate(void)
1017 {
1018 const auto &ctx = m_context.getContextCommonData();
1019 const auto colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1020 const auto tcuColorFmt = mapVkFormat(colorFormat);
1021 const auto tcuDSFmt = mapVkFormat(m_params.format);
1022 const auto clearColor = NoStencilAttachmentCase::getClearColor();
1023 const auto geomColor = NoStencilAttachmentCase::getGeometryColor();
1024 const tcu::Vec4 threshold(0.0f, 0.0f, 0.0f, 0.0f); // When using 0 and 1 only, we expect exact results.
1025 const auto dataStages = VK_SHADER_STAGE_VERTEX_BIT;
1026 const float clearDepth = 0.5f;
1027 const float geomDepth = 0.75f;
1028 const uint32_t stencilClr = 255u;
1029 const uint32_t stencilRef = 128u;
1030 const bool useDR = m_params.useDynamicRendering();
1031
1032 // Formats used to verify the different aspects.
1033 const bool hasDepth = tcu::hasDepthComponent(tcuDSFmt.order);
1034 const bool hasStencil = tcu::hasStencilComponent(tcuDSFmt.order);
1035
1036 DE_ASSERT(hasDepth);
1037
1038 const auto depthCopyFormat = (hasDepth ? getDepthCopyFormat(m_params.format) : tcu::TextureFormat());
1039 const auto stencilCopyFormat = (hasStencil ? getStencilCopyFormat(m_params.format) : tcu::TextureFormat());
1040
1041 VkImageCreateInfo colorCreateInfo;
1042 VkImageCreateInfo dsCreateInfo;
1043
1044 NoStencilAttachmentCase::getImageCreateInfo(&colorCreateInfo, colorFormat);
1045 NoStencilAttachmentCase::getImageCreateInfo(&dsCreateInfo, m_params.format);
1046
1047 const auto &vkExtent = colorCreateInfo.extent;
1048 const auto fbExtent = tcu::IVec3(static_cast<int>(vkExtent.width), static_cast<int>(vkExtent.height),
1049 static_cast<int>(vkExtent.depth));
1050 const auto pixelCount = fbExtent.x() * fbExtent.y() * fbExtent.z();
1051 const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, colorCreateInfo.mipLevels, 0u,
1052 colorCreateInfo.arrayLayers);
1053 const auto dsSRR = makeImageSubresourceRange(getImageAspectFlags(tcuDSFmt), 0u, dsCreateInfo.mipLevels, 0u,
1054 dsCreateInfo.arrayLayers);
1055 const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, colorCreateInfo.arrayLayers);
1056 const auto depthSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, dsCreateInfo.arrayLayers);
1057 const auto stencilSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, dsCreateInfo.arrayLayers);
1058
1059 // Color buffer with verification buffer.
1060 ImageWithBuffer colorBuffer(ctx.vkd, ctx.device, ctx.allocator, colorCreateInfo.extent, colorCreateInfo.format,
1061 colorCreateInfo.usage, colorCreateInfo.imageType, colorSRR, colorCreateInfo.arrayLayers,
1062 colorCreateInfo.samples, colorCreateInfo.tiling, colorCreateInfo.mipLevels,
1063 colorCreateInfo.sharingMode);
1064
1065 ImageWithMemory dsBuffer(ctx.vkd, ctx.device, ctx.allocator, dsCreateInfo, MemoryRequirement::Any);
1066 const auto dsView =
1067 makeImageView(ctx.vkd, ctx.device, dsBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, dsCreateInfo.format, dsSRR);
1068
1069 // Verification buffers for depth/stencil.
1070 using BufferWithMemoryPtr = std::unique_ptr<BufferWithMemory>;
1071
1072 BufferWithMemoryPtr depthVerifBuffer;
1073 BufferWithMemoryPtr stencilVerifBuffer;
1074
1075 VkDeviceSize depthVerifBufferSize = 0ull;
1076 VkDeviceSize stencilVerifBufferSize = 0ull;
1077
1078 if (hasDepth)
1079 {
1080 depthVerifBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(depthCopyFormat) * pixelCount);
1081 const auto createInfo = makeBufferCreateInfo(depthVerifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1082 depthVerifBuffer.reset(
1083 new BufferWithMemory(ctx.vkd, ctx.device, ctx.allocator, createInfo, MemoryRequirement::HostVisible));
1084 }
1085
1086 if (hasStencil)
1087 {
1088 stencilVerifBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(stencilCopyFormat) * pixelCount);
1089 const auto createInfo = makeBufferCreateInfo(stencilVerifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1090 stencilVerifBuffer.reset(
1091 new BufferWithMemory(ctx.vkd, ctx.device, ctx.allocator, createInfo, MemoryRequirement::HostVisible));
1092 }
1093
1094 const std::vector<VkImageView> fbViews{colorBuffer.getImageView(), *dsView};
1095
1096 // Push constants.
1097 const auto pcSize = static_cast<uint32_t>(sizeof(geomDepth));
1098 const auto pcRange = makePushConstantRange(dataStages, 0u, pcSize);
1099
1100 const PipelineLayoutWrapper pipelineLayout(m_params.pipelineConstructionType, ctx.vkd, ctx.device, VK_NULL_HANDLE,
1101 &pcRange);
1102
1103 const auto renderPass = (useDR ? Move<VkRenderPass>() :
1104 makeRenderPass(ctx.vkd, ctx.device, colorCreateInfo.format, dsCreateInfo.format));
1105 const auto framebuffer = (useDR ? Move<VkFramebuffer>() :
1106 makeFramebuffer(ctx.vkd, ctx.device, *renderPass, de::sizeU32(fbViews),
1107 de::dataOrNull(fbViews), colorCreateInfo.extent.width,
1108 colorCreateInfo.extent.height, colorCreateInfo.arrayLayers));
1109
1110 // Modules.
1111 const auto &binaries = m_context.getBinaryCollection();
1112 const ShaderWrapper vertModule(ctx.vkd, ctx.device, binaries.get("vert"));
1113 const ShaderWrapper fragModule(ctx.vkd, ctx.device, binaries.get("frag"));
1114 const ShaderWrapper nullModule;
1115
1116 const std::vector<VkViewport> viewports(1u, makeViewport(colorCreateInfo.extent));
1117 const std::vector<VkRect2D> scissors(1u, makeRect2D(colorCreateInfo.extent));
1118
1119 // Depth/stencil state: note how, despite not having a stencil attachment, we enable the stencil test in a way that will not
1120 // preserve the stencil clear value no matter if the test passes or not.
1121 const auto stencilOpState = makeStencilOpState(VK_STENCIL_OP_ZERO, VK_STENCIL_OP_DECREMENT_AND_CLAMP,
1122 VK_STENCIL_OP_INVERT, VK_COMPARE_OP_EQUAL, 0xFFu, 0xFFu, stencilRef);
1123
1124 const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
1125 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
1126 nullptr, // const void* pNext;
1127 0u, // VkPipelineDepthStencilStateCreateFlags flags;
1128 VK_TRUE, // VkBool32 depthTestEnable;
1129 VK_TRUE, // VkBool32 depthWriteEnable;
1130 VK_COMPARE_OP_GREATER, // VkCompareOp depthCompareOp;
1131 VK_FALSE, // VkBool32 depthBoundsTestEnable;
1132 (m_params.dynamicEnable ? VK_FALSE : VK_TRUE), // VkBool32 stencilTestEnable;
1133 stencilOpState, // VkStencilOpState front;
1134 stencilOpState, // VkStencilOpState back;
1135 0.0f, // float minDepthBounds;
1136 1.0f, // float maxDepthBounds;
1137 };
1138
1139 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = initVulkanStructure();
1140
1141 #ifndef CTS_USES_VULKANSC
1142 // When using dynamic rendering, we'll signal the lack of a stencil attachment using VK_FORMAT_UNDEFINED for the stencil format.
1143 VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo = {
1144 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, // VkStructureType sType;
1145 nullptr, // const void* pNext;
1146 0u, // uint32_t viewMask;
1147 1u, // uint32_t colorAttachmentCount;
1148 &colorCreateInfo.format, // const VkFormat* pColorAttachmentFormats;
1149 dsCreateInfo.format, // VkFormat depthAttachmentFormat;
1150 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
1151 };
1152 #endif // CTS_USES_VULKANSC
1153
1154 PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfoPtr(
1155 #ifndef CTS_USES_VULKANSC
1156 &pipelineRenderingCreateInfo
1157 #else
1158 nullptr
1159 #endif // CTS_USES_VULKANSC
1160 );
1161
1162 std::vector<VkDynamicState> dynamicStates;
1163 if (m_params.dynamicEnable)
1164 dynamicStates.push_back(VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT);
1165
1166 const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
1167 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
1168 nullptr, // const void* pNext;
1169 0u, // VkPipelineDynamicStateCreateFlags flags;
1170 de::sizeU32(dynamicStates), // uint32_t dynamicStateCount;
1171 de::dataOrNull(dynamicStates), // const VkDynamicState* pDynamicStates;
1172 };
1173
1174 GraphicsPipelineWrapper pipelineWrapper(ctx.vki, ctx.vkd, ctx.physicalDevice, ctx.device,
1175 m_context.getDeviceExtensions(), m_params.pipelineConstructionType);
1176
1177 pipelineWrapper.setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
1178 .setDefaultRasterizationState()
1179 .setDefaultColorBlendState()
1180 .setDefaultMultisampleState()
1181 .setDynamicState(&dynamicStateCreateInfo)
1182 .setupVertexInputState(&vertexInputStateCreateInfo)
1183 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertModule, nullptr,
1184 nullModule, nullModule, nullModule, nullptr, nullptr,
1185 pipelineRenderingCreateInfoPtr)
1186 .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule, &depthStencilStateCreateInfo)
1187 .setupFragmentOutputState(*renderPass, 0u)
1188 .setMonolithicPipelineLayout(pipelineLayout)
1189 .buildPipeline();
1190
1191 CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
1192 const auto cmdBuffer = *cmd.cmdBuffer;
1193
1194 const std::vector<VkClearValue> clearValues{
1195 makeClearValueColor(clearColor),
1196 makeClearValueDepthStencil(clearDepth, stencilClr),
1197 };
1198
1199 beginCommandBuffer(ctx.vkd, cmdBuffer);
1200
1201 if (useDR)
1202 {
1203 // Transition image layouts and clear images, then begin rendering.
1204 const std::vector<VkImageMemoryBarrier> preClearBarriers{
1205 makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1206 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, colorBuffer.getImage(), colorSRR),
1207
1208 makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1209 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dsBuffer.get(), dsSRR),
1210 };
1211
1212 cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1213 VK_PIPELINE_STAGE_TRANSFER_BIT, de::dataOrNull(preClearBarriers),
1214 de::sizeU32(preClearBarriers));
1215
1216 // We want to use these clears instead of beginRendering clears to make sure the stencil aspect of the image is cleared too when present.
1217 ctx.vkd.cmdClearColorImage(cmdBuffer, colorBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1218 &clearValues.at(0u).color, 1u, &colorSRR);
1219 ctx.vkd.cmdClearDepthStencilImage(cmdBuffer, dsBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1220 &clearValues.at(1u).depthStencil, 1u, &dsSRR);
1221
1222 const std::vector<VkImageMemoryBarrier> postClearBarriers{
1223 makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT,
1224 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
1225 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1226 colorBuffer.getImage(), colorSRR),
1227
1228 makeImageMemoryBarrier(
1229 VK_ACCESS_TRANSFER_WRITE_BIT,
1230 (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT),
1231 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, dsBuffer.get(),
1232 dsSRR),
1233 };
1234
1235 const auto srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
1236 const auto dstStage = (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
1237 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1238
1239 cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, srcStage, dstStage, de::dataOrNull(postClearBarriers),
1240 de::sizeU32(postClearBarriers));
1241
1242 #ifndef CTS_USES_VULKANSC
1243 const VkRenderingAttachmentInfo colorAttInfo = {
1244 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType sType;
1245 nullptr, // const void* pNext;
1246 colorBuffer.getImageView(), // VkImageView imageView;
1247 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
1248 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
1249 VK_NULL_HANDLE, // VkImageView resolveImageView;
1250 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout;
1251 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
1252 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1253 /*unused*/ makeClearValueColor(tcu::Vec4(0.0f)), // VkClearValue clearValue;
1254 };
1255
1256 const VkRenderingAttachmentInfo depthAttInfo = {
1257 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType sType;
1258 nullptr, // const void* pNext;
1259 *dsView, // VkImageView imageView;
1260 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
1261 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
1262 VK_NULL_HANDLE, // VkImageView resolveImageView;
1263 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout;
1264 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
1265 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1266 /*unused*/ makeClearValueColor(tcu::Vec4(0.0f)), // VkClearValue clearValue;
1267 };
1268
1269 const VkRenderingInfo renderingInfo = {
1270 VK_STRUCTURE_TYPE_RENDERING_INFO, // VkStructureType sType;
1271 nullptr, // const void* pNext;
1272 0u, // VkRenderingFlags flags;
1273 scissors.at(0u), // VkRect2D renderArea;
1274 colorCreateInfo.arrayLayers, // uint32_t layerCount;
1275 0u, // uint32_t viewMask;
1276 1u, // uint32_t colorAttachmentCount;
1277 &colorAttInfo, // const VkRenderingAttachmentInfo* pColorAttachments;
1278 &depthAttInfo, // const VkRenderingAttachmentInfo* pDepthAttachment;
1279 nullptr, // const VkRenderingAttachmentInfo* pStencilAttachment;
1280 };
1281
1282 ctx.vkd.cmdBeginRendering(cmdBuffer, &renderingInfo);
1283 #else
1284 DE_ASSERT(false);
1285 #endif // CTS_USES_VULKANSC
1286 }
1287 else
1288 beginRenderPass(ctx.vkd, cmdBuffer, *renderPass, *framebuffer, scissors.at(0u), de::sizeU32(clearValues),
1289 de::dataOrNull(clearValues));
1290
1291 pipelineWrapper.bind(cmdBuffer);
1292 ctx.vkd.cmdPushConstants(cmdBuffer, *pipelineLayout, dataStages, 0u, pcSize, &geomDepth);
1293 if (m_params.dynamicEnable)
1294 {
1295 #ifndef CTS_USES_VULKANSC
1296 ctx.vkd.cmdSetStencilTestEnable(cmdBuffer, VK_TRUE);
1297 #else
1298 ctx.vkd.cmdSetStencilTestEnableEXT(cmdBuffer, VK_TRUE);
1299 #endif // CTS_USES_VULKANSC
1300 }
1301 ctx.vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
1302
1303 if (useDR)
1304 {
1305 #ifndef CTS_USES_VULKANSC
1306 endRendering(ctx.vkd, cmdBuffer);
1307 #else
1308 DE_ASSERT(false);
1309 #endif // CTS_USES_VULKANSC
1310 }
1311 else
1312 endRenderPass(ctx.vkd, cmdBuffer);
1313
1314 {
1315 const std::vector<VkImageMemoryBarrier> imgMemoryBarriers{
1316 makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1317 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1318 colorBuffer.getImage(), colorSRR),
1319
1320 makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1321 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1322 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dsBuffer.get(), dsSRR),
1323 };
1324
1325 const auto srcStages = (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
1326 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1327 const auto dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
1328
1329 cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, srcStages, dstStages, de::dataOrNull(imgMemoryBarriers),
1330 de::sizeU32(imgMemoryBarriers));
1331
1332 const auto colorRegion = makeBufferImageCopy(vkExtent, colorSRL);
1333 ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1334 colorBuffer.getBuffer(), 1u, &colorRegion);
1335
1336 if (hasDepth)
1337 {
1338 const auto depthRegion = makeBufferImageCopy(vkExtent, depthSRL);
1339 ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, dsBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1340 depthVerifBuffer->get(), 1u, &depthRegion);
1341 }
1342
1343 if (hasStencil)
1344 {
1345 const auto stencilRegion = makeBufferImageCopy(vkExtent, stencilSRL);
1346 ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, dsBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1347 stencilVerifBuffer->get(), 1u, &stencilRegion);
1348 }
1349
1350 const auto preHostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1351 cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1352 &preHostBarrier);
1353 }
1354
1355 endCommandBuffer(ctx.vkd, cmdBuffer);
1356 submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
1357
1358 // Verify color output.
1359 invalidateAlloc(ctx.vkd, ctx.device, colorBuffer.getBufferAllocation());
1360 tcu::PixelBufferAccess resultAccess(tcuColorFmt, fbExtent, colorBuffer.getBufferAllocation().getHostPtr());
1361
1362 tcu::TextureLevel referenceLevel(tcuColorFmt, fbExtent.x(), fbExtent.y());
1363 auto referenceAccess = referenceLevel.getAccess();
1364 tcu::clear(referenceAccess, geomColor);
1365
1366 auto &log = m_context.getTestContext().getLog();
1367 if (!tcu::floatThresholdCompare(log, "ResultColor", "", referenceAccess, resultAccess, threshold,
1368 tcu::COMPARE_LOG_ON_ERROR))
1369 return tcu::TestStatus::fail("Unexpected color in result buffer; check log for details");
1370
1371 // Verify depth/stencil if available.
1372 if (hasDepth)
1373 {
1374 const auto &allocation = depthVerifBuffer->getAllocation();
1375 invalidateAlloc(ctx.vkd, ctx.device, allocation);
1376
1377 tcu::PixelBufferAccess resultDepth(depthCopyFormat, fbExtent, allocation.getHostPtr());
1378 tcu::TextureLevel referenceDepth(depthCopyFormat, fbExtent.x(), fbExtent.y());
1379 auto refDepthAccess = referenceDepth.getAccess();
1380
1381 tcu::clearDepth(refDepthAccess, geomDepth);
1382 const float depthThreshold =
1383 0.000025f; // Should be good enough for D16, D24 and D32 given the depth values we're using.
1384
1385 if (!tcu::dsThresholdCompare(log, "ResultDepth", "", refDepthAccess, resultDepth, depthThreshold,
1386 tcu::COMPARE_LOG_ON_ERROR))
1387 return tcu::TestStatus::fail("Unexpected depth in result buffer; check log for details");
1388 }
1389 if (hasStencil)
1390 {
1391 const auto &allocation = stencilVerifBuffer->getAllocation();
1392 invalidateAlloc(ctx.vkd, ctx.device, allocation);
1393
1394 tcu::PixelBufferAccess resultStencil(stencilCopyFormat, fbExtent, allocation.getHostPtr());
1395 tcu::TextureLevel referenceStencil(stencilCopyFormat, fbExtent.x(), fbExtent.y());
1396 auto refStencilAccess = referenceStencil.getAccess();
1397
1398 tcu::clearStencil(refStencilAccess, stencilClr);
1399 const float stencilThreshold = 0.0f; // This is actually not used for stencil.
1400
1401 if (!tcu::dsThresholdCompare(log, "ResultStencil", "", refStencilAccess, resultStencil, stencilThreshold,
1402 tcu::COMPARE_LOG_ON_ERROR))
1403 return tcu::TestStatus::fail("Unexpected stencil value in result buffer; check log for details");
1404 }
1405
1406 return tcu::TestStatus::pass("Pass");
1407 }
1408
1409 // Utilities for test names
1410
getShortName(VkStencilOp stencilOp)1411 const char *getShortName(VkStencilOp stencilOp)
1412 {
1413 switch (stencilOp)
1414 {
1415 case VK_STENCIL_OP_KEEP:
1416 return "keep";
1417 case VK_STENCIL_OP_ZERO:
1418 return "zero";
1419 case VK_STENCIL_OP_REPLACE:
1420 return "repl";
1421 case VK_STENCIL_OP_INCREMENT_AND_CLAMP:
1422 return "incc";
1423 case VK_STENCIL_OP_DECREMENT_AND_CLAMP:
1424 return "decc";
1425 case VK_STENCIL_OP_INVERT:
1426 return "inv";
1427 case VK_STENCIL_OP_INCREMENT_AND_WRAP:
1428 return "wrap";
1429 case VK_STENCIL_OP_DECREMENT_AND_WRAP:
1430 return "decw";
1431
1432 default:
1433 DE_FATAL("Invalid VkStencilOpState value");
1434 }
1435 return nullptr;
1436 }
1437
getFormatCaseName(VkFormat format)1438 std::string getFormatCaseName(VkFormat format)
1439 {
1440 const std::string fullName = getFormatName(format);
1441
1442 DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
1443
1444 return de::toLower(fullName.substr(10));
1445 }
1446
1447 } // namespace
1448
createStencilTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)1449 tcu::TestCaseGroup *createStencilTests(tcu::TestContext &testCtx, PipelineConstructionType pipelineConstructionType)
1450 {
1451 const VkFormat stencilFormats[] = {VK_FORMAT_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT,
1452 VK_FORMAT_D32_SFLOAT_S8_UINT};
1453
1454 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(compareOps) == 8);
1455 DE_STATIC_ASSERT(vk::VK_COMPARE_OP_LAST == 8);
1456
1457 static const char *compareOpNames[8] = {"comp_never",
1458 "comp_less",
1459 "comp_equal",
1460 "comp_less_or_equal",
1461 "comp_greater",
1462 "comp_not_equal",
1463 "comp_greater_or_equal",
1464 "comp_always"};
1465
1466 // Stencil tests
1467 de::MovePtr<tcu::TestCaseGroup> stencilTests(new tcu::TestCaseGroup(testCtx, "stencil"));
1468 // Stencil tests with no color attachment
1469 de::MovePtr<tcu::TestCaseGroup> noColorAttachmentTests(new tcu::TestCaseGroup(testCtx, "nocolor"));
1470 const bool colorAttachmentEnabled[] = {true, false};
1471
1472 for (uint32_t colorAttachmentEnabledIdx = 0; colorAttachmentEnabledIdx < DE_LENGTH_OF_ARRAY(colorAttachmentEnabled);
1473 colorAttachmentEnabledIdx++)
1474 {
1475 const bool colorEnabled = colorAttachmentEnabled[colorAttachmentEnabledIdx];
1476 de::MovePtr<tcu::TestCaseGroup> formatTests(new tcu::TestCaseGroup(testCtx, "format"));
1477 StencilOpStateUniqueRandomIterator stencilOpItr(123);
1478
1479 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(stencilFormats); formatNdx++)
1480 {
1481 const VkFormat stencilFormat = stencilFormats[formatNdx];
1482 const bool hasDepth = tcu::hasDepthComponent(mapVkFormat(stencilFormat).order);
1483 const bool hasStencil = tcu::hasStencilComponent(mapVkFormat(stencilFormat).order);
1484 const int separateLayoutsLoopCount = (hasDepth && hasStencil) ? 2 : 1;
1485
1486 for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount;
1487 ++separateDepthStencilLayouts)
1488 {
1489 const bool useSeparateDepthStencilLayouts = bool(separateDepthStencilLayouts);
1490
1491 de::MovePtr<tcu::TestCaseGroup> formatTest(new tcu::TestCaseGroup(
1492 testCtx,
1493 (getFormatCaseName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : ""))
1494 .c_str()));
1495
1496 de::MovePtr<tcu::TestCaseGroup> stencilStateTests;
1497 {
1498 std::ostringstream desc;
1499 desc << "Draws 4 quads with the following depths and dynamic stencil states: ";
1500
1501 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
1502 {
1503 const StencilTest::StencilStateConfig &stencilConfig =
1504 StencilTest::s_stencilStateConfigs[quadNdx];
1505
1506 desc << "(" << quadNdx << ") "
1507 << "z = " << StencilTest::s_quadDepths[quadNdx] << ", "
1508 << "frontReadMask = " << stencilConfig.frontReadMask << ", "
1509 << "frontWriteMask = " << stencilConfig.frontWriteMask << ", "
1510 << "frontRef = " << stencilConfig.frontRef << ", "
1511 << "backReadMask = " << stencilConfig.backReadMask << ", "
1512 << "backWriteMask = " << stencilConfig.backWriteMask << ", "
1513 << "backRef = " << stencilConfig.backRef;
1514 }
1515
1516 stencilStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states"));
1517 }
1518
1519 stencilOpItr.reset();
1520
1521 for (uint32_t failOpNdx = 0u; failOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); failOpNdx++)
1522 {
1523 const std::string failOpName = std::string("fail_") + getShortName(stencilOps[failOpNdx]);
1524 de::MovePtr<tcu::TestCaseGroup> failOpTest(new tcu::TestCaseGroup(testCtx, failOpName.c_str()));
1525
1526 for (uint32_t passOpNdx = 0u; passOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); passOpNdx++)
1527 {
1528 const std::string passOpName = std::string("pass_") + getShortName(stencilOps[passOpNdx]);
1529 de::MovePtr<tcu::TestCaseGroup> passOpTest(new tcu::TestCaseGroup(testCtx, passOpName.c_str()));
1530
1531 for (uint32_t dFailOpNdx = 0u; dFailOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); dFailOpNdx++)
1532 {
1533 const std::string dFailOpName =
1534 std::string("dfail_") + getShortName(stencilOps[dFailOpNdx]);
1535 de::MovePtr<tcu::TestCaseGroup> dFailOpTest(
1536 new tcu::TestCaseGroup(testCtx, dFailOpName.c_str()));
1537
1538 for (uint32_t compareOpNdx = 0u; compareOpNdx < DE_LENGTH_OF_ARRAY(compareOps);
1539 compareOpNdx++)
1540 {
1541 // Iterate front set of stencil state in ascending order
1542 const VkStencilOpState stencilStateFront = {
1543 stencilOps[failOpNdx], // failOp
1544 stencilOps[passOpNdx], // passOp
1545 stencilOps[dFailOpNdx], // depthFailOp
1546 compareOps[compareOpNdx], // compareOp
1547 0x0, // compareMask
1548 0x0, // writeMask
1549 0x0 // reference
1550 };
1551
1552 // Iterate back set of stencil state in random order
1553 const VkStencilOpState stencilStateBack = stencilOpItr.next();
1554 const std::string caseName = compareOpNames[compareOpNdx];
1555
1556 dFailOpTest->addChild(new StencilTest(
1557 testCtx, caseName, pipelineConstructionType, stencilFormat, stencilStateFront,
1558 stencilStateBack, colorEnabled, useSeparateDepthStencilLayouts));
1559 }
1560 passOpTest->addChild(dFailOpTest.release());
1561 }
1562 failOpTest->addChild(passOpTest.release());
1563 }
1564 stencilStateTests->addChild(failOpTest.release());
1565 }
1566
1567 formatTest->addChild(stencilStateTests.release());
1568 formatTests->addChild(formatTest.release());
1569 }
1570 }
1571
1572 if (colorEnabled)
1573 stencilTests->addChild(formatTests.release());
1574 else
1575 noColorAttachmentTests->addChild(formatTests.release());
1576 }
1577
1578 stencilTests->addChild(noColorAttachmentTests.release());
1579
1580 // Tests attempting to enable the stencil test while not using a stencil attachment.
1581 const auto isNoStencilRelevantVariant =
1582 (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC ||
1583 pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_SPIRV ||
1584 pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY);
1585 if (isNoStencilRelevantVariant)
1586 {
1587 de::MovePtr<tcu::TestCaseGroup> noStencilAttGroup(new tcu::TestCaseGroup(testCtx, "no_stencil_att"));
1588
1589 const VkFormat depthComponentFormats[] = {
1590 VK_FORMAT_D16_UNORM, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT,
1591 VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT,
1592 };
1593
1594 for (const auto dynamicRendering : {false, true})
1595 {
1596 if (!dynamicRendering && isConstructionTypeShaderObject(pipelineConstructionType))
1597 continue;
1598
1599 #ifdef CTS_USES_VULKANSC
1600 if (dynamicRendering)
1601 continue;
1602 #endif
1603
1604 const char *renderingGroupName = (dynamicRendering ? "dynamic_rendering" : "render_passes");
1605 de::MovePtr<tcu::TestCaseGroup> renderingGroup(new tcu::TestCaseGroup(testCtx, renderingGroupName));
1606
1607 for (const auto dynamicEnable : {false, true})
1608 {
1609 const char *enableGroupName = (dynamicEnable ? "dynamic_enable" : "static_enable");
1610 de::MovePtr<tcu::TestCaseGroup> dynEnableGroup(new tcu::TestCaseGroup(testCtx, enableGroupName));
1611
1612 for (const auto &depthComponentFormat : depthComponentFormats)
1613 {
1614 // When using classic render passes, we cannot indicate a separate stencil format and image.
1615 const auto tcuFormat = mapVkFormat(depthComponentFormat);
1616 if (!dynamicRendering && tcu::hasStencilComponent(tcuFormat.order))
1617 continue;
1618
1619 const NoStencilAttachmentParams params{
1620 pipelineConstructionType,
1621 depthComponentFormat,
1622 dynamicRendering,
1623 dynamicEnable,
1624 };
1625 const std::string testName = getFormatCaseName(depthComponentFormat);
1626 dynEnableGroup->addChild(new NoStencilAttachmentCase(testCtx, testName, params));
1627 }
1628
1629 renderingGroup->addChild(dynEnableGroup.release());
1630 }
1631
1632 noStencilAttGroup->addChild(renderingGroup.release());
1633 }
1634
1635 stencilTests->addChild(noStencilAttGroup.release());
1636 }
1637
1638 return stencilTests.release();
1639 }
1640
1641 } // namespace pipeline
1642 } // namespace vkt
1643