1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Imagination Technologies Ltd.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Stencil Tests
23 *//*--------------------------------------------------------------------*/
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"
37 #include "vkRefUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 #include "tcuImageCompare.hpp"
43 #include "deRandom.hpp"
44 #include "deStringUtil.hpp"
45 #include "deUniquePtr.hpp"
61 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
63 VkFormatProperties formatProps;
65 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
67 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
70 class StencilOpStateUniqueRandomIterator : public UniqueRandomIterator<VkStencilOpState>
73 StencilOpStateUniqueRandomIterator (int seed);
74 virtual ~StencilOpStateUniqueRandomIterator (void) {}
75 virtual VkStencilOpState getIndexedValue (deUint32 index);
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;
85 // Total number of cross-combinations of (stencilFailOp x stencilPassOp x stencilDepthFailOp x stencilCompareOp)
86 const static deUint32 s_totalStencilOpStates;
90 class StencilTest : public vkt::TestCase
98 struct StencilStateConfig
100 deUint32 frontReadMask;
101 deUint32 frontWriteMask;
104 deUint32 backReadMask;
105 deUint32 backWriteMask;
109 const static StencilStateConfig s_stencilStateConfigs[QUAD_COUNT];
110 const static float s_quadDepths[QUAD_COUNT];
113 StencilTest (tcu::TestContext& testContext,
114 const std::string& name,
115 const std::string& description,
116 VkFormat stencilFormat,
117 const VkStencilOpState& stencilOpStateFront,
118 const VkStencilOpState& stencilOpStateBack,
119 const bool colorAttachmentEnable,
120 const bool separateDepthStencilLayouts);
121 virtual ~StencilTest (void);
122 virtual void initPrograms (SourceCollections& sourceCollections) const;
123 virtual void checkSupport (Context& context) const;
124 virtual TestInstance* createInstance (Context& context) const;
127 VkFormat m_stencilFormat;
128 const VkStencilOpState m_stencilOpStateFront;
129 const VkStencilOpState m_stencilOpStateBack;
130 const bool m_colorAttachmentEnable;
131 const bool m_separateDepthStencilLayouts;
134 class StencilTestInstance : public vkt::TestInstance
137 StencilTestInstance (Context& context,
138 VkFormat stencilFormat,
139 const VkStencilOpState& stencilOpStatesFront,
140 const VkStencilOpState& stencilOpStatesBack,
141 const bool colorAttachmentEnable,
142 const bool separateDepthStencilLayouts);
143 virtual ~StencilTestInstance (void);
144 virtual tcu::TestStatus iterate (void);
147 tcu::TestStatus verifyImage (void);
149 VkStencilOpState m_stencilOpStateFront;
150 VkStencilOpState m_stencilOpStateBack;
151 const bool m_colorAttachmentEnable;
152 const bool m_separateDepthStencilLayouts;
153 const tcu::UVec2 m_renderSize;
154 const VkFormat m_colorFormat;
155 const VkFormat m_stencilFormat;
156 VkImageSubresourceRange m_stencilImageSubresourceRange;
158 VkImageCreateInfo m_colorImageCreateInfo;
159 Move<VkImage> m_colorImage;
160 de::MovePtr<Allocation> m_colorImageAlloc;
161 Move<VkImage> m_stencilImage;
162 de::MovePtr<Allocation> m_stencilImageAlloc;
163 Move<VkImageView> m_colorAttachmentView;
164 Move<VkImageView> m_stencilAttachmentView;
165 Move<VkRenderPass> m_renderPass;
166 Move<VkFramebuffer> m_framebuffer;
168 Move<VkShaderModule> m_vertexShaderModule;
169 Move<VkShaderModule> m_fragmentShaderModule;
171 Move<VkBuffer> m_vertexBuffer;
172 std::vector<Vertex4RGBA> m_vertices;
173 de::MovePtr<Allocation> m_vertexBufferAlloc;
175 Move<VkPipelineLayout> m_pipelineLayout;
176 Move<VkPipeline> m_graphicsPipelines[StencilTest::QUAD_COUNT];
178 Move<VkCommandPool> m_cmdPool;
179 Move<VkCommandBuffer> m_cmdBuffer;
182 const VkStencilOp stencilOps[] =
186 VK_STENCIL_OP_REPLACE,
187 VK_STENCIL_OP_INCREMENT_AND_CLAMP,
188 VK_STENCIL_OP_DECREMENT_AND_CLAMP,
189 VK_STENCIL_OP_INVERT,
190 VK_STENCIL_OP_INCREMENT_AND_WRAP,
191 VK_STENCIL_OP_DECREMENT_AND_WRAP
194 const VkCompareOp compareOps[] =
199 VK_COMPARE_OP_LESS_OR_EQUAL,
200 VK_COMPARE_OP_GREATER,
201 VK_COMPARE_OP_NOT_EQUAL,
202 VK_COMPARE_OP_GREATER_OR_EQUAL,
206 // StencilOpStateUniqueRandomIterator
208 const deUint32 StencilOpStateUniqueRandomIterator::s_stencilOpsLength = DE_LENGTH_OF_ARRAY(stencilOps);
209 const deUint32 StencilOpStateUniqueRandomIterator::s_stencilOpsLength2 = s_stencilOpsLength * s_stencilOpsLength;
210 const deUint32 StencilOpStateUniqueRandomIterator::s_stencilOpsLength3 = s_stencilOpsLength2 * s_stencilOpsLength;
211 const deUint32 StencilOpStateUniqueRandomIterator::s_compareOpsLength = DE_LENGTH_OF_ARRAY(compareOps);
212 const deUint32 StencilOpStateUniqueRandomIterator::s_totalStencilOpStates = s_stencilOpsLength3 * s_compareOpsLength;
214 StencilOpStateUniqueRandomIterator::StencilOpStateUniqueRandomIterator (int seed)
215 : UniqueRandomIterator<VkStencilOpState>(s_totalStencilOpStates, s_totalStencilOpStates, seed)
219 VkStencilOpState StencilOpStateUniqueRandomIterator::getIndexedValue (deUint32 index)
221 const deUint32 stencilCompareOpIndex = index / s_stencilOpsLength3;
222 const deUint32 stencilCompareOpSeqIndex = stencilCompareOpIndex * s_stencilOpsLength3;
224 const deUint32 stencilDepthFailOpIndex = (index - stencilCompareOpSeqIndex) / s_stencilOpsLength2;
225 const deUint32 stencilDepthFailOpSeqIndex = stencilDepthFailOpIndex * s_stencilOpsLength2;
227 const deUint32 stencilPassOpIndex = (index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex) / s_stencilOpsLength;
228 const deUint32 stencilPassOpSeqIndex = stencilPassOpIndex * s_stencilOpsLength;
230 const deUint32 stencilFailOpIndex = index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex - stencilPassOpSeqIndex;
232 const VkStencilOpState stencilOpState =
234 stencilOps[stencilFailOpIndex], // VkStencilOp failOp;
235 stencilOps[stencilPassOpIndex], // VkStencilOp passOp;
236 stencilOps[stencilDepthFailOpIndex], // VkStencilOp depthFailOp;
237 compareOps[stencilCompareOpIndex], // VkCompareOp compareOp;
238 0x0, // deUint32 compareMask;
239 0x0, // deUint32 writeMask;
240 0x0 // deUint32 reference;
243 return stencilOpState;
249 const StencilTest::StencilStateConfig StencilTest::s_stencilStateConfigs[QUAD_COUNT] =
251 // frontReadMask frontWriteMask frontRef backReadMask backWriteMask backRef
252 { 0xFF, 0xFF, 0xAB, 0xF0, 0xFF, 0xFF },
253 { 0xFF, 0xF0, 0xCD, 0xF0, 0xF0, 0xEF },
254 { 0xF0, 0x0F, 0xEF, 0xFF, 0x0F, 0xCD },
255 { 0xF0, 0x01, 0xFF, 0xFF, 0x01, 0xAB }
258 const float StencilTest::s_quadDepths[QUAD_COUNT] =
266 StencilTest::StencilTest (tcu::TestContext& testContext,
267 const std::string& name,
268 const std::string& description,
269 VkFormat stencilFormat,
270 const VkStencilOpState& stencilOpStateFront,
271 const VkStencilOpState& stencilOpStateBack,
272 const bool colorAttachmentEnable,
273 const bool separateDepthStencilLayouts)
274 : vkt::TestCase (testContext, name, description)
275 , m_stencilFormat (stencilFormat)
276 , m_stencilOpStateFront (stencilOpStateFront)
277 , m_stencilOpStateBack (stencilOpStateBack)
278 , m_colorAttachmentEnable (colorAttachmentEnable)
279 , m_separateDepthStencilLayouts (separateDepthStencilLayouts)
283 StencilTest::~StencilTest (void)
287 void StencilTest::checkSupport (Context& context) const
289 if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_stencilFormat))
290 throw tcu::NotSupportedError(std::string("Unsupported depth/stencil format: ") + getFormatName(m_stencilFormat));
292 if (m_separateDepthStencilLayouts && !isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_separate_depth_stencil_layouts"))
293 TCU_THROW(NotSupportedError, "VK_KHR_separate_depth_stencil_layouts is not supported");
296 TestInstance* StencilTest::createInstance (Context& context) const
298 return new StencilTestInstance(context, m_stencilFormat, m_stencilOpStateFront, m_stencilOpStateBack, m_colorAttachmentEnable, m_separateDepthStencilLayouts);
301 void StencilTest::initPrograms (SourceCollections& sourceCollections) const
303 if (m_colorAttachmentEnable)
305 sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
307 "layout(location = 0) in vec4 position;\n"
308 "layout(location = 1) in vec4 color;\n"
309 "layout(location = 0) out highp vec4 vtxColor;\n"
312 " gl_Position = position;\n"
313 " vtxColor = color;\n"
316 sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(
318 "layout(location = 0) in highp vec4 vtxColor;\n"
319 "layout(location = 0) out highp vec4 fragColor;\n"
322 " fragColor = vtxColor;\n"
327 sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
329 "layout(location = 0) in vec4 position;\n"
330 "layout(location = 1) in vec4 color;\n"
333 " gl_Position = position;\n"
336 sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(
345 // StencilTestInstance
347 StencilTestInstance::StencilTestInstance (Context& context,
348 VkFormat stencilFormat,
349 const VkStencilOpState& stencilOpStateFront,
350 const VkStencilOpState& stencilOpStateBack,
351 const bool colorAttachmentEnable,
352 const bool separateDepthStencilLayouts)
353 : vkt::TestInstance (context)
354 , m_stencilOpStateFront (stencilOpStateFront)
355 , m_stencilOpStateBack (stencilOpStateBack)
356 , m_colorAttachmentEnable (colorAttachmentEnable)
357 , m_separateDepthStencilLayouts (separateDepthStencilLayouts)
358 , m_renderSize (32, 32)
359 , m_colorFormat (colorAttachmentEnable ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED)
360 , m_stencilFormat (stencilFormat)
362 const DeviceInterface& vk = context.getDeviceInterface();
363 const VkDevice vkDevice = context.getDevice();
364 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
365 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
366 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
368 // Create color image
369 if (m_colorAttachmentEnable)
371 const VkImageCreateInfo colorImageParams =
373 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
374 DE_NULL, // const void* pNext;
375 0u, // VkImageCreateFlags flags;
376 VK_IMAGE_TYPE_2D, // VkImageType imageType;
377 m_colorFormat, // VkFormat format;
378 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
379 1u, // deUint32 mipLevels;
380 1u, // deUint32 arrayLayers;
381 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
382 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
383 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
384 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
385 1u, // deUint32 queueFamilyIndexCount;
386 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
387 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
390 m_colorImageCreateInfo = colorImageParams;
391 m_colorImage = createImage(vk, vkDevice, &m_colorImageCreateInfo);
393 // Allocate and bind color image memory
394 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
395 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
398 // Create stencil image
400 const VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
402 const VkImageCreateInfo stencilImageParams =
404 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
405 DE_NULL, // const void* pNext;
406 0u, // VkImageCreateFlags flags;
407 VK_IMAGE_TYPE_2D, // VkImageType imageType;
408 m_stencilFormat, // VkFormat format;
409 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
410 1u, // deUint32 mipLevels;
411 1u, // deUint32 arrayLayers;
412 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
413 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
414 usageFlags, // VkImageUsageFlags usage;
415 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
416 1u, // deUint32 queueFamilyIndexCount;
417 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
418 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
421 m_stencilImage = createImage(vk, vkDevice, &stencilImageParams);
423 // Allocate and bind stencil image memory
424 m_stencilImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_stencilImage), MemoryRequirement::Any);
425 VK_CHECK(vk.bindImageMemory(vkDevice, *m_stencilImage, m_stencilImageAlloc->getMemory(), m_stencilImageAlloc->getOffset()));
427 const VkImageAspectFlags aspect = (mapVkFormat(m_stencilFormat).order == tcu::TextureFormat::DS ? VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT
428 : VK_IMAGE_ASPECT_STENCIL_BIT);
429 m_stencilImageSubresourceRange = makeImageSubresourceRange(aspect, 0u, stencilImageParams.mipLevels, 0u, stencilImageParams.arrayLayers);
432 // Create color attachment view
433 if (m_colorAttachmentEnable)
435 const VkImageViewCreateInfo colorAttachmentViewParams =
437 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
438 DE_NULL, // const void* pNext;
439 0u, // VkImageViewCreateFlags flags;
440 *m_colorImage, // VkImage image;
441 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
442 m_colorFormat, // VkFormat format;
443 componentMappingRGBA, // VkComponentMapping components;
444 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
447 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
450 // Create stencil attachment view
452 const VkImageViewCreateInfo stencilAttachmentViewParams =
454 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
455 DE_NULL, // const void* pNext;
456 0u, // VkImageViewCreateFlags flags;
457 *m_stencilImage, // VkImage image;
458 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
459 m_stencilFormat, // VkFormat format;
460 componentMappingRGBA, // VkComponentMapping components;
461 m_stencilImageSubresourceRange, // VkImageSubresourceRange subresourceRange;
464 m_stencilAttachmentView = createImageView(vk, vkDevice, &stencilAttachmentViewParams);
467 // Create render pass
468 m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat, m_stencilFormat);
470 // Create framebuffer
472 std::vector<VkImageView> attachmentBindInfos;
474 if (m_colorAttachmentEnable)
475 attachmentBindInfos.push_back(*m_colorAttachmentView);
477 attachmentBindInfos.push_back(*m_stencilAttachmentView);
479 const VkFramebufferCreateInfo framebufferParams =
481 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
482 DE_NULL, // const void* pNext;
483 0u, // VkFramebufferCreateFlags flags;
484 *m_renderPass, // VkRenderPass renderPass;
485 (deUint32)attachmentBindInfos.size(), // deUint32 attachmentCount;
486 attachmentBindInfos.data(), // const VkImageView* pAttachments;
487 (deUint32)m_renderSize.x(), // deUint32 width;
488 (deUint32)m_renderSize.y(), // deUint32 height;
489 1u // deUint32 layers;
492 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
495 // Create pipeline layout
497 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
499 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
500 DE_NULL, // const void* pNext;
501 0u, // VkPipelineLayoutCreateFlags flags;
502 0u, // deUint32 setLayoutCount;
503 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
504 0u, // deUint32 pushConstantRangeCount;
505 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
508 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
511 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
512 m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
516 const VkVertexInputBindingDescription vertexInputBindingDescription =
518 0u, // deUint32 binding;
519 sizeof(Vertex4RGBA), // deUint32 strideInBytes;
520 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
523 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
526 0u, // deUint32 location;
527 0u, // deUint32 binding;
528 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
529 0u // deUint32 offsetInBytes;
532 1u, // deUint32 location;
533 0u, // deUint32 binding;
534 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
535 DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offsetInBytes;
539 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
541 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
542 DE_NULL, // const void* pNext;
543 0u, // VkPipelineVertexInputStateCreateFlags flags;
544 1u, // deUint32 vertexBindingDescriptionCount;
545 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
546 2u, // deUint32 vertexAttributeDescriptionCount;
547 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
550 const std::vector<VkViewport> viewports (1, makeViewport(m_renderSize));
551 const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize));
553 const bool isDepthEnabled = (vk::mapVkFormat(m_stencilFormat).order != tcu::TextureFormat::S);
555 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
557 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
558 DE_NULL, // const void* pNext;
559 0u, // VkPipelineDepthStencilStateCreateFlags flags;
560 isDepthEnabled, // VkBool32 depthTestEnable;
561 isDepthEnabled, // VkBool32 depthWriteEnable;
562 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
563 false, // VkBool32 depthBoundsTestEnable;
564 true, // VkBool32 stencilTestEnable;
565 m_stencilOpStateFront, // VkStencilOpState front;
566 m_stencilOpStateBack, // VkStencilOpState back;
567 0.0f, // float minDepthBounds;
568 1.0f // float maxDepthBounds;
571 // Setup different stencil masks and refs in each quad
572 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
574 const StencilTest::StencilStateConfig& config = StencilTest::s_stencilStateConfigs[quadNdx];
575 VkStencilOpState& front = depthStencilStateParams.front;
576 VkStencilOpState& back = depthStencilStateParams.back;
578 front.compareMask = config.frontReadMask;
579 front.writeMask = config.frontWriteMask;
580 front.reference = config.frontRef;
582 back.compareMask = config.backReadMask;
583 back.writeMask = config.backWriteMask;
584 back.reference = config.backRef;
586 m_graphicsPipelines[quadNdx] = makeGraphicsPipeline(vk, // const DeviceInterface& vk
587 vkDevice, // const VkDevice device
588 *m_pipelineLayout, // const VkPipelineLayout pipelineLayout
589 *m_vertexShaderModule, // const VkShaderModule vertexShaderModule
590 DE_NULL, // const VkShaderModule tessellationControlModule
591 DE_NULL, // const VkShaderModule tessellationEvalModule
592 DE_NULL, // const VkShaderModule geometryShaderModule
593 *m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule
594 *m_renderPass, // const VkRenderPass renderPass
595 viewports, // const std::vector<VkViewport>& viewports
596 scissors, // const std::vector<VkRect2D>& scissors
597 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
598 0u, // const deUint32 subpass
599 0u, // const deUint32 patchControlPoints
600 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
601 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
602 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
603 &depthStencilStateParams); // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
608 // Create vertex buffer
610 const VkBufferCreateInfo vertexBufferParams =
612 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
613 DE_NULL, // const void* pNext;
614 0u, // VkBufferCreateFlags flags;
615 1024u, // VkDeviceSize size;
616 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
617 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
618 1u, // deUint32 queueFamilyIndexCount;
619 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
622 m_vertices = createOverlappingQuads();
623 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
624 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
626 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
629 for (int quadNdx = 0; quadNdx < 4; quadNdx++)
630 for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
631 m_vertices[quadNdx * 6 + vertexNdx].position.z() = StencilTest::s_quadDepths[quadNdx];
633 // Load vertices into vertex buffer
634 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
635 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
638 // Create command pool
639 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
641 // Create command buffer
643 const VkImageMemoryBarrier colorImageBarrier =
645 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
646 DE_NULL, // const void* pNext;
647 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
648 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
649 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
650 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
651 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
652 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
653 *m_colorImage, // VkImage image;
654 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
657 VkImageSubresourceRange stencilImageBarrierSubresourceRange = m_stencilImageSubresourceRange;
658 VkImageLayout newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
659 if (m_separateDepthStencilLayouts)
661 stencilImageBarrierSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
662 newLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
665 const VkImageMemoryBarrier stencilImageBarrier =
667 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
668 DE_NULL, // const void* pNext;
669 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
670 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
671 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
672 newLayout, // VkImageLayout newLayout;
673 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
674 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
675 *m_stencilImage, // VkImage image;
676 stencilImageBarrierSubresourceRange, // VkImageSubresourceRange subresourceRange;
679 std::vector<VkClearValue> attachmentClearValues;
680 std::vector<VkImageMemoryBarrier> imageLayoutBarriers;
682 if (m_colorAttachmentEnable)
684 attachmentClearValues.push_back(defaultClearValue(m_colorFormat));
685 imageLayoutBarriers.push_back(colorImageBarrier);
688 attachmentClearValues.push_back(defaultClearValue(m_stencilFormat));
689 imageLayoutBarriers.push_back(stencilImageBarrier);
691 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
693 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
695 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,
696 0u, DE_NULL, 0u, DE_NULL, (deUint32)imageLayoutBarriers.size(), imageLayoutBarriers.data());
698 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), (deUint32)attachmentClearValues.size(), attachmentClearValues.data());
700 const VkDeviceSize quadOffset = (m_vertices.size() / StencilTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
702 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
704 VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
706 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]);
707 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
708 vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / StencilTest::QUAD_COUNT), 1, 0, 0);
711 endRenderPass(vk, *m_cmdBuffer);
712 endCommandBuffer(vk, *m_cmdBuffer);
716 StencilTestInstance::~StencilTestInstance (void)
720 tcu::TestStatus StencilTestInstance::iterate (void)
722 const DeviceInterface& vk = m_context.getDeviceInterface();
723 const VkDevice vkDevice = m_context.getDevice();
724 const VkQueue queue = m_context.getUniversalQueue();
726 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
728 return verifyImage();
731 tcu::TestStatus StencilTestInstance::verifyImage (void)
733 const tcu::TextureFormat tcuColorFormat = mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
734 const tcu::TextureFormat tcuStencilFormat = mapVkFormat(m_stencilFormat);
735 const ColorVertexShader vertexShader;
736 const ColorFragmentShader fragmentShader (tcuColorFormat, tcuStencilFormat);
737 const rr::Program program (&vertexShader, &fragmentShader);
738 ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
739 bool colorCompareOk = false;
740 bool stencilCompareOk = false;
742 // Render reference image
745 rr::RenderState renderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
747 renderState.fragOps.depthTestEnabled = true;
748 renderState.fragOps.depthFunc = mapVkCompareOp(VK_COMPARE_OP_LESS);
749 renderState.fragOps.stencilTestEnabled = true;
751 rr::StencilState& refStencilFront = renderState.fragOps.stencilStates[rr::FACETYPE_FRONT];
752 rr::StencilState& refStencilBack = renderState.fragOps.stencilStates[rr::FACETYPE_BACK];
754 refStencilFront.sFail = mapVkStencilOp(m_stencilOpStateFront.failOp);
755 refStencilFront.dpFail = mapVkStencilOp(m_stencilOpStateFront.depthFailOp);
756 refStencilFront.dpPass = mapVkStencilOp(m_stencilOpStateFront.passOp);
757 refStencilFront.func = mapVkCompareOp(m_stencilOpStateFront.compareOp);
759 refStencilBack.sFail = mapVkStencilOp(m_stencilOpStateBack.failOp);
760 refStencilBack.dpPass = mapVkStencilOp(m_stencilOpStateBack.passOp);
761 refStencilBack.dpFail = mapVkStencilOp(m_stencilOpStateBack.depthFailOp);
762 refStencilBack.func = mapVkCompareOp(m_stencilOpStateBack.compareOp);
764 // Reverse winding of vertices, as Vulkan screen coordinates start at upper left
765 std::vector<Vertex4RGBA> cwVertices(m_vertices);
766 for (size_t vertexNdx = 0; vertexNdx < cwVertices.size() - 2; vertexNdx += 3)
768 const Vertex4RGBA cwVertex1 = cwVertices[vertexNdx + 1];
770 cwVertices[vertexNdx + 1] = cwVertices[vertexNdx + 2];
771 cwVertices[vertexNdx + 2] = cwVertex1;
774 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
776 refStencilFront.ref = (int)StencilTest::s_stencilStateConfigs[quadNdx].frontRef;
777 refStencilFront.compMask = StencilTest::s_stencilStateConfigs[quadNdx].frontReadMask;
778 refStencilFront.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].frontWriteMask;
780 refStencilBack.ref = (int)StencilTest::s_stencilStateConfigs[quadNdx].backRef;
781 refStencilBack.compMask = StencilTest::s_stencilStateConfigs[quadNdx].backReadMask;
782 refStencilBack.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].backWriteMask;
784 refRenderer.draw(renderState,
785 rr::PRIMITIVETYPE_TRIANGLES,
786 std::vector<Vertex4RGBA>(cwVertices.begin() + quadNdx * 6,
787 cwVertices.begin() + (quadNdx + 1) * 6));
791 // Compare result with reference image
792 if (m_colorAttachmentEnable)
794 const DeviceInterface& vk = m_context.getDeviceInterface();
795 const VkDevice vkDevice = m_context.getDevice();
796 const VkQueue queue = m_context.getUniversalQueue();
797 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
798 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
799 de::UniquePtr<tcu::TextureLevel> result (readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
801 colorCompareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
804 refRenderer.getAccess(),
806 tcu::UVec4(2, 2, 2, 2),
809 tcu::COMPARE_LOG_RESULT);
813 colorCompareOk = true;
816 // Compare stencil result with reference image
818 const DeviceInterface& vk = m_context.getDeviceInterface();
819 const VkDevice vkDevice = m_context.getDevice();
820 const VkQueue queue = m_context.getUniversalQueue();
821 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
822 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
823 de::UniquePtr<tcu::TextureLevel> result (readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_stencilImage, m_stencilFormat, m_renderSize).release());
826 const tcu::PixelBufferAccess stencilAccess (tcu::getEffectiveDepthStencilAccess(refRenderer.getDepthStencilAccess(), tcu::Sampler::MODE_STENCIL));
827 stencilCompareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
828 "StencilImageCompare",
829 "Stencil image comparison",
832 tcu::UVec4(2, 2, 2, 2),
835 tcu::COMPARE_LOG_RESULT);
839 if (colorCompareOk && stencilCompareOk)
840 return tcu::TestStatus::pass("Result image matches reference");
842 return tcu::TestStatus::fail("Image mismatch");
846 // Utilities for test names
848 const char* getShortName (VkStencilOp stencilOp)
852 case VK_STENCIL_OP_KEEP: return "keep";
853 case VK_STENCIL_OP_ZERO: return "zero";
854 case VK_STENCIL_OP_REPLACE: return "repl";
855 case VK_STENCIL_OP_INCREMENT_AND_CLAMP: return "incc";
856 case VK_STENCIL_OP_DECREMENT_AND_CLAMP: return "decc";
857 case VK_STENCIL_OP_INVERT: return "inv";
858 case VK_STENCIL_OP_INCREMENT_AND_WRAP: return "wrap";
859 case VK_STENCIL_OP_DECREMENT_AND_WRAP: return "decw";
862 DE_FATAL("Invalid VkStencilOpState value");
867 std::string getStencilStateSetDescription(const VkStencilOpState& stencilOpStateFront,
868 const VkStencilOpState& stencilOpStateBack)
870 std::ostringstream desc;
872 desc << "\nFront faces:\n" << stencilOpStateFront;
873 desc << "Back faces:\n" << stencilOpStateBack;
878 std::string getFormatCaseName (VkFormat format)
880 const std::string fullName = getFormatName(format);
882 DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
884 return de::toLower(fullName.substr(10));
889 tcu::TestCaseGroup* createStencilTests (tcu::TestContext& testCtx)
891 const VkFormat stencilFormats[] =
894 VK_FORMAT_D16_UNORM_S8_UINT,
895 VK_FORMAT_D24_UNORM_S8_UINT,
896 VK_FORMAT_D32_SFLOAT_S8_UINT
899 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(compareOps) == 8);
900 DE_STATIC_ASSERT(vk::VK_COMPARE_OP_LAST == 8);
902 static const char* compareOpNames[8] =
907 "comp_less_or_equal",
910 "comp_greater_or_equal",
914 de::MovePtr<tcu::TestCaseGroup> stencilTests (new tcu::TestCaseGroup(testCtx, "stencil", "Stencil tests"));
915 de::MovePtr<tcu::TestCaseGroup> noColorAttachmentTests (new tcu::TestCaseGroup(testCtx, "nocolor", "Stencil tests with no color attachment"));
916 const bool colorAttachmentEnabled[] = { true, false };
918 for (deUint32 colorAttachmentEnabledIdx = 0; colorAttachmentEnabledIdx < DE_LENGTH_OF_ARRAY(colorAttachmentEnabled); colorAttachmentEnabledIdx++)
920 const bool colorEnabled = colorAttachmentEnabled[colorAttachmentEnabledIdx];
921 de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Uses different stencil formats"));
922 StencilOpStateUniqueRandomIterator stencilOpItr (123);
924 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(stencilFormats); formatNdx++)
926 const VkFormat stencilFormat = stencilFormats[formatNdx];
927 const bool hasDepth = tcu::hasDepthComponent(mapVkFormat(stencilFormat).order);
928 const bool hasStencil = tcu::hasStencilComponent(mapVkFormat(stencilFormat).order);
929 const int separateLayoutsLoopCount = (hasDepth && hasStencil) ? 2 : 1;
931 for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount; ++separateDepthStencilLayouts)
933 const bool useSeparateDepthStencilLayouts = bool(separateDepthStencilLayouts);
935 de::MovePtr<tcu::TestCaseGroup> formatTest (new tcu::TestCaseGroup(testCtx,
936 (getFormatCaseName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : "")).c_str(),
937 (std::string("Uses format ") + getFormatName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? " with separate depth/stencil layouts" : "")).c_str()));
939 de::MovePtr<tcu::TestCaseGroup> stencilStateTests;
941 std::ostringstream desc;
942 desc << "Draws 4 quads with the following depths and dynamic stencil states: ";
944 for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
946 const StencilTest::StencilStateConfig& stencilConfig = StencilTest::s_stencilStateConfigs[quadNdx];
948 desc << "(" << quadNdx << ") "
949 << "z = " << StencilTest::s_quadDepths[quadNdx] << ", "
950 << "frontReadMask = " << stencilConfig.frontReadMask << ", "
951 << "frontWriteMask = " << stencilConfig.frontWriteMask << ", "
952 << "frontRef = " << stencilConfig.frontRef << ", "
953 << "backReadMask = " << stencilConfig.backReadMask << ", "
954 << "backWriteMask = " << stencilConfig.backWriteMask << ", "
955 << "backRef = " << stencilConfig.backRef;
958 stencilStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", desc.str().c_str()));
961 stencilOpItr.reset();
963 for (deUint32 failOpNdx = 0u; failOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); failOpNdx++)
965 const std::string failOpName = std::string("fail_") + getShortName(stencilOps[failOpNdx]);
966 de::MovePtr<tcu::TestCaseGroup> failOpTest (new tcu::TestCaseGroup(testCtx, failOpName.c_str(), ""));
968 for (deUint32 passOpNdx = 0u; passOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); passOpNdx++)
970 const std::string passOpName = std::string("pass_") + getShortName(stencilOps[passOpNdx]);
971 de::MovePtr<tcu::TestCaseGroup> passOpTest (new tcu::TestCaseGroup(testCtx, passOpName.c_str(), ""));
973 for (deUint32 dFailOpNdx = 0u; dFailOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); dFailOpNdx++)
975 const std::string dFailOpName = std::string("dfail_") + getShortName(stencilOps[dFailOpNdx]);
976 de::MovePtr<tcu::TestCaseGroup> dFailOpTest (new tcu::TestCaseGroup(testCtx, dFailOpName.c_str(), ""));
978 for (deUint32 compareOpNdx = 0u; compareOpNdx < DE_LENGTH_OF_ARRAY(compareOps); compareOpNdx++)
980 // Iterate front set of stencil state in ascending order
981 const VkStencilOpState stencilStateFront =
983 stencilOps[failOpNdx], // failOp
984 stencilOps[passOpNdx], // passOp
985 stencilOps[dFailOpNdx], // depthFailOp
986 compareOps[compareOpNdx], // compareOp
992 // Iterate back set of stencil state in random order
993 const VkStencilOpState stencilStateBack = stencilOpItr.next();
994 const std::string caseName = compareOpNames[compareOpNdx];
995 const std::string caseDesc = getStencilStateSetDescription(stencilStateFront, stencilStateBack);
997 dFailOpTest->addChild(new StencilTest(testCtx, caseName, caseDesc, stencilFormat, stencilStateFront, stencilStateBack, colorEnabled, useSeparateDepthStencilLayouts));
999 passOpTest->addChild(dFailOpTest.release());
1001 failOpTest->addChild(passOpTest.release());
1003 stencilStateTests->addChild(failOpTest.release());
1006 formatTest->addChild(stencilStateTests.release());
1007 formatTests->addChild(formatTest.release());
1012 stencilTests->addChild(formatTests.release());
1014 noColorAttachmentTests->addChild(formatTests.release());
1017 stencilTests->addChild(noColorAttachmentTests.release());
1019 return stencilTests.release();