1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 * Copyright (c) 2015 The Khronos Group Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Early fragment tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktFragmentOperationsEarlyFragmentTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27
28 #include "vkDefs.hpp"
29 #include "vkRef.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkStrUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkBarrierUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42
43 #include "tcuTestLog.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuTextureUtil.hpp"
46
47 #include "deUniquePtr.hpp"
48 #include "deStringUtil.hpp"
49 #include "deMath.h"
50
51 #include <string>
52
53 namespace vkt
54 {
55 namespace FragmentOperations
56 {
57 namespace
58 {
59 using namespace vk;
60 using de::UniquePtr;
61
62 //! Basic 2D image.
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)63 inline VkImageCreateInfo makeImageCreateInfo(const tcu::IVec2 &size, const VkFormat format,
64 const VkImageUsageFlags usage)
65 {
66 const VkImageCreateInfo imageParams = {
67 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
68 DE_NULL, // const void* pNext;
69 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
70 VK_IMAGE_TYPE_2D, // VkImageType imageType;
71 format, // VkFormat format;
72 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
73 1u, // uint32_t mipLevels;
74 1u, // uint32_t arrayLayers;
75 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
76 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
77 usage, // VkImageUsageFlags usage;
78 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
79 0u, // uint32_t queueFamilyIndexCount;
80 DE_NULL, // const uint32_t* pQueueFamilyIndices;
81 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
82 };
83 return imageParams;
84 }
85
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const bool useDepthStencilAttachment,const VkFormat depthStencilFormat)86 Move<VkRenderPass> makeRenderPass(const DeviceInterface &vk, const VkDevice device, const VkFormat colorFormat,
87 const bool useDepthStencilAttachment, const VkFormat depthStencilFormat)
88 {
89 return makeRenderPass(vk, device, colorFormat,
90 useDepthStencilAttachment ? depthStencilFormat : VK_FORMAT_UNDEFINED);
91 }
92
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & renderSize,const bool enableDepthTest,const bool enableStencilTest,const VkStencilOp stencilFailOp=VK_STENCIL_OP_KEEP,const VkStencilOp stencilPassOp=VK_STENCIL_OP_KEEP)93 Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface &vk, const VkDevice device,
94 const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass,
95 const VkShaderModule vertexModule, const VkShaderModule fragmentModule,
96 const tcu::IVec2 &renderSize, const bool enableDepthTest,
97 const bool enableStencilTest,
98 const VkStencilOp stencilFailOp = VK_STENCIL_OP_KEEP,
99 const VkStencilOp stencilPassOp = VK_STENCIL_OP_KEEP)
100 {
101 const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
102 const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
103
104 const VkStencilOpState stencilOpState = makeStencilOpState(stencilFailOp, // stencil fail
105 stencilPassOp, // depth & stencil pass
106 VK_STENCIL_OP_KEEP, // depth only fail
107 VK_COMPARE_OP_EQUAL, // compare op
108 0x3, // compare mask
109 0xf, // write mask
110 1u); // reference
111
112 VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
113 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
114 DE_NULL, // const void* pNext
115 0u, // VkPipelineDepthStencilStateCreateFlags flags
116 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthTestEnable
117 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthWriteEnable
118 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp
119 VK_FALSE, // VkBool32 depthBoundsTestEnable
120 enableStencilTest ? VK_TRUE : VK_FALSE, // VkBool32 stencilTestEnable
121 stencilOpState, // VkStencilOpState front
122 stencilOpState, // VkStencilOpState back
123 0.0f, // float minDepthBounds
124 1.0f // float maxDepthBounds
125 };
126
127 return vk::makeGraphicsPipeline(
128 vk, // const DeviceInterface& vk
129 device, // const VkDevice device
130 pipelineLayout, // const VkPipelineLayout pipelineLayout
131 vertexModule, // const VkShaderModule vertexShaderModule
132 DE_NULL, // const VkShaderModule tessellationControlModule
133 DE_NULL, // const VkShaderModule tessellationEvalModule
134 DE_NULL, // const VkShaderModule geometryShaderModule
135 fragmentModule, // const VkShaderModule fragmentShaderModule
136 renderPass, // const VkRenderPass renderPass
137 viewports, // const std::vector<VkViewport>& viewports
138 scissors, // const std::vector<VkRect2D>& scissors
139 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
140 0u, // const uint32_t subpass
141 0u, // const uint32_t patchControlPoints
142 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
143 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
144 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
145 &depthStencilStateCreateInfo); // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
146 }
147
commandClearStencilAttachment(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkOffset2D & offset,const VkExtent2D & extent,const uint32_t clearValue)148 void commandClearStencilAttachment(const DeviceInterface &vk, const VkCommandBuffer commandBuffer,
149 const VkOffset2D &offset, const VkExtent2D &extent, const uint32_t clearValue)
150 {
151 const VkClearAttachment stencilAttachment = {
152 VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask;
153 0u, // uint32_t colorAttachment;
154 makeClearValueDepthStencil(0.0f, clearValue), // VkClearValue clearValue;
155 };
156
157 const VkClearRect rect = {
158 {offset, extent}, // VkRect2D rect;
159 0u, // uint32_t baseArrayLayer;
160 1u, // uint32_t layerCount;
161 };
162
163 vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
164 }
165
getImageAspectFlags(const VkFormat format)166 VkImageAspectFlags getImageAspectFlags(const VkFormat format)
167 {
168 const tcu::TextureFormat tcuFormat = mapVkFormat(format);
169
170 if (tcuFormat.order == tcu::TextureFormat::DS)
171 return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
172 else if (tcuFormat.order == tcu::TextureFormat::D)
173 return VK_IMAGE_ASPECT_DEPTH_BIT;
174 else if (tcuFormat.order == tcu::TextureFormat::S)
175 return VK_IMAGE_ASPECT_STENCIL_BIT;
176
177 DE_ASSERT(false);
178 return 0u;
179 }
180
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const VkFormat format)181 bool isSupportedDepthStencilFormat(const InstanceInterface &instanceInterface, const VkPhysicalDevice device,
182 const VkFormat format)
183 {
184 VkFormatProperties formatProps;
185 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
186 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
187 }
188
pickSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const uint32_t numFormats,const VkFormat * pFormats)189 VkFormat pickSupportedDepthStencilFormat(const InstanceInterface &instanceInterface, const VkPhysicalDevice device,
190 const uint32_t numFormats, const VkFormat *pFormats)
191 {
192 for (uint32_t i = 0; i < numFormats; ++i)
193 if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
194 return pFormats[i];
195 return VK_FORMAT_UNDEFINED;
196 }
197
198 enum Flags
199 {
200 FLAG_TEST_DEPTH = 1u << 0,
201 FLAG_TEST_STENCIL = 1u << 1,
202 FLAG_DONT_USE_TEST_ATTACHMENT = 1u << 2,
203 FLAG_DONT_USE_EARLY_FRAGMENT_TESTS = 1u << 3,
204 FLAG_EARLY_AND_LATE_FRAGMENT_TESTS = 1u << 4,
205 };
206
207 class EarlyFragmentTest : public TestCase
208 {
209 public:
210 EarlyFragmentTest(tcu::TestContext &testCtx, const std::string name, const uint32_t flags);
211
212 void initPrograms(SourceCollections &programCollection) const;
213 TestInstance *createInstance(Context &context) const;
214 virtual void checkSupport(Context &context) const;
215
216 private:
217 const uint32_t m_flags;
218 };
219
EarlyFragmentTest(tcu::TestContext & testCtx,const std::string name,const uint32_t flags)220 EarlyFragmentTest::EarlyFragmentTest(tcu::TestContext &testCtx, const std::string name, const uint32_t flags)
221 : TestCase(testCtx, name)
222 , m_flags(flags)
223 {
224 }
225
initPrograms(SourceCollections & programCollection) const226 void EarlyFragmentTest::initPrograms(SourceCollections &programCollection) const
227 {
228 // Vertex
229 {
230 std::ostringstream src;
231 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
232 << "\n"
233 << "layout(location = 0) in highp vec4 position;\n"
234 << "\n"
235 << "out gl_PerVertex {\n"
236 << " vec4 gl_Position;\n"
237 << "};\n"
238 << "\n"
239 << "void main (void)\n"
240 << "{\n"
241 << " gl_Position = position;\n"
242 << "}\n";
243
244 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
245 }
246
247 // Fragment
248 if ((m_flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == 0)
249 {
250 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
251 std::ostringstream src;
252 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
253 << "\n"
254 << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
255 << "layout(location = 0) out highp vec4 fragColor;\n"
256 << "\n"
257 << "layout(binding = 0) coherent buffer Output {\n"
258 << " uint result;\n"
259 << "} sb_out;\n"
260 << "\n"
261 << "void main (void)\n"
262 << "{\n"
263 << " atomicAdd(sb_out.result, 1u);\n"
264 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
265 << "}\n";
266
267 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
268 }
269 else
270 {
271 const SpirVAsmBuildOptions buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
272 const std::string src = "; SPIR-V\n"
273 "; Version: 1.0\n"
274 "; Bound: 24\n"
275 "; Schema: 0\n"
276 "OpCapability Shader\n"
277 "OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
278 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
279 "OpMemoryModel Logical GLSL450\n"
280 "OpEntryPoint Fragment %4 \"main\" %20\n"
281 "OpExecutionMode %4 OriginUpperLeft\n"
282 "OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
283 "OpMemberDecorate %7 0 Coherent\n"
284 "OpMemberDecorate %7 0 Offset 0\n"
285 "OpDecorate %7 BufferBlock\n"
286 "OpDecorate %9 DescriptorSet 0\n"
287 "OpDecorate %9 Binding 0\n"
288 "OpDecorate %20 Location 0\n"
289 "%2 = OpTypeVoid\n"
290 "%3 = OpTypeFunction %2\n"
291 "%6 = OpTypeInt 32 0\n"
292 "%7 = OpTypeStruct %6\n"
293 "%8 = OpTypePointer Uniform %7\n"
294 "%9 = OpVariable %8 Uniform\n"
295 "%10 = OpTypeInt 32 1\n"
296 "%11 = OpConstant %10 0\n"
297 "%12 = OpTypePointer Uniform %6\n"
298 "%14 = OpConstant %6 1\n"
299 "%15 = OpConstant %6 0\n"
300 "%17 = OpTypeFloat 32\n"
301 "%18 = OpTypeVector %17 4\n"
302 "%19 = OpTypePointer Output %18\n"
303 "%20 = OpVariable %19 Output\n"
304 "%21 = OpConstant %17 1\n"
305 "%22 = OpConstant %17 0\n"
306 "%23 = OpConstantComposite %18 %21 %21 %22 %21\n"
307 "%4 = OpFunction %2 None %3\n"
308 "%5 = OpLabel\n"
309 "%13 = OpAccessChain %12 %9 %11\n"
310 "%16 = OpAtomicIAdd %6 %13 %14 %15 %14\n"
311 "OpStore %20 %23\n"
312 "OpReturn\n"
313 "OpFunctionEnd\n";
314 programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
315 }
316 }
317
318 class EarlyFragmentTestInstance : public TestInstance
319 {
320 public:
321 EarlyFragmentTestInstance(Context &context, const uint32_t flags);
322
323 tcu::TestStatus iterate(void);
324
325 private:
326 enum TestMode
327 {
328 MODE_INVALID,
329 MODE_DEPTH,
330 MODE_STENCIL,
331 };
332
333 const TestMode m_testMode;
334 const bool m_useTestAttachment;
335 const bool m_useEarlyTests;
336 const bool m_useEarlyLateTests;
337 };
338
EarlyFragmentTestInstance(Context & context,const uint32_t flags)339 EarlyFragmentTestInstance::EarlyFragmentTestInstance(Context &context, const uint32_t flags)
340 : TestInstance(context)
341 , m_testMode(flags & FLAG_TEST_DEPTH ? MODE_DEPTH :
342 flags & FLAG_TEST_STENCIL ? MODE_STENCIL :
343 MODE_INVALID)
344 , m_useTestAttachment((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
345 , m_useEarlyTests((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
346 , m_useEarlyLateTests((flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == FLAG_EARLY_AND_LATE_FRAGMENT_TESTS)
347 {
348 DE_ASSERT(m_testMode != MODE_INVALID);
349 }
350
iterate(void)351 tcu::TestStatus EarlyFragmentTestInstance::iterate(void)
352 {
353 const DeviceInterface &vk = m_context.getDeviceInterface();
354 const InstanceInterface &vki = m_context.getInstanceInterface();
355 const VkDevice device = m_context.getDevice();
356 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
357 const VkQueue queue = m_context.getUniversalQueue();
358 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
359 Allocator &allocator = m_context.getDefaultAllocator();
360
361 // Color attachment
362
363 const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
364 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
365 const VkImageSubresourceRange colorSubresourceRange =
366 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
367 const Unique<VkImage> colorImage(
368 makeImage(vk, device,
369 makeImageCreateInfo(renderSize, colorFormat,
370 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
371 const UniquePtr<Allocation> colorImageAlloc(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
372 const Unique<VkImageView> colorImageView(
373 makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
374
375 // Test attachment (depth or stencil)
376 static const VkFormat stencilFormats[] = {
377 // One of the following formats must be supported, as per spec requirement.
378 VK_FORMAT_S8_UINT,
379 VK_FORMAT_D16_UNORM_S8_UINT,
380 VK_FORMAT_D24_UNORM_S8_UINT,
381 VK_FORMAT_D32_SFLOAT_S8_UINT,
382 };
383
384 const VkFormat testFormat =
385 (m_testMode == MODE_STENCIL ?
386 pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats) :
387 VK_FORMAT_D16_UNORM); // spec requires this format to be supported
388 if (testFormat == VK_FORMAT_UNDEFINED)
389 return tcu::TestStatus::fail("Required depth/stencil format not supported");
390
391 if (m_useTestAttachment)
392 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format "
393 << getFormatName(testFormat) << tcu::TestLog::EndMessage;
394
395 const VkImageSubresourceRange testSubresourceRange =
396 makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
397 const Unique<VkImage> testImage(makeImage(
398 vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
399 const UniquePtr<Allocation> testImageAlloc(bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
400 const Unique<VkImageView> testImageView(
401 makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
402 const VkImageView attachmentImages[] = {*colorImageView, *testImageView};
403 const uint32_t numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
404
405 // Vertex buffer
406
407 const uint32_t numVertices = 6;
408 const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
409 const Unique<VkBuffer> vertexBuffer(
410 makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
411 const UniquePtr<Allocation> vertexBufferAlloc(
412 bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
413
414 {
415 tcu::Vec4 *const pVertices = reinterpret_cast<tcu::Vec4 *>(vertexBufferAlloc->getHostPtr());
416
417 // A small +0.00001f adjustment for the z-coordinate to get the expected rounded value for depth.
418 pVertices[0] = tcu::Vec4(1.0f, -1.0f, 0.50001f, 1.0f);
419 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
420 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.50001f, 1.0f);
421
422 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.50001f, 1.0f);
423 pVertices[4] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
424 pVertices[5] = tcu::Vec4(1.0f, -1.0f, 0.50001f, 1.0f);
425
426 flushAlloc(vk, device, *vertexBufferAlloc);
427 // No barrier needed, flushed memory is automatically visible
428 }
429
430 // Result buffer
431
432 const VkDeviceSize resultBufferSizeBytes = sizeof(uint32_t);
433 const Unique<VkBuffer> resultBuffer(
434 makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
435 const UniquePtr<Allocation> resultBufferAlloc(
436 bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
437
438 {
439 uint32_t *const pData = static_cast<uint32_t *>(resultBufferAlloc->getHostPtr());
440
441 *pData = 0;
442 flushAlloc(vk, device, *resultBufferAlloc);
443 }
444
445 // Render result buffer (to retrieve color attachment contents)
446
447 const VkDeviceSize colorBufferSizeBytes =
448 tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
449 const Unique<VkBuffer> colorBuffer(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
450 const UniquePtr<Allocation> colorBufferAlloc(
451 bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
452
453 // Descriptors
454
455 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
456 DescriptorSetLayoutBuilder()
457 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
458 .build(vk, device));
459
460 const Unique<VkDescriptorPool> descriptorPool(
461 DescriptorPoolBuilder()
462 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
463 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
464
465 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
466 const VkDescriptorBufferInfo resultBufferDescriptorInfo =
467 makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
468
469 DescriptorSetUpdateBuilder()
470 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
471 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
472 .update(vk, device);
473
474 // Pipeline
475
476 const Unique<VkShaderModule> vertexModule(
477 createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
478 const Unique<VkShaderModule> fragmentModule(
479 createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
480 const Unique<VkRenderPass> renderPass(makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
481 const Unique<VkFramebuffer> framebuffer(makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages,
482 attachmentImages, renderSize.x(), renderSize.y()));
483 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
484 const Unique<VkPipeline> pipeline(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule,
485 *fragmentModule, renderSize, (m_testMode == MODE_DEPTH),
486 (m_testMode == MODE_STENCIL)));
487 const Unique<VkCommandPool> cmdPool(
488 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
489 const Unique<VkCommandBuffer> cmdBuffer(
490 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
491
492 // Draw commands
493
494 {
495 const VkRect2D renderArea = {
496 makeOffset2D(0, 0),
497 makeExtent2D(renderSize.x(), renderSize.y()),
498 };
499 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
500 const VkDeviceSize vertexBufferOffset = 0ull;
501
502 beginCommandBuffer(vk, *cmdBuffer);
503
504 {
505 const VkImageMemoryBarrier barriers[] = {
506 makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
507 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresourceRange),
508 makeImageMemoryBarrier(0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
509 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *testImage,
510 testSubresourceRange),
511 };
512
513 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT,
514 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
515 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
516 0u, 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
517 }
518
519 // Will clear the attachments with specified depth and stencil values.
520 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
521
522 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
523 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
524 &descriptorSet.get(), 0u, DE_NULL);
525 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
526
527 // Mask half of the attachment image with value that will pass the stencil test.
528 if (m_useTestAttachment && m_testMode == MODE_STENCIL)
529 commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0),
530 makeExtent2D(renderSize.x() / 2, renderSize.y()), 1u);
531
532 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
533 endRenderPass(vk, *cmdBuffer);
534
535 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
536
537 endCommandBuffer(vk, *cmdBuffer);
538 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
539 }
540
541 // Log result image
542 {
543 invalidateAlloc(vk, device, *colorBufferAlloc);
544
545 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1,
546 colorBufferAlloc->getHostPtr());
547 tcu::TextureLevel referenceImage(mapVkFormat(colorFormat), renderSize.x(), renderSize.y());
548
549 if (m_useTestAttachment == true)
550 {
551 const tcu::Vec4 fillColor = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
552 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
553
554 tcu::clear(referenceImage.getAccess(), clearColor);
555
556 if (m_testMode == MODE_DEPTH)
557 {
558 int xOffset = 0;
559
560 for (int y = 0; y < renderSize.y() - 1; y++)
561 {
562 for (int x = 0; x < renderSize.x() - 1 - xOffset; x++)
563 {
564 referenceImage.getAccess().setPixel(fillColor, x, y);
565 }
566
567 xOffset++;
568 }
569 }
570
571 if (m_testMode == MODE_STENCIL)
572 {
573 for (int y = 0; y < renderSize.y(); y++)
574 {
575 for (int x = 0; x < renderSize.x() / 2; x++)
576 {
577 referenceImage.getAccess().setPixel(fillColor, x, y);
578 }
579 }
580 }
581 }
582 else
583 {
584 const tcu::Vec4 clearColor = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
585
586 tcu::clear(referenceImage.getAccess(), clearColor);
587 }
588
589 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
590 referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f),
591 tcu::COMPARE_LOG_RESULT))
592 return tcu::TestStatus::fail("Rendered color image is not correct");
593 }
594
595 // Verify results
596 {
597 invalidateAlloc(vk, device, *resultBufferAlloc);
598
599 const int actualCounter = *static_cast<int32_t *>(resultBufferAlloc->getHostPtr());
600 const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
601 const int expectedCounter =
602 expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
603 const int tolerance = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3 : 0;
604 const int expectedMin = de::max(0, expectedCounter - tolerance);
605 const int expectedMax =
606 (m_useEarlyLateTests ? (renderSize.x() * renderSize.y()) : (expectedCounter + tolerance));
607
608 tcu::TestLog &log = m_context.getTestContext().getLog();
609 log << tcu::TestLog::Message << "Expected value"
610 << (expectPartialResult ?
611 " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" :
612 ": " + de::toString(expectedCounter))
613 << tcu::TestLog::EndMessage;
614 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
615
616 if (expectedMin <= actualCounter && actualCounter <= expectedMax)
617 return tcu::TestStatus::pass("Success");
618 else
619 return tcu::TestStatus::fail("Value out of range");
620 }
621 }
622
createInstance(Context & context) const623 TestInstance *EarlyFragmentTest::createInstance(Context &context) const
624 {
625 return new EarlyFragmentTestInstance(context, m_flags);
626 }
627
checkSupport(Context & context) const628 void EarlyFragmentTest::checkSupport(Context &context) const
629 {
630 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
631 #ifndef CTS_USES_VULKANSC
632 if ((m_flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == FLAG_EARLY_AND_LATE_FRAGMENT_TESTS)
633 {
634 context.requireDeviceFunctionality("VK_AMD_shader_early_and_late_fragment_tests");
635 if (context.getShaderEarlyAndLateFragmentTestsFeaturesAMD().shaderEarlyAndLateFragmentTests == VK_FALSE)
636 TCU_THROW(NotSupportedError, "shaderEarlyAndLateFragmentTests is not supported");
637 }
638 #endif
639 }
640
641 class EarlyFragmentDiscardTestInstance : public EarlyFragmentTestInstance
642 {
643 public:
644 EarlyFragmentDiscardTestInstance(Context &context, const uint32_t flags);
645
646 tcu::TestStatus iterate(void);
647
648 private:
649 tcu::TextureLevel generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize);
650 enum TestMode
651 {
652 MODE_INVALID,
653 MODE_DEPTH,
654 MODE_STENCIL,
655 };
656
657 const TestMode m_testMode;
658 const bool m_useTestAttachment;
659 const bool m_useEarlyTests;
660 const bool m_useEarlyLateTests;
661 };
662
EarlyFragmentDiscardTestInstance(Context & context,const uint32_t flags)663 EarlyFragmentDiscardTestInstance::EarlyFragmentDiscardTestInstance(Context &context, const uint32_t flags)
664 : EarlyFragmentTestInstance(context, flags)
665 , m_testMode(flags & FLAG_TEST_DEPTH ? MODE_DEPTH :
666 flags & FLAG_TEST_STENCIL ? MODE_STENCIL :
667 MODE_INVALID)
668 , m_useTestAttachment((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
669 , m_useEarlyTests((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
670 , m_useEarlyLateTests((flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) != 0)
671 {
672 DE_ASSERT(m_testMode != MODE_INVALID);
673 }
674
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)675 tcu::TextureLevel EarlyFragmentDiscardTestInstance::generateReferenceColorImage(const tcu::TextureFormat format,
676 const tcu::IVec2 &renderSize)
677 {
678 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
679 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
680
681 tcu::clear(image.getAccess(), clearColor);
682
683 return image;
684 }
685
iterate(void)686 tcu::TestStatus EarlyFragmentDiscardTestInstance::iterate(void)
687 {
688 const DeviceInterface &vk = m_context.getDeviceInterface();
689 const InstanceInterface &vki = m_context.getInstanceInterface();
690 const VkDevice device = m_context.getDevice();
691 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
692 const VkQueue queue = m_context.getUniversalQueue();
693 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
694 Allocator &allocator = m_context.getDefaultAllocator();
695
696 DE_ASSERT(m_useTestAttachment);
697
698 // Color attachment
699 const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
700 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
701 const VkImageSubresourceRange colorSubresourceRange =
702 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
703 const Unique<VkImage> colorImage(
704 makeImage(vk, device,
705 makeImageCreateInfo(renderSize, colorFormat,
706 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
707 const UniquePtr<Allocation> colorImageAlloc(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
708 const Unique<VkImageView> colorImageView(
709 makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
710
711 // Test attachment (depth or stencil)
712 static const VkFormat stencilFormats[] = {
713 // One of the following formats must be supported, as per spec requirement.
714 VK_FORMAT_S8_UINT,
715 VK_FORMAT_D16_UNORM_S8_UINT,
716 VK_FORMAT_D24_UNORM_S8_UINT,
717 VK_FORMAT_D32_SFLOAT_S8_UINT,
718 };
719
720 const VkFormat depthStencilFormat =
721 (m_testMode == MODE_STENCIL ?
722 pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats) :
723 VK_FORMAT_D16_UNORM); // spec requires this format to be supported
724
725 if (depthStencilFormat == VK_FORMAT_UNDEFINED)
726 return tcu::TestStatus::fail("Required depth/stencil format not supported");
727
728 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format "
729 << getFormatName(depthStencilFormat) << tcu::TestLog::EndMessage;
730
731 const VkImageSubresourceRange testSubresourceRange =
732 makeImageSubresourceRange(getImageAspectFlags(depthStencilFormat), 0u, 1u, 0u, 1u);
733 const Unique<VkImage> testImage(
734 makeImage(vk, device,
735 makeImageCreateInfo(renderSize, depthStencilFormat,
736 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
737 const UniquePtr<Allocation> testImageAlloc(bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
738 const Unique<VkImageView> testImageView(
739 makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, testSubresourceRange));
740 const VkImageView attachmentImages[] = {*colorImageView, *testImageView};
741 const uint32_t numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
742
743 // Vertex buffer
744
745 const uint32_t numVertices = 6;
746 const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
747 const Unique<VkBuffer> vertexBuffer(
748 makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
749 const UniquePtr<Allocation> vertexBufferAlloc(
750 bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
751
752 {
753 tcu::Vec4 *const pVertices = reinterpret_cast<tcu::Vec4 *>(vertexBufferAlloc->getHostPtr());
754
755 pVertices[0] = tcu::Vec4(1.0f, -1.0f, 0.5f, 1.0f);
756 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
757 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
758
759 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
760 pVertices[4] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
761 pVertices[5] = tcu::Vec4(1.0f, -1.0f, 0.5f, 1.0f);
762
763 flushAlloc(vk, device, *vertexBufferAlloc);
764 // No barrier needed, flushed memory is automatically visible
765 }
766
767 // Result buffer
768
769 const VkDeviceSize resultBufferSizeBytes = sizeof(uint32_t);
770 const Unique<VkBuffer> resultBuffer(
771 makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
772 const UniquePtr<Allocation> resultBufferAlloc(
773 bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
774
775 {
776 uint32_t *const pData = static_cast<uint32_t *>(resultBufferAlloc->getHostPtr());
777
778 *pData = 0;
779 flushAlloc(vk, device, *resultBufferAlloc);
780 }
781
782 // Render result buffer (to retrieve color attachment contents)
783
784 const VkDeviceSize colorBufferSizeBytes =
785 tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
786 const Unique<VkBuffer> colorBuffer(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
787 const UniquePtr<Allocation> colorBufferAlloc(
788 bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
789
790 // Depth stencil result buffer (to retrieve depth-stencil attachment contents)
791
792 const VkDeviceSize dsBufferSizeBytes =
793 tcu::getPixelSize(mapVkFormat(depthStencilFormat)) * renderSize.x() * renderSize.y();
794 const Unique<VkBuffer> dsBuffer(makeBuffer(vk, device, dsBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
795 const UniquePtr<Allocation> dsBufferAlloc(
796 bindBuffer(vk, device, allocator, *dsBuffer, MemoryRequirement::HostVisible));
797
798 // Descriptors
799
800 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
801 DescriptorSetLayoutBuilder()
802 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
803 .build(vk, device));
804
805 const Unique<VkDescriptorPool> descriptorPool(
806 DescriptorPoolBuilder()
807 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
808 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
809
810 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
811 const VkDescriptorBufferInfo resultBufferDescriptorInfo =
812 makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
813
814 DescriptorSetUpdateBuilder()
815 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
816 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
817 .update(vk, device);
818
819 // Pipeline
820
821 const Unique<VkShaderModule> vertexModule(
822 createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
823 const Unique<VkShaderModule> fragmentModule(
824 createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
825 const Unique<VkRenderPass> renderPass(
826 makeRenderPass(vk, device, colorFormat, m_useTestAttachment, depthStencilFormat));
827 const Unique<VkFramebuffer> framebuffer(makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages,
828 attachmentImages, renderSize.x(), renderSize.y()));
829 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
830 const Unique<VkPipeline> pipeline(
831 makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
832 (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL),
833 VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));
834 const Unique<VkCommandPool> cmdPool(
835 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
836 const Unique<VkCommandBuffer> cmdBuffer(
837 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
838
839 // Draw commands
840 {
841 const VkRect2D renderArea = {
842 makeOffset2D(0, 0),
843 makeExtent2D(renderSize.x(), renderSize.y()),
844 };
845 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
846 const VkDeviceSize vertexBufferOffset = 0ull;
847
848 beginCommandBuffer(vk, *cmdBuffer);
849
850 {
851 const VkImageMemoryBarrier barriers[] = {
852 makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
853 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresourceRange),
854 makeImageMemoryBarrier(0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
855 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *testImage,
856 testSubresourceRange),
857 };
858
859 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT,
860 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
861 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
862 0u, 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
863 }
864
865 // Will clear the attachments with specified depth and stencil values.
866 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 3u);
867
868 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
869 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
870 &descriptorSet.get(), 0u, DE_NULL);
871 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
872
873 // Mask half of the attachment image with value that will pass the stencil test.
874 if (m_testMode == MODE_STENCIL)
875 commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0),
876 makeExtent2D(renderSize.x() / 2, renderSize.y()), 1u);
877
878 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
879 endRenderPass(vk, *cmdBuffer);
880
881 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
882 VkImageAspectFlags dsAspect =
883 m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
884 VkImageLayout dsImageLayout = m_testMode == MODE_DEPTH ? VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL :
885 VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
886 copyImageToBuffer(vk, *cmdBuffer, *testImage, *dsBuffer, renderSize,
887 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, dsImageLayout, 1u, dsAspect, dsAspect);
888
889 endCommandBuffer(vk, *cmdBuffer);
890 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
891 }
892
893 // Verify color output
894 {
895 invalidateAlloc(vk, device, *colorBufferAlloc);
896
897 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1,
898 colorBufferAlloc->getHostPtr());
899 const tcu::TextureLevel referenceImage = generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
900 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
901 referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f),
902 tcu::COMPARE_LOG_RESULT))
903 printf("Rendered color image is not correct");
904 }
905
906 // Verify depth-stencil output
907 {
908 invalidateAlloc(vk, device, *dsBufferAlloc);
909 // the buffer holds only one aspect of d/s format
910 tcu::TextureFormat format =
911 vk::mapVkFormat(m_testMode == MODE_STENCIL ? VK_FORMAT_S8_UINT : depthStencilFormat);
912 DE_ASSERT(format.order == tcu::TextureFormat::D || format.order == tcu::TextureFormat::S);
913
914 const tcu::ConstPixelBufferAccess dsPixelAccess(format, renderSize.x(), renderSize.y(), 1,
915 dsBufferAlloc->getHostPtr());
916
917 for (int z = 0; z < dsPixelAccess.getDepth(); z++)
918 for (int y = 0; y < dsPixelAccess.getHeight(); y++)
919 for (int x = 0; x < dsPixelAccess.getWidth(); x++)
920 {
921 float depthValue = (m_testMode == MODE_DEPTH) ? dsPixelAccess.getPixDepth(x, y, z) : 0.0f;
922 int stencilValue = (m_testMode == MODE_STENCIL) ? dsPixelAccess.getPixStencil(x, y, z) : 0;
923
924 // Depth test should write to the depth buffer even when there is a discard in the fragment shader,
925 // when early fragment tests are enabled. We allow some tolerance to account for precision error
926 // on depth writes.
927 if (m_testMode == MODE_DEPTH)
928 {
929 float tolerance = 0.0001f;
930 if (m_useEarlyTests && ((x + y) < 31) && depthValue >= 0.50 + tolerance)
931 {
932 std::ostringstream error;
933 error << "Rendered depth value [ " << x << ", " << y << ", " << z
934 << "] is not correct: " << depthValue << " >= 0.5f";
935 TCU_FAIL(error.str().c_str());
936 }
937 // When early fragment tests are disabled, the depth test happens after the fragment shader, but as we are discarding
938 // all fragments, the stored value in the depth buffer should be the clear one (0.5f).
939 if (!m_useEarlyTests && deAbs(depthValue - 0.5f) > tolerance)
940 {
941 std::ostringstream error;
942 error << "Rendered depth value [ " << x << ", " << y << ", " << z
943 << "] is not correct: " << depthValue << " != 0.5f";
944 TCU_FAIL(error.str().c_str());
945 }
946 }
947
948 if (m_testMode == MODE_STENCIL)
949 {
950 if (m_useEarlyTests && ((x < 16 && stencilValue != 2u) || (x >= 16 && stencilValue != 4u)))
951 {
952 std::ostringstream error;
953 error << "Rendered stencil value [ " << x << ", " << y << ", " << z
954 << "] is not correct: " << stencilValue << " != ";
955 error << (x < 16 ? 2u : 4u);
956 TCU_FAIL(error.str().c_str());
957 }
958
959 if (!m_useEarlyTests && ((x < 16 && stencilValue != 1u) || (x >= 16 && stencilValue != 3u)))
960 {
961 std::ostringstream error;
962 error << "Rendered stencil value [ " << x << ", " << y << ", " << z
963 << "] is not correct: " << stencilValue << " != ";
964 error << (x < 16 ? 1u : 3u);
965 TCU_FAIL(error.str().c_str());
966 }
967 }
968 }
969 }
970
971 // Verify we process all the fragments
972 {
973 invalidateAlloc(vk, device, *resultBufferAlloc);
974
975 const int actualCounter = *static_cast<int32_t *>(resultBufferAlloc->getHostPtr());
976 const bool expectPartialResult = m_useEarlyTests;
977 const int expectedCounter =
978 expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
979 const int tolerance = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3 : 0;
980 const int expectedMin = de::max(0, expectedCounter - tolerance);
981 const int expectedMax =
982 (m_useEarlyLateTests ? (renderSize.x() * renderSize.y()) : (expectedCounter + tolerance));
983
984 tcu::TestLog &log = m_context.getTestContext().getLog();
985 log << tcu::TestLog::Message << "Expected value"
986 << (expectPartialResult ?
987 " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" :
988 ": " + de::toString(expectedCounter))
989 << tcu::TestLog::EndMessage;
990 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
991
992 if (expectedMin <= actualCounter && actualCounter <= expectedMax)
993 return tcu::TestStatus::pass("Success");
994 else
995 return tcu::TestStatus::fail("Value out of range");
996 }
997 }
998
999 class EarlyFragmentDiscardTest : public EarlyFragmentTest
1000 {
1001 public:
1002 EarlyFragmentDiscardTest(tcu::TestContext &testCtx, const std::string name, const uint32_t flags);
1003
1004 void initPrograms(SourceCollections &programCollection) const;
1005 TestInstance *createInstance(Context &context) const;
1006
1007 private:
1008 const uint32_t m_flags;
1009 };
1010
EarlyFragmentDiscardTest(tcu::TestContext & testCtx,const std::string name,const uint32_t flags)1011 EarlyFragmentDiscardTest::EarlyFragmentDiscardTest(tcu::TestContext &testCtx, const std::string name,
1012 const uint32_t flags)
1013 : EarlyFragmentTest(testCtx, name, flags)
1014 , m_flags(flags)
1015 {
1016 }
1017
createInstance(Context & context) const1018 TestInstance *EarlyFragmentDiscardTest::createInstance(Context &context) const
1019 {
1020 return new EarlyFragmentDiscardTestInstance(context, m_flags);
1021 }
1022
initPrograms(SourceCollections & programCollection) const1023 void EarlyFragmentDiscardTest::initPrograms(SourceCollections &programCollection) const
1024 {
1025 // Vertex
1026 {
1027 std::ostringstream src;
1028 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1029 << "\n"
1030 << "layout(location = 0) in highp vec4 position;\n"
1031 << "\n"
1032 << "out gl_PerVertex {\n"
1033 << " vec4 gl_Position;\n"
1034 << "};\n"
1035 << "\n"
1036 << "void main (void)\n"
1037 << "{\n"
1038 << " gl_Position = position;\n"
1039 << "}\n";
1040
1041 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1042 }
1043
1044 // Fragment
1045 {
1046 if ((m_flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == 0)
1047 {
1048 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
1049 std::ostringstream src;
1050 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1051 << "\n"
1052 << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
1053 << "layout(location = 0) out highp vec4 fragColor;\n"
1054 << "\n"
1055 << "layout(binding = 0) coherent buffer Output {\n"
1056 << " uint result;\n"
1057 << "} sb_out;\n"
1058 << "\n"
1059 << "void main (void)\n"
1060 << "{\n"
1061 << " atomicAdd(sb_out.result, 1u);\n"
1062 << " gl_FragDepth = 0.75f;\n"
1063 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
1064 << " discard;\n"
1065 << "}\n";
1066 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1067 }
1068 else
1069 {
1070 const SpirVAsmBuildOptions buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
1071 const std::string src = "; SPIR - V\n"
1072 "; Version: 1.0\n"
1073 "; Generator: Khronos Glslang Reference Front End; 10\n"
1074 "; Bound: 28\n"
1075 "; Schema: 0\n"
1076 "OpCapability Shader\n"
1077 "OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
1078 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
1079 "OpMemoryModel Logical GLSL450\n"
1080 "OpEntryPoint Fragment %4 \"main\" %19 %23\n"
1081 "OpExecutionMode %4 OriginUpperLeft\n"
1082 "OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
1083 "OpExecutionMode %4 DepthReplacing\n"
1084 "OpExecutionMode %4 DepthGreater\n"
1085 "OpMemberDecorate %7 0 Coherent\n"
1086 "OpMemberDecorate %7 0 Offset 0\n"
1087 "OpDecorate %7 BufferBlock\n"
1088 "OpDecorate %9 DescriptorSet 0\n"
1089 "OpDecorate %9 Binding 0\n"
1090 "OpDecorate %19 BuiltIn FragDepth\n"
1091 "OpDecorate %23 Location 0\n"
1092 "%2 = OpTypeVoid\n"
1093 "%3 = OpTypeFunction %2\n"
1094 "%6 = OpTypeInt 32 0\n"
1095 "%7 = OpTypeStruct %6\n"
1096 "%8 = OpTypePointer Uniform %7\n"
1097 "%9 = OpVariable %8 Uniform\n"
1098 "%10 = OpTypeInt 32 1\n"
1099 "%11 = OpConstant %10 0\n"
1100 "%12 = OpTypePointer Uniform %6\n"
1101 "%14 = OpConstant %6 1\n"
1102 "%15 = OpConstant %6 0\n"
1103 "%17 = OpTypeFloat 32\n"
1104 "%18 = OpTypePointer Output %17\n"
1105 "%19 = OpVariable %18 Output\n"
1106 "%20 = OpConstant %17 0.75\n"
1107 "%21 = OpTypeVector %17 4\n"
1108 "%22 = OpTypePointer Output %21\n"
1109 "%23 = OpVariable %22 Output\n"
1110 "%24 = OpConstant %17 1\n"
1111 "%25 = OpConstant %17 0\n"
1112 "%26 = OpConstantComposite %21 %24 %24 %25 %24\n"
1113 "%4 = OpFunction %2 None %3\n"
1114 "%5 = OpLabel\n"
1115 "%13 = OpAccessChain %12 %9 %11\n"
1116 "%16 = OpAtomicIAdd %6 %13 %14 %15 %14\n"
1117 "OpStore %19 %20\n"
1118 "OpStore %23 %26\n"
1119 "OpKill\n"
1120 "OpFunctionEnd\n";
1121 programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
1122 }
1123 }
1124 }
1125
1126 class EarlyFragmentSampleMaskTestInstance : public EarlyFragmentTestInstance
1127 {
1128 public:
1129 EarlyFragmentSampleMaskTestInstance(Context &context, const uint32_t flags, const uint32_t sampleCount);
1130
1131 tcu::TestStatus iterate(void);
1132
1133 private:
1134 tcu::TextureLevel generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize);
1135 Move<VkRenderPass> makeRenderPass(const DeviceInterface &vk, const VkDevice device, const VkFormat colorFormat,
1136 const VkFormat depthStencilFormat);
1137 Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface &vk, const VkDevice device,
1138 const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass,
1139 const VkShaderModule vertexModule, const VkShaderModule fragmentModule,
1140 const tcu::IVec2 &renderSize, const bool enableDepthTest,
1141 const bool enableStencilTest, const VkStencilOp stencilFailOp,
1142 const VkStencilOp stencilPassOp);
1143 enum TestMode
1144 {
1145 MODE_INVALID,
1146 MODE_DEPTH,
1147 MODE_STENCIL,
1148 };
1149
1150 const TestMode m_testMode;
1151 const bool m_useTestAttachment;
1152 const bool m_useEarlyTests;
1153 const uint32_t m_sampleCount;
1154 };
1155
EarlyFragmentSampleMaskTestInstance(Context & context,const uint32_t flags,const uint32_t sampleCount)1156 EarlyFragmentSampleMaskTestInstance::EarlyFragmentSampleMaskTestInstance(Context &context, const uint32_t flags,
1157 const uint32_t sampleCount)
1158 : EarlyFragmentTestInstance(context, flags)
1159 , m_testMode(flags & FLAG_TEST_DEPTH ? MODE_DEPTH :
1160 flags & FLAG_TEST_STENCIL ? MODE_STENCIL :
1161 MODE_INVALID)
1162 , m_useTestAttachment((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
1163 , m_useEarlyTests((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
1164 , m_sampleCount(sampleCount)
1165 {
1166 DE_ASSERT(m_testMode != MODE_INVALID);
1167 }
1168
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)1169 tcu::TextureLevel EarlyFragmentSampleMaskTestInstance::generateReferenceColorImage(const tcu::TextureFormat format,
1170 const tcu::IVec2 &renderSize)
1171 {
1172 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
1173 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1174
1175 tcu::clear(image.getAccess(), clearColor);
1176
1177 return image;
1178 }
1179
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & renderSize,const bool enableDepthTest,const bool enableStencilTest,const VkStencilOp stencilFailOp,const VkStencilOp stencilPassOp)1180 Move<VkPipeline> EarlyFragmentSampleMaskTestInstance::makeGraphicsPipeline(
1181 const DeviceInterface &vk, const VkDevice device, const VkPipelineLayout pipelineLayout,
1182 const VkRenderPass renderPass, const VkShaderModule vertexModule, const VkShaderModule fragmentModule,
1183 const tcu::IVec2 &renderSize, const bool enableDepthTest, const bool enableStencilTest,
1184 const VkStencilOp stencilFailOp, const VkStencilOp stencilPassOp)
1185 {
1186 const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
1187 const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
1188
1189 const VkStencilOpState stencilOpState = makeStencilOpState(stencilFailOp, // stencil fail
1190 stencilPassOp, // depth & stencil pass
1191 VK_STENCIL_OP_KEEP, // depth only fail
1192 VK_COMPARE_OP_EQUAL, // compare op
1193 0x3, // compare mask
1194 0xf, // write mask
1195 1u); // reference
1196
1197 const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
1198 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
1199 DE_NULL, // const void* pNext
1200 0u, // VkPipelineDepthStencilStateCreateFlags flags
1201 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthTestEnable
1202 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthWriteEnable
1203 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp
1204 VK_FALSE, // VkBool32 depthBoundsTestEnable
1205 enableStencilTest ? VK_TRUE : VK_FALSE, // VkBool32 stencilTestEnable
1206 stencilOpState, // VkStencilOpState front
1207 stencilOpState, // VkStencilOpState back
1208 0.0f, // float minDepthBounds
1209 1.0f // float maxDepthBounds
1210 };
1211
1212 // Only allow coverage on sample 0.
1213 const VkSampleMask sampleMask = 0x1;
1214
1215 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
1216 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType
1217 DE_NULL, // const void* pNext
1218 0u, // VkPipelineMultisampleStateCreateFlags flags
1219 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits rasterizationSamples
1220 true, // VkBool32 sampleShadingEnable
1221 0.0f, // float minSampleShading
1222 &sampleMask, // const VkSampleMask* pSampleMask
1223 false, // VkBool32 alphaToCoverageEnable
1224 false, // VkBool32 alphaToOneEnable
1225 };
1226
1227 return vk::makeGraphicsPipeline(
1228 vk, // const DeviceInterface& vk
1229 device, // const VkDevice device
1230 pipelineLayout, // const VkPipelineLayout pipelineLayout
1231 vertexModule, // const VkShaderModule vertexShaderModule
1232 DE_NULL, // const VkShaderModule tessellationControlModule
1233 DE_NULL, // const VkShaderModule tessellationEvalModule
1234 DE_NULL, // const VkShaderModule geometryShaderModule
1235 fragmentModule, // const VkShaderModule fragmentShaderModule
1236 renderPass, // const VkRenderPass renderPass
1237 viewports, // const std::vector<VkViewport>& viewports
1238 scissors, // const std::vector<VkRect2D>& scissors
1239 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
1240 0u, // const uint32_t subpass
1241 0u, // const uint32_t patchControlPoints
1242 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
1243 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1244 &multisampleStateCreateInfo, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
1245 &depthStencilStateCreateInfo); // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
1246 }
1247
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat depthStencilFormat)1248 Move<VkRenderPass> EarlyFragmentSampleMaskTestInstance::makeRenderPass(const DeviceInterface &vk, const VkDevice device,
1249 const VkFormat colorFormat,
1250 const VkFormat depthStencilFormat)
1251 {
1252 const bool hasColor = colorFormat != VK_FORMAT_UNDEFINED;
1253 const bool hasDepthStencil = depthStencilFormat != VK_FORMAT_UNDEFINED;
1254
1255 const VkAttachmentDescription2 colorAttachmentDescription = {
1256 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1257 DE_NULL, // const void* pNext;
1258 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
1259 colorFormat, // VkFormat format
1260 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples
1261 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
1262 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
1263 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
1264 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
1265 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
1266 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
1267 };
1268
1269 const VkAttachmentDescription2 depthStencilAttachmentDescription = {
1270 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1271 DE_NULL, // const void* pNext;
1272 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
1273 depthStencilFormat, // VkFormat format
1274 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples
1275 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
1276 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
1277 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp
1278 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp
1279 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
1280 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
1281 };
1282
1283 const VkAttachmentDescription2 resolveAttachmentDescription = {
1284 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1285 DE_NULL, // const void* pNext;
1286 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
1287 colorFormat, // VkFormat format
1288 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
1289 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
1290 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
1291 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
1292 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
1293 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
1294 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
1295 };
1296
1297 const VkAttachmentDescription2 resolveDepthStencilAttachmentDescription = {
1298 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1299 DE_NULL, // const void* pNext;
1300 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
1301 depthStencilFormat, // VkFormat format
1302 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
1303 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
1304 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
1305 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp
1306 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp
1307 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
1308 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
1309 };
1310
1311 std::vector<VkAttachmentDescription2> attachmentDescriptions;
1312
1313 if (hasColor)
1314 attachmentDescriptions.push_back(colorAttachmentDescription);
1315 if (hasDepthStencil)
1316 attachmentDescriptions.push_back(depthStencilAttachmentDescription);
1317 if (hasColor)
1318 attachmentDescriptions.push_back(resolveAttachmentDescription);
1319 if (hasDepthStencil)
1320 attachmentDescriptions.push_back(resolveDepthStencilAttachmentDescription);
1321
1322 const VkAttachmentReference2 colorAttachmentRef = {
1323 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
1324 DE_NULL, // const void* pNext;
1325 0u, // uint32_t attachment
1326 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
1327 VK_IMAGE_ASPECT_COLOR_BIT // VkImageAspectFlags aspectMask;
1328 };
1329
1330 const VkAttachmentReference2 depthStencilAttachmentRef = {
1331 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
1332 DE_NULL, // const void* pNext;
1333 hasDepthStencil ? 1u : 0u, // uint32_t attachment
1334 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout layout
1335 VkImageAspectFlags(m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT :
1336 VK_IMAGE_ASPECT_STENCIL_BIT) // VkImageAspectFlags aspectMask;
1337 };
1338
1339 const VkAttachmentReference2 resolveAttachmentRef = {
1340 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
1341 DE_NULL, // const void* pNext;
1342 hasColor ? 2u : 0u, // uint32_t attachment
1343 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
1344 VK_IMAGE_ASPECT_COLOR_BIT // VkImageAspectFlags aspectMask;
1345 };
1346
1347 const VkAttachmentReference2 depthStencilResolveAttachmentRef = {
1348 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
1349 DE_NULL, // const void* pNext;
1350 hasDepthStencil ? 3u : 0u, // uint32_t attachment
1351 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout layout
1352 VkImageAspectFlags(m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT :
1353 VK_IMAGE_ASPECT_STENCIL_BIT) // VkImageAspectFlags aspectMask;
1354 };
1355
1356 // Using VK_RESOLVE_MODE_SAMPLE_ZERO_BIT as resolve mode, so no need to check its support as it is mandatory in the extension.
1357 const VkSubpassDescriptionDepthStencilResolve depthStencilResolveDescription = {
1358 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE, // VkStructureType sType;
1359 DE_NULL, // const void* pNext;
1360 VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, // VkResolveModeFlagBits depthResolveMode;
1361 VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, // VkResolveModeFlagBits stencilResolveMode;
1362 &depthStencilResolveAttachmentRef // const VkAttachmentReference2* pDepthStencilResolveAttachment;
1363 };
1364
1365 const VkSubpassDescription2 subpassDescription = {
1366 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, // VkStructureType sType;
1367 hasDepthStencil ? &depthStencilResolveDescription : DE_NULL, // const void* pNext;
1368 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
1369 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
1370 0u, // uint32_t viewMask;
1371 0u, // uint32_t inputAttachmentCount
1372 DE_NULL, // const VkAttachmentReference2* pInputAttachments
1373 hasColor ? 1u : 0u, // uint32_t colorAttachmentCount
1374 hasColor ? &colorAttachmentRef : DE_NULL, // const VkAttachmentReference2* pColorAttachments
1375 hasColor ? &resolveAttachmentRef : DE_NULL, // const VkAttachmentReference2* pResolveAttachments
1376 hasDepthStencil ? &depthStencilAttachmentRef :
1377 DE_NULL, // const VkAttachmentReference2* pDepthStencilAttachment
1378 0u, // uint32_t preserveAttachmentCount
1379 DE_NULL // const uint32_t* pPreserveAttachments
1380 };
1381
1382 const VkRenderPassCreateInfo2 renderPassInfo = {
1383 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, // VkStructureType sType
1384 DE_NULL, // const void* pNext
1385 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
1386 (uint32_t)attachmentDescriptions.size(), // uint32_t attachmentCount
1387 attachmentDescriptions.size() > 0 ? &attachmentDescriptions[0] :
1388 DE_NULL, // const VkAttachmentDescription2* pAttachments
1389 1u, // uint32_t subpassCount
1390 &subpassDescription, // const VkSubpassDescription2* pSubpasses
1391 0u, // uint32_t dependencyCount
1392 DE_NULL, // const VkSubpassDependency* pDependencies
1393 0u, // uint32_t correlatedViewMaskCount;
1394 DE_NULL, // const uint32_t* pCorrelatedViewMasks;
1395 };
1396
1397 return createRenderPass2(vk, device, &renderPassInfo, DE_NULL);
1398 }
1399
iterate(void)1400 tcu::TestStatus EarlyFragmentSampleMaskTestInstance::iterate(void)
1401 {
1402 const DeviceInterface &vk = m_context.getDeviceInterface();
1403 const InstanceInterface &vki = m_context.getInstanceInterface();
1404 const VkDevice device = m_context.getDevice();
1405 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1406 const VkQueue queue = m_context.getUniversalQueue();
1407 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1408 Allocator &allocator = m_context.getDefaultAllocator();
1409 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1410
1411 DE_ASSERT(m_useTestAttachment);
1412 DE_UNREF(m_useTestAttachment);
1413
1414 // Test attachment (depth or stencil)
1415 static const VkFormat stencilFormats[] = {
1416 // One of the following formats must be supported, as per spec requirement.
1417 VK_FORMAT_S8_UINT,
1418 VK_FORMAT_D16_UNORM_S8_UINT,
1419 VK_FORMAT_D24_UNORM_S8_UINT,
1420 VK_FORMAT_D32_SFLOAT_S8_UINT,
1421 };
1422
1423 const VkFormat depthStencilFormat =
1424 (m_testMode == MODE_STENCIL ?
1425 pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats) :
1426 VK_FORMAT_D16_UNORM); // spec requires this format to be supported
1427
1428 if (depthStencilFormat == VK_FORMAT_UNDEFINED)
1429 return tcu::TestStatus::fail("Required depth/stencil format not supported");
1430
1431 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format "
1432 << getFormatName(depthStencilFormat) << tcu::TestLog::EndMessage;
1433
1434 // Check support for MSAA image formats used in the test.
1435 VkImageFormatProperties formatProperties;
1436 vki.getPhysicalDeviceImageFormatProperties(physDevice, colorFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
1437 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
1438 0u, &formatProperties);
1439 if ((formatProperties.sampleCounts & m_sampleCount) == 0)
1440 TCU_THROW(NotSupportedError, "Format does not support this number of samples for color format");
1441
1442 vki.getPhysicalDeviceImageFormatProperties(
1443 physDevice, depthStencilFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
1444 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
1445 if ((formatProperties.sampleCounts & m_sampleCount) == 0)
1446 TCU_THROW(NotSupportedError, "Format does not support this number of samples for depth-stencil format");
1447
1448 // Color attachment
1449 const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
1450 const VkImageSubresourceRange colorSubresourceRange =
1451 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1452
1453 const VkImageCreateInfo imageParams = {
1454 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1455 DE_NULL, // const void* pNext;
1456 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
1457 VK_IMAGE_TYPE_2D, // VkImageType imageType;
1458 colorFormat, // VkFormat format;
1459 makeExtent3D(renderSize.x(), renderSize.y(), 1), // VkExtent3D extent;
1460 1u, // uint32_t mipLevels;
1461 1u, // uint32_t arrayLayers;
1462 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples;
1463 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1464 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
1465 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1466 0u, // uint32_t queueFamilyIndexCount;
1467 DE_NULL, // const uint32_t* pQueueFamilyIndices;
1468 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1469 };
1470 const Unique<VkImage> colorImage(makeImage(vk, device, imageParams));
1471 const UniquePtr<Allocation> colorImageAlloc(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1472 const Unique<VkImageView> colorImageView(
1473 makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1474
1475 const Unique<VkImage> resolveColorImage(
1476 makeImage(vk, device,
1477 makeImageCreateInfo(renderSize, colorFormat,
1478 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1479 const UniquePtr<Allocation> resolveColorImageAlloc(
1480 bindImage(vk, device, allocator, *resolveColorImage, MemoryRequirement::Any));
1481 const Unique<VkImageView> resolveColorImageView(
1482 makeImageView(vk, device, *resolveColorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1483
1484 // Depth-Stencil attachment
1485 const VkImageSubresourceRange depthStencilSubresourceRange =
1486 makeImageSubresourceRange(getImageAspectFlags(depthStencilFormat), 0u, 1u, 0u, 1u);
1487
1488 const VkImageCreateInfo depthStencilImageParams = {
1489 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1490 DE_NULL, // const void* pNext;
1491 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
1492 VK_IMAGE_TYPE_2D, // VkImageType imageType;
1493 depthStencilFormat, // VkFormat format;
1494 makeExtent3D(renderSize.x(), renderSize.y(), 1), // VkExtent3D extent;
1495 1u, // uint32_t mipLevels;
1496 1u, // uint32_t arrayLayers;
1497 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples;
1498 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1499 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
1500 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1501 0u, // uint32_t queueFamilyIndexCount;
1502 DE_NULL, // const uint32_t* pQueueFamilyIndices;
1503 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1504 };
1505 const Unique<VkImage> depthStencilImage(makeImage(vk, device, depthStencilImageParams));
1506 const UniquePtr<Allocation> depthStencilImageAlloc(
1507 bindImage(vk, device, allocator, *depthStencilImage, MemoryRequirement::Any));
1508 const Unique<VkImageView> depthStencilImageView(makeImageView(vk, device, *depthStencilImage, VK_IMAGE_VIEW_TYPE_2D,
1509 depthStencilFormat, depthStencilSubresourceRange));
1510
1511 const Unique<VkImage> resolveDepthStencilImage(
1512 makeImage(vk, device,
1513 makeImageCreateInfo(renderSize, depthStencilFormat,
1514 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1515 const UniquePtr<Allocation> resolveDepthStencilImageAlloc(
1516 bindImage(vk, device, allocator, *resolveDepthStencilImage, MemoryRequirement::Any));
1517 const Unique<VkImageView> resolveDepthStencilImageView(makeImageView(vk, device, *resolveDepthStencilImage,
1518 VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat,
1519 depthStencilSubresourceRange));
1520
1521 const VkImageView attachmentImages[] = {*colorImageView, *depthStencilImageView, *resolveColorImageView,
1522 *resolveDepthStencilImageView};
1523 const uint32_t numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
1524
1525 // Vertex buffer
1526
1527 const uint32_t numVertices = 6u;
1528 const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
1529 const Unique<VkBuffer> vertexBuffer(
1530 makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1531 const UniquePtr<Allocation> vertexBufferAlloc(
1532 bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1533
1534 {
1535 tcu::Vec4 *const pVertices = reinterpret_cast<tcu::Vec4 *>(vertexBufferAlloc->getHostPtr());
1536
1537 pVertices[0] = tcu::Vec4(1.0f, -1.0f, 0.5f, 1.0f);
1538 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
1539 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
1540
1541 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
1542 pVertices[4] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
1543 pVertices[5] = tcu::Vec4(1.0f, -1.0f, 0.5f, 1.0f);
1544
1545 flushAlloc(vk, device, *vertexBufferAlloc);
1546 // No barrier needed, flushed memory is automatically visible
1547 }
1548
1549 // Result buffer
1550
1551 const VkDeviceSize resultBufferSizeBytes = sizeof(uint32_t);
1552 const Unique<VkBuffer> resultBuffer(
1553 makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1554 const UniquePtr<Allocation> resultBufferAlloc(
1555 bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
1556
1557 {
1558 uint32_t *const pData = static_cast<uint32_t *>(resultBufferAlloc->getHostPtr());
1559
1560 *pData = 0;
1561 flushAlloc(vk, device, *resultBufferAlloc);
1562 }
1563
1564 // Render result buffer (to retrieve color attachment contents)
1565
1566 const VkDeviceSize colorBufferSizeBytes =
1567 tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
1568 const Unique<VkBuffer> colorBuffer(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1569 const UniquePtr<Allocation> colorBufferAlloc(
1570 bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1571
1572 // Depth stencil result buffer (to retrieve depth-stencil attachment contents)
1573
1574 const VkDeviceSize dsBufferSizeBytes =
1575 tcu::getPixelSize(mapVkFormat(depthStencilFormat)) * renderSize.x() * renderSize.y();
1576 const Unique<VkBuffer> dsBuffer(makeBuffer(vk, device, dsBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1577 const UniquePtr<Allocation> dsBufferAlloc(
1578 bindBuffer(vk, device, allocator, *dsBuffer, MemoryRequirement::HostVisible));
1579
1580 // Descriptors
1581
1582 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1583 DescriptorSetLayoutBuilder()
1584 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1585 .build(vk, device));
1586
1587 const Unique<VkDescriptorPool> descriptorPool(
1588 DescriptorPoolBuilder()
1589 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1590 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1591
1592 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1593 const VkDescriptorBufferInfo resultBufferDescriptorInfo =
1594 makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
1595
1596 DescriptorSetUpdateBuilder()
1597 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1598 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
1599 .update(vk, device);
1600
1601 // Pipeline
1602
1603 const Unique<VkShaderModule> vertexModule(
1604 createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1605 const Unique<VkShaderModule> fragmentModule(
1606 createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1607
1608 const Unique<VkRenderPass> renderPass(makeRenderPass(vk, device, colorFormat, depthStencilFormat));
1609 const Unique<VkFramebuffer> framebuffer(makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages,
1610 attachmentImages, renderSize.x(), renderSize.y()));
1611 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
1612 const Unique<VkPipeline> pipeline(
1613 makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
1614 (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL),
1615 VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));
1616 const Unique<VkCommandPool> cmdPool(
1617 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1618 const Unique<VkCommandBuffer> cmdBuffer(
1619 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1620
1621 // Draw commands
1622
1623 {
1624 const VkRect2D renderArea = {
1625 makeOffset2D(0, 0),
1626 makeExtent2D(renderSize.x(), renderSize.y()),
1627 };
1628 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1629 const VkDeviceSize vertexBufferOffset = 0ull;
1630
1631 beginCommandBuffer(vk, *cmdBuffer);
1632
1633 {
1634 const VkImageMemoryBarrier barriers[] = {
1635 makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1636 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresourceRange),
1637 makeImageMemoryBarrier(0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1638 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *depthStencilImage,
1639 depthStencilSubresourceRange),
1640 makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1641 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *resolveColorImage,
1642 colorSubresourceRange),
1643 makeImageMemoryBarrier(0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1644 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *resolveDepthStencilImage,
1645 depthStencilSubresourceRange),
1646 };
1647
1648 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT,
1649 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
1650 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1651 0u, 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1652 }
1653
1654 // Will clear the attachments with specified depth and stencil values.
1655 {
1656 const VkClearValue clearValues[] = {
1657 makeClearValueColor(clearColor), // attachment 0
1658 makeClearValueDepthStencil(0.5f, 3u), // attachment 1
1659 makeClearValueColor(clearColor), // attachment 2
1660 makeClearValueDepthStencil(0.5f, 3u), // attachment 3
1661 };
1662
1663 const VkRenderPassBeginInfo renderPassBeginInfo = {
1664 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1665 DE_NULL, // const void* pNext;
1666 *renderPass, // VkRenderPass renderPass;
1667 *framebuffer, // VkFramebuffer framebuffer;
1668 renderArea, // VkRect2D renderArea;
1669 DE_LENGTH_OF_ARRAY(clearValues), // uint32_t clearValueCount;
1670 clearValues, // const VkClearValue* pClearValues;
1671 };
1672
1673 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1674 }
1675
1676 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1677 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
1678 &descriptorSet.get(), 0u, DE_NULL);
1679 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1680
1681 // Mask half of the attachment image with value that will pass the stencil test.
1682 if (m_testMode == MODE_STENCIL)
1683 commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0),
1684 makeExtent2D(renderSize.x() / 2, renderSize.y()), 1u);
1685
1686 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
1687 endRenderPass(vk, *cmdBuffer);
1688
1689 copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBuffer, renderSize,
1690 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
1691 VkImageAspectFlags dsAspect =
1692 m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
1693 copyImageToBuffer(vk, *cmdBuffer, *resolveDepthStencilImage, *dsBuffer, renderSize,
1694 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1695 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1u, dsAspect, dsAspect);
1696
1697 endCommandBuffer(vk, *cmdBuffer);
1698 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1699 }
1700
1701 // Verify color output
1702 {
1703 invalidateAlloc(vk, device, *colorBufferAlloc);
1704
1705 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1,
1706 colorBufferAlloc->getHostPtr());
1707 const tcu::TextureLevel referenceImage = generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
1708 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1709 referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f),
1710 tcu::COMPARE_LOG_RESULT))
1711 printf("Rendered color image is not correct");
1712 }
1713
1714 // Verify depth-stencil output
1715 {
1716 invalidateAlloc(vk, device, *dsBufferAlloc);
1717 tcu::TextureFormat format = mapVkFormat(depthStencilFormat);
1718 const tcu::ConstPixelBufferAccess dsPixelAccess(format, renderSize.x(), renderSize.y(), 1,
1719 dsBufferAlloc->getHostPtr());
1720
1721 for (int z = 0; z < dsPixelAccess.getDepth(); z++)
1722 for (int y = 0; y < dsPixelAccess.getHeight(); y++)
1723 for (int x = 0; x < dsPixelAccess.getWidth(); x++)
1724 {
1725 float depthValue = (m_testMode == MODE_DEPTH) ? dsPixelAccess.getPixDepth(x, y, z) : 0.0f;
1726 int stencilValue = (m_testMode == MODE_STENCIL) ? dsPixelAccess.getPixStencil(x, y, z) : 0;
1727
1728 // Depth test should write to the depth buffer even when there is a discard in the fragment shader,
1729 // when early fragment tests are enabled.
1730 if (m_testMode == MODE_DEPTH)
1731 {
1732 if (m_useEarlyTests && ((x + y) < 31) && depthValue >= 0.5f)
1733 {
1734 std::ostringstream error;
1735 error << "Rendered depth value [ " << x << ", " << y << ", " << z
1736 << "] is not correct: " << depthValue << " >= 0.5f";
1737 TCU_FAIL(error.str().c_str());
1738 }
1739 // When early fragment tests are disabled, the depth test happens after the fragment shader, but as we are discarding
1740 // all fragments, the stored value in the depth buffer should be the clear one (0.5f).
1741 if (!m_useEarlyTests && deAbs(depthValue - 0.5f) > 0.01f)
1742 {
1743 std::ostringstream error;
1744 error << "Rendered depth value [ " << x << ", " << y << ", " << z
1745 << "] is not correct: " << depthValue << " != 0.5f";
1746 TCU_FAIL(error.str().c_str());
1747 }
1748 }
1749
1750 if (m_testMode == MODE_STENCIL)
1751 {
1752 if (m_useEarlyTests && ((x < 16 && stencilValue != 2u) || (x >= 16 && stencilValue != 4u)))
1753 {
1754 std::ostringstream error;
1755 error << "Rendered stencil value [ " << x << ", " << y << ", " << z
1756 << "] is not correct: " << stencilValue << " != ";
1757 error << (x < 16 ? 2u : 4u);
1758 TCU_FAIL(error.str().c_str());
1759 }
1760
1761 if (!m_useEarlyTests && ((x < 16 && stencilValue != 1u) || (x >= 16 && stencilValue != 3u)))
1762 {
1763 std::ostringstream error;
1764 error << "Rendered stencil value [ " << x << ", " << y << ", " << z
1765 << "] is not correct: " << stencilValue << " != ";
1766 error << (x < 16 ? 1u : 3u);
1767 TCU_FAIL(error.str().c_str());
1768 }
1769 }
1770 }
1771 }
1772
1773 // Verify we process all the fragments
1774 {
1775 invalidateAlloc(vk, device, *resultBufferAlloc);
1776
1777 const int actualCounter = *static_cast<int32_t *>(resultBufferAlloc->getHostPtr());
1778 const bool expectPartialResult = m_useEarlyTests;
1779 const int expectedCounter =
1780 expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
1781 const int tolerance = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3 : 0;
1782 const int expectedMin = de::max(0, expectedCounter - tolerance);
1783
1784 tcu::TestLog &log = m_context.getTestContext().getLog();
1785 log << tcu::TestLog::Message << "Minimum expected value: " + de::toString(expectedMin)
1786 << tcu::TestLog::EndMessage;
1787 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
1788
1789 if (expectedMin <= actualCounter)
1790 return tcu::TestStatus::pass("Success");
1791 else
1792 return tcu::TestStatus::fail("Value out of range");
1793 }
1794 }
1795
1796 class EarlyFragmentSampleMaskTest : public EarlyFragmentTest
1797 {
1798 public:
1799 EarlyFragmentSampleMaskTest(tcu::TestContext &testCtx, const std::string name, const uint32_t flags,
1800 const uint32_t sampleCount);
1801
1802 void initPrograms(SourceCollections &programCollection) const override;
1803 TestInstance *createInstance(Context &context) const override;
1804 void checkSupport(Context &context) const override;
1805
1806 private:
1807 const uint32_t m_flags;
1808 const uint32_t m_sampleCount;
1809 };
1810
EarlyFragmentSampleMaskTest(tcu::TestContext & testCtx,const std::string name,const uint32_t flags,const uint32_t sampleCount)1811 EarlyFragmentSampleMaskTest::EarlyFragmentSampleMaskTest(tcu::TestContext &testCtx, const std::string name,
1812 const uint32_t flags, const uint32_t sampleCount)
1813 : EarlyFragmentTest(testCtx, name, flags)
1814 , m_flags(flags)
1815 , m_sampleCount(sampleCount)
1816 {
1817 }
1818
createInstance(Context & context) const1819 TestInstance *EarlyFragmentSampleMaskTest::createInstance(Context &context) const
1820 {
1821 return new EarlyFragmentSampleMaskTestInstance(context, m_flags, m_sampleCount);
1822 }
1823
initPrograms(SourceCollections & programCollection) const1824 void EarlyFragmentSampleMaskTest::initPrograms(SourceCollections &programCollection) const
1825 {
1826 // Vertex
1827 {
1828 std::ostringstream src;
1829 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1830 << "\n"
1831 << "layout(location = 0) in highp vec4 position;\n"
1832 << "\n"
1833 << "out gl_PerVertex {\n"
1834 << " vec4 gl_Position;\n"
1835 << "};\n"
1836 << "\n"
1837 << "void main (void)\n"
1838 << "{\n"
1839 << " gl_Position = position;\n"
1840 << "}\n";
1841
1842 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1843 }
1844
1845 // Fragment
1846 {
1847 if ((m_flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == 0)
1848 {
1849 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
1850 std::ostringstream src;
1851 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1852 << "\n"
1853 << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
1854 << "layout(location = 0) out highp vec4 fragColor;\n"
1855 << "\n"
1856 << "layout(binding = 0) coherent buffer Output {\n"
1857 << " uint result;\n"
1858 << "} sb_out;\n"
1859 << "\n"
1860 << "void main (void)\n"
1861 << "{\n"
1862 << " atomicAdd(sb_out.result, 1u);\n"
1863 << " gl_SampleMask[0] = 0x0;\n"
1864 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
1865 << " discard;\n"
1866 << "}\n";
1867
1868 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1869 }
1870 else
1871 {
1872 const SpirVAsmBuildOptions buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
1873 const std::string option = (((m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) != 0) ?
1874 "OpExecutionMode %4 DepthReplacing\nOpExecutionMode %4 DepthGreater\n" :
1875 "");
1876 const std::string src = "; SPIR - V\n"
1877 "; Version: 1.0\n"
1878 "; Generator: Khronos Glslang Reference Front End; 10\n"
1879 "; Bound: 30\n"
1880 "; Schema: 0\n"
1881 "OpCapability Shader\n"
1882 "OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
1883 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
1884 "OpMemoryModel Logical GLSL450\n"
1885 "OpEntryPoint Fragment %4 \"main\" %19 %25\n"
1886 "OpExecutionMode %4 OriginUpperLeft\n"
1887 "OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n" +
1888 option +
1889 "OpMemberDecorate %7 0 Coherent\n"
1890 "OpMemberDecorate %7 0 Offset 0\n"
1891 "OpDecorate %7 BufferBlock\n"
1892 "OpDecorate %9 DescriptorSet 0\n"
1893 "OpDecorate %9 Binding 0\n"
1894 "OpDecorate %19 BuiltIn SampleMask\n"
1895 "OpDecorate %25 Location 0\n"
1896 "%2 = OpTypeVoid\n"
1897 "%3 = OpTypeFunction %2\n"
1898 "%6 = OpTypeInt 32 0\n"
1899 "%7 = OpTypeStruct %6\n"
1900 "%8 = OpTypePointer Uniform %7\n"
1901 "%9 = OpVariable %8 Uniform\n"
1902 "%10 = OpTypeInt 32 1\n"
1903 "%11 = OpConstant %10 0\n"
1904 "%12 = OpTypePointer Uniform %6\n"
1905 "%14 = OpConstant %6 1\n"
1906 "%15 = OpConstant %6 0\n"
1907 "%17 = OpTypeArray %10 %14\n"
1908 "%18 = OpTypePointer Output %17\n"
1909 "%19 = OpVariable %18 Output\n"
1910 "%20 = OpTypePointer Output %10\n"
1911 "%22 = OpTypeFloat 32\n"
1912 "%23 = OpTypeVector %22 4\n"
1913 "%24 = OpTypePointer Output %23\n"
1914 "%25 = OpVariable %24 Output\n"
1915 "%26 = OpConstant %22 1\n"
1916 "%27 = OpConstant %22 0\n"
1917 "%28 = OpConstantComposite %23 %26 %26 %27 %26\n"
1918 "%4 = OpFunction %2 None %3\n"
1919 "%5 = OpLabel\n"
1920 "%13 = OpAccessChain %12 %9 %11\n"
1921 "%16 = OpAtomicIAdd %6 %13 %14 %15 %14\n"
1922 "%21 = OpAccessChain %20 %19 %11\n"
1923 "OpStore %21 %11\n"
1924 "OpStore %25 %28\n"
1925 "OpKill\n"
1926 "OpFunctionEnd\n";
1927 programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
1928 }
1929 }
1930 }
1931
checkSupport(Context & context) const1932 void EarlyFragmentSampleMaskTest::checkSupport(Context &context) const
1933 {
1934 EarlyFragmentTest::checkSupport(context);
1935
1936 context.requireDeviceFunctionality("VK_KHR_depth_stencil_resolve");
1937 }
1938
1939 struct SampleCountTestParams
1940 {
1941 uint32_t sampleCount;
1942 bool earlyAndLate;
1943 bool alphaToCoverage;
1944 bool useMaintenance5;
1945 };
1946
1947 class EarlyFragmentSampleCountTestInstance : public EarlyFragmentTestInstance
1948 {
1949 public:
1950 EarlyFragmentSampleCountTestInstance(Context &context, const SampleCountTestParams &testParams);
1951
1952 tcu::TestStatus iterate(void);
1953
1954 private:
1955 tcu::TextureLevel generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize);
1956
1957 Move<VkRenderPass> makeRenderPass(const DeviceInterface &vk, const VkDevice device, const VkFormat colorFormat,
1958 const VkFormat depthStencilFormat);
1959
1960 Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface &vk, const VkDevice device,
1961 const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass,
1962 const VkShaderModule vertexModule, const VkShaderModule fragmentModule,
1963 const tcu::IVec2 &renderSize, const VkSampleMask sampleMask);
1964
1965 const SampleCountTestParams m_testParams;
1966 };
1967
EarlyFragmentSampleCountTestInstance(Context & context,const SampleCountTestParams & testParams)1968 EarlyFragmentSampleCountTestInstance::EarlyFragmentSampleCountTestInstance(Context &context,
1969 const SampleCountTestParams &testParams)
1970 : EarlyFragmentTestInstance(context, FLAG_TEST_DEPTH)
1971 , m_testParams(testParams)
1972 {
1973 }
1974
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & renderSize,const VkSampleMask sampleMask)1975 Move<VkPipeline> EarlyFragmentSampleCountTestInstance::makeGraphicsPipeline(
1976 const DeviceInterface &vk, const VkDevice device, const VkPipelineLayout pipelineLayout,
1977 const VkRenderPass renderPass, const VkShaderModule vertexModule, const VkShaderModule fragmentModule,
1978 const tcu::IVec2 &renderSize, const VkSampleMask sampleMask)
1979 {
1980 const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
1981 const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
1982
1983 const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
1984 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
1985 DE_NULL, // const void* pNext
1986 0u, // VkPipelineDepthStencilStateCreateFlags flags
1987 VK_TRUE, // VkBool32 depthTestEnable
1988 VK_TRUE, // VkBool32 depthWriteEnable
1989 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp
1990 VK_FALSE, // VkBool32 depthBoundsTestEnable
1991 VK_FALSE, // VkBool32 stencilTestEnable
1992 {}, // VkStencilOpState front
1993 {}, // VkStencilOpState back
1994 0.0f, // float minDepthBounds
1995 1.0f // float maxDepthBounds
1996 };
1997
1998 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
1999 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType
2000 DE_NULL, // const void* pNext
2001 0u, // VkPipelineMultisampleStateCreateFlags flags
2002 (VkSampleCountFlagBits)
2003 m_testParams.sampleCount, // VkSampleCountFlagBits rasterizationSamples
2004 false, // VkBool32 sampleShadingEnable
2005 0.0f, // float minSampleShading
2006 &sampleMask, // const VkSampleMask* pSampleMask
2007 m_testParams.alphaToCoverage, // VkBool32 alphaToCoverageEnable
2008 false, // VkBool32 alphaToOneEnable
2009 };
2010
2011 return vk::makeGraphicsPipeline(
2012 vk, // const DeviceInterface& vk
2013 device, // const VkDevice device
2014 pipelineLayout, // const VkPipelineLayout pipelineLayout
2015 vertexModule, // const VkShaderModule vertexShaderModule
2016 DE_NULL, // const VkShaderModule tessellationControlModule
2017 DE_NULL, // const VkShaderModule tessellationEvalModule
2018 DE_NULL, // const VkShaderModule geometryShaderModule
2019 fragmentModule, // const VkShaderModule fragmentShaderModule
2020 renderPass, // const VkRenderPass renderPass
2021 viewports, // const std::vector<VkViewport>& viewports
2022 scissors, // const std::vector<VkRect2D>& scissors
2023 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
2024 0u, // const uint32_t subpass
2025 0u, // const uint32_t patchControlPoints
2026 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
2027 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
2028 &multisampleStateCreateInfo, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
2029 &depthStencilStateCreateInfo); // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
2030 }
2031
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat depthStencilFormat)2032 Move<VkRenderPass> EarlyFragmentSampleCountTestInstance::makeRenderPass(const DeviceInterface &vk,
2033 const VkDevice device,
2034 const VkFormat colorFormat,
2035 const VkFormat depthStencilFormat)
2036 {
2037 const VkAttachmentDescription colorAttachmentDescription = {
2038 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
2039 colorFormat, // VkFormat format;
2040 (VkSampleCountFlagBits)m_testParams.sampleCount, // VkSampleCountFlagBits samples;
2041 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
2042 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
2043 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
2044 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
2045 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
2046 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
2047 };
2048
2049 const VkAttachmentDescription depthStencilAttachmentDescription = {
2050 (VkAttachmentDescriptionFlags)0, // VkStructureType sType;
2051 depthStencilFormat, // VkFormat format
2052 (VkSampleCountFlagBits)m_testParams.sampleCount, // VkSampleCountFlagBits samples
2053 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
2054 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
2055 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp
2056 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp
2057 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
2058 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
2059 };
2060
2061 const VkAttachmentDescription resolveAttachmentDescription = {
2062
2063 (VkAttachmentDescriptionFlags)0, // VkSubpassDescriptionFlags flags
2064 colorFormat, // VkFormat format
2065 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
2066 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
2067 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
2068 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
2069 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
2070 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
2071 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
2072 };
2073
2074 std::vector<VkAttachmentDescription> attachmentDescriptions;
2075
2076 attachmentDescriptions.push_back(colorAttachmentDescription);
2077 attachmentDescriptions.push_back(depthStencilAttachmentDescription);
2078 attachmentDescriptions.push_back(resolveAttachmentDescription);
2079
2080 const VkAttachmentReference colorAttachmentRef = {
2081 0u, // uint32_t attachment
2082 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
2083 };
2084
2085 const VkAttachmentReference depthStencilAttachmentRef = {
2086 1u, // uint32_t attachment
2087 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout layout
2088 };
2089
2090 const VkAttachmentReference resolveAttachmentRef = {
2091 2u, // uint32_t attachment
2092 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
2093 };
2094
2095 const VkSubpassDescription subpassDescription = {
2096 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
2097 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
2098 0u, // uint32_t inputAttachmentCount
2099 DE_NULL, // const VkAttachmentReference2* pInputAttachments
2100 1u, // uint32_t colorAttachmentCount
2101 &colorAttachmentRef, // const VkAttachmentReference2* pColorAttachments
2102 &resolveAttachmentRef, // const VkAttachmentReference2* pResolveAttachments
2103 &depthStencilAttachmentRef, // const VkAttachmentReference2* pDepthStencilAttachment
2104 0u, // uint32_t preserveAttachmentCount
2105 DE_NULL // const uint32_t* pPreserveAttachments
2106 };
2107
2108 const VkRenderPassCreateInfo renderPassInfo = {
2109 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
2110 DE_NULL, // const void* pNext;
2111 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
2112 (uint32_t)attachmentDescriptions.size(), // uint32_t attachmentCount;
2113 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments;
2114 1u, // uint32_t subpassCount;
2115 &subpassDescription, // const VkSubpassDescription* pSubpasses;
2116 0u, // uint32_t dependencyCount;
2117 DE_NULL // const VkSubpassDependency* pDependencies;
2118 };
2119
2120 return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
2121 }
2122
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)2123 tcu::TextureLevel EarlyFragmentSampleCountTestInstance::generateReferenceColorImage(const tcu::TextureFormat format,
2124 const tcu::IVec2 &renderSize)
2125 {
2126 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
2127 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
2128
2129 tcu::clear(image.getAccess(), clearColor);
2130
2131 return image;
2132 }
2133
iterate(void)2134 tcu::TestStatus EarlyFragmentSampleCountTestInstance::iterate(void)
2135 {
2136 const DeviceInterface &vk = m_context.getDeviceInterface();
2137 const VkDevice device = m_context.getDevice();
2138 const VkQueue queue = m_context.getUniversalQueue();
2139 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2140 Allocator &allocator = m_context.getDefaultAllocator();
2141 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
2142 const VkFormat depthFormat = VK_FORMAT_D16_UNORM;
2143 VkQueryPool queryPool;
2144 const uint32_t queryCount = 2u;
2145 std::vector<VkDeviceSize> sampleCounts(queryCount);
2146
2147 // Create a query pool for storing the occlusion query result
2148 {
2149 VkQueryPoolCreateInfo queryPoolInfo{
2150 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType;
2151 DE_NULL, // const void* pNext;
2152 (VkQueryPoolCreateFlags)0, // VkQueryPoolCreateFlags flags;
2153 VK_QUERY_TYPE_OCCLUSION, // VkQueryType queryType;
2154 queryCount, // uint32_t queryCount;
2155 0u, // VkQueryPipelineStatisticFlags pipelineStatistics;
2156 };
2157
2158 VK_CHECK(vk.createQueryPool(device, &queryPoolInfo, NULL, &queryPool));
2159 }
2160
2161 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth format "
2162 << getFormatName(VK_FORMAT_D16_UNORM) << tcu::TestLog::EndMessage;
2163
2164 // Color attachment
2165 const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
2166 const VkImageSubresourceRange colorSubresourceRange =
2167 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2168
2169 const VkImageCreateInfo imageParams = {
2170 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2171 DE_NULL, // const void* pNext;
2172 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
2173 VK_IMAGE_TYPE_2D, // VkImageType imageType;
2174 colorFormat, // VkFormat format;
2175 makeExtent3D(renderSize.x(), renderSize.y(), 1), // VkExtent3D extent;
2176 1u, // uint32_t mipLevels;
2177 1u, // uint32_t arrayLayers;
2178 (VkSampleCountFlagBits)m_testParams.sampleCount, // VkSampleCountFlagBits samples;
2179 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
2180 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags usage;
2181 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
2182 0u, // uint32_t queueFamilyIndexCount;
2183 DE_NULL, // const uint32_t* pQueueFamilyIndices;
2184 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
2185 };
2186
2187 const Unique<VkImage> colorImage(makeImage(vk, device, imageParams));
2188 const UniquePtr<Allocation> colorImageAlloc(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
2189 const Unique<VkImageView> colorImageView(
2190 makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
2191
2192 const Unique<VkImage> resolveColorImage(
2193 makeImage(vk, device,
2194 makeImageCreateInfo(renderSize, colorFormat,
2195 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
2196 const UniquePtr<Allocation> resolveColorImageAlloc(
2197 bindImage(vk, device, allocator, *resolveColorImage, MemoryRequirement::Any));
2198 const Unique<VkImageView> resolveColorImageView(
2199 makeImageView(vk, device, *resolveColorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
2200
2201 // Depth-Stencil attachment
2202 const VkImageSubresourceRange depthSubresourceRange =
2203 makeImageSubresourceRange(getImageAspectFlags(depthFormat), 0u, 1u, 0u, 1u);
2204
2205 const VkImageCreateInfo depthImageParams = {
2206 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2207 DE_NULL, // const void* pNext;
2208 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
2209 VK_IMAGE_TYPE_2D, // VkImageType imageType;
2210 depthFormat, // VkFormat format;
2211 makeExtent3D(renderSize.x(), renderSize.y(), 1), // VkExtent3D extent;
2212 1u, // uint32_t mipLevels;
2213 1u, // uint32_t arrayLayers;
2214 (VkSampleCountFlagBits)m_testParams.sampleCount, // VkSampleCountFlagBits samples;
2215 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
2216 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, // VkImageUsageFlags usage;
2217 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
2218 0u, // uint32_t queueFamilyIndexCount;
2219 DE_NULL, // const uint32_t* pQueueFamilyIndices;
2220 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
2221 };
2222
2223 const Unique<VkImage> depthImage(makeImage(vk, device, depthImageParams));
2224 const UniquePtr<Allocation> depthImageAlloc(bindImage(vk, device, allocator, *depthImage, MemoryRequirement::Any));
2225 const Unique<VkImageView> depthImageView(
2226 makeImageView(vk, device, *depthImage, VK_IMAGE_VIEW_TYPE_2D, depthFormat, depthSubresourceRange));
2227
2228 const VkImageView attachmentImages[] = {*colorImageView, *depthImageView, *resolveColorImageView};
2229 const uint32_t numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
2230
2231 // Vertex buffer
2232 const uint32_t numVertices = 6u;
2233 const VkDeviceSize vertexBufferSizeBytes = 256 * numVertices;
2234 const Unique<VkBuffer> vertexBuffer(
2235 makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
2236 const UniquePtr<Allocation> vertexBufferAlloc(
2237 bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
2238
2239 {
2240 tcu::Vec4 *const pVertices = reinterpret_cast<tcu::Vec4 *>(vertexBufferAlloc->getHostPtr());
2241
2242 pVertices[0] = tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f);
2243 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
2244 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f);
2245
2246 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f);
2247 pVertices[4] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
2248 pVertices[5] = tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f);
2249
2250 flushAlloc(vk, device, *vertexBufferAlloc);
2251 // No barrier needed, flushed memory is automatically visible
2252 }
2253
2254 // Render result buffer (to retrieve color attachment contents)
2255
2256 const VkDeviceSize colorBufferSizeBytes =
2257 tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
2258 const Unique<VkBuffer> colorBufferNoEarlyResults(
2259 makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2260 const UniquePtr<Allocation> colorBufferAllocNoEarly(
2261 bindBuffer(vk, device, allocator, *colorBufferNoEarlyResults, MemoryRequirement::HostVisible));
2262 const Unique<VkBuffer> colorBufferEarlyResults(
2263 makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2264 const UniquePtr<Allocation> colorBufferAllocEarly(
2265 bindBuffer(vk, device, allocator, *colorBufferEarlyResults, MemoryRequirement::HostVisible));
2266
2267 // Pipeline
2268
2269 const Unique<VkShaderModule> vertexModule(
2270 createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2271 const Unique<VkShaderModule> fragmentModuleNoEarly(
2272 createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
2273 const Unique<VkShaderModule> fragmentModuleEarlyFrag(
2274 createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_early"), 0u));
2275
2276 const Unique<VkRenderPass> renderPass(makeRenderPass(vk, device, colorFormat, depthFormat));
2277
2278 const Unique<VkFramebuffer> framebuffer(makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages,
2279 attachmentImages, renderSize.x(), renderSize.y()));
2280
2281 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, DE_NULL));
2282
2283 // When we are creating a pipeline for runs without early fragment test, we are enabling all the samples for full coverage.
2284 // Sample mask will be modified in a fragment shader.
2285 const Unique<VkPipeline> pipelineNoEarlyFrag(makeGraphicsPipeline(
2286 vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModuleNoEarly, renderSize, 0xFFFFFFFF));
2287
2288 // For early fragment tests, we are enabling only half of the samples.
2289 const Unique<VkPipeline> pipelineEarlyFrag(makeGraphicsPipeline(
2290 vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModuleEarlyFrag, renderSize, 0xAAAAAAAA));
2291
2292 // Build a command buffer
2293
2294 const Unique<VkCommandPool> cmdPool(
2295 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2296 const Unique<VkCommandBuffer> cmdBuffer(
2297 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2298
2299 enum QueryIndex
2300 {
2301 QUERY_INDEX_NO_EARLY_FRAG = 0,
2302 QUERY_INDEX_EARLY_FRAG = 1
2303 };
2304
2305 {
2306 const VkRect2D renderArea = {
2307 makeOffset2D(0, 0),
2308 makeExtent2D(renderSize.x(), renderSize.y()),
2309 };
2310
2311 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
2312 const VkDeviceSize vertexBufferOffset = 0ull;
2313
2314 beginCommandBuffer(vk, *cmdBuffer);
2315
2316 // transition images to proper layouts - this cant be done with renderpass as we will use same renderpass twice
2317 const VkImageMemoryBarrier initialImageBarriers[]{
2318 makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2319 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresourceRange),
2320 makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2321 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *resolveColorImage, colorSubresourceRange),
2322 makeImageMemoryBarrier(0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2323 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *depthImage,
2324 depthSubresourceRange)};
2325 vk.cmdPipelineBarrier(*cmdBuffer, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u,
2326 DE_NULL, 2u, initialImageBarriers);
2327 vk.cmdPipelineBarrier(*cmdBuffer, 0, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
2328 1u, &initialImageBarriers[2]);
2329
2330 const VkClearValue clearValues[] = {
2331 makeClearValueColor(clearColor), // attachment 0
2332 makeClearValueDepthStencil(0.5f, 3u), // attachment 1
2333 makeClearValueColor(clearColor), // attachment 2
2334 makeClearValueDepthStencil(0.5f, 3u), // attachment 3
2335 };
2336
2337 const VkRenderPassBeginInfo renderPassBeginInfo = {
2338 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
2339 DE_NULL, // const void* pNext;
2340 *renderPass, // VkRenderPass renderPass;
2341 *framebuffer, // VkFramebuffer framebuffer;
2342 renderArea, // VkRect2D renderArea;
2343 DE_LENGTH_OF_ARRAY(clearValues), // uint32_t clearValueCount;
2344 clearValues, // const VkClearValue* pClearValues;
2345 };
2346
2347 // Reset query pool. Must be done outside of render pass
2348 vk.cmdResetQueryPool(*cmdBuffer, queryPool, 0, queryCount);
2349
2350 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2351
2352 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2353
2354 // Run without early fragment test.
2355 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineNoEarlyFrag);
2356
2357 vk.cmdBeginQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_NO_EARLY_FRAG, VK_QUERY_CONTROL_PRECISE_BIT);
2358 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
2359 vk.cmdEndQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_NO_EARLY_FRAG);
2360
2361 endRenderPass(vk, *cmdBuffer);
2362
2363 copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBufferNoEarlyResults, renderSize,
2364 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
2365
2366 // after copying from resolved image we need to switch its layout back to color attachment optimal
2367 const VkImageMemoryBarrier postResolveImageBarrier = makeImageMemoryBarrier(
2368 VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2369 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *resolveColorImage, colorSubresourceRange);
2370 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2371 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &postResolveImageBarrier);
2372
2373 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2374
2375 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2376
2377 // Run with early fragment test.
2378 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineEarlyFrag);
2379
2380 vk.cmdBeginQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_EARLY_FRAG, VK_QUERY_CONTROL_PRECISE_BIT);
2381 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
2382 vk.cmdEndQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_EARLY_FRAG);
2383
2384 endRenderPass(vk, *cmdBuffer);
2385
2386 copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBufferEarlyResults, renderSize,
2387 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
2388
2389 endCommandBuffer(vk, *cmdBuffer);
2390 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2391 }
2392
2393 // When early fragment test is enabled, all samples are killed in fragment shader. The result color should be black.
2394 {
2395 invalidateAlloc(vk, device, *colorBufferAllocEarly);
2396
2397 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1,
2398 colorBufferAllocEarly->getHostPtr());
2399 const tcu::TextureLevel referenceImage = generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
2400
2401 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare color output",
2402 "Early fragment image result comparison", referenceImage.getAccess(),
2403 imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
2404 return tcu::TestStatus::fail("Rendered color image is not correct");
2405 }
2406
2407 // The image has 32x32 pixels and each pixel has m_sampleCount samples. Half of these samples are discarded before sample counting.
2408 // This means the reference value for passed samples is ((32 x 32) / 2 / 2) * sampleCount.
2409 {
2410 uint64_t refValue = uint64_t(uint32_t((renderSize.x() * renderSize.y()) / 4) * m_testParams.sampleCount);
2411 uint64_t tolerance = uint64_t(refValue * 5 / 100);
2412 uint64_t minValue = refValue - tolerance;
2413 uint64_t maxValue = refValue + tolerance;
2414
2415 VK_CHECK(vk.getQueryPoolResults(device, queryPool, 0u, queryCount, queryCount * sizeof(VkDeviceSize),
2416 sampleCounts.data(), sizeof(VkDeviceSize),
2417 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
2418
2419 // Log test results
2420 {
2421 tcu::TestLog &log = m_context.getTestContext().getLog();
2422
2423 log << tcu::TestLog::Message << "\nAcceptable range: " << minValue << " - " << maxValue
2424 << tcu::TestLog::EndMessage;
2425 log << tcu::TestLog::Message
2426 << "Passed Samples (without early fragment test) : " << de::toString(sampleCounts[0])
2427 << tcu::TestLog::EndMessage;
2428 log << tcu::TestLog::Message
2429 << "Passed Samples (with early fragment test) : " << de::toString(sampleCounts[1])
2430 << tcu::TestLog::EndMessage;
2431 }
2432
2433 #ifndef CTS_USES_VULKANSC
2434 vk.destroyQueryPool(device, queryPool, nullptr);
2435 #endif // CTS_USES_VULKANSC
2436
2437 // Check that number of the all passed samples are within an acceptable range.
2438 if (sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] >= minValue &&
2439 sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] <= maxValue && sampleCounts[QUERY_INDEX_EARLY_FRAG] >= minValue &&
2440 sampleCounts[QUERY_INDEX_EARLY_FRAG] <= maxValue)
2441 {
2442 return tcu::TestStatus::pass("Success");
2443 }
2444 else if (sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] >= minValue &&
2445 sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] <= maxValue && sampleCounts[QUERY_INDEX_EARLY_FRAG] == 0)
2446 {
2447 #ifndef CTS_USES_VULKANSC
2448 if (m_testParams.useMaintenance5)
2449 {
2450 if (m_context.getMaintenance5Properties().earlyFragmentMultisampleCoverageAfterSampleCounting)
2451 return tcu::TestStatus::fail("Fail");
2452 return tcu::TestStatus::pass("Pass");
2453 }
2454 #endif
2455 // Spec says: "If the fragment shader declares the EarlyFragmentTests execution mode, fragment shading and
2456 // multisample coverage operations should instead be performed after sample counting.
2457
2458 // since the specification says 'should', the opposite behavior is allowed, but not preferred
2459 return tcu::TestStatus(
2460 QP_TEST_RESULT_QUALITY_WARNING,
2461 "Sample count is 0 - sample counting performed after multisample coverage and fragment shading");
2462 }
2463 else if (sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] >= minValue &&
2464 sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] <= maxValue &&
2465 sampleCounts[QUERY_INDEX_EARLY_FRAG] >= (minValue * 2) &&
2466 sampleCounts[QUERY_INDEX_EARLY_FRAG] <= (maxValue * 2))
2467 {
2468 // If the sample count returned is double the expected value, the sample mask test has been executed after
2469 // sample counting.
2470
2471 #ifndef CTS_USES_VULKANSC
2472 if (m_testParams.useMaintenance5)
2473 {
2474 if (m_context.getMaintenance5Properties().earlyFragmentSampleMaskTestBeforeSampleCounting)
2475 return tcu::TestStatus::fail("Fail");
2476 return tcu::TestStatus::pass("Pass");
2477 }
2478 #endif
2479 // Spec says: "If there is a fragment shader and it declares the EarlyFragmentTests execution mode, ...
2480 // sample mask test may: instead be performed after sample counting"
2481
2482 // since the specification says 'may', the opposite behavior is allowed, but not preferred
2483 return tcu::TestStatus(
2484 QP_TEST_RESULT_QUALITY_WARNING,
2485 "Sample count is greater than expected - sample mask test performed after sample counting");
2486 }
2487 else
2488 {
2489 // Log no early frag test images
2490 {
2491 tcu::TestLog &log = m_context.getTestContext().getLog();
2492
2493 invalidateAlloc(vk, device, *colorBufferAllocNoEarly);
2494
2495 const tcu::ConstPixelBufferAccess imagePixelAccess(
2496 mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAllocNoEarly->getHostPtr());
2497
2498 log << tcu::LogImageSet("No Early Frag Test Images", "No Early Fragment Test Images")
2499 << tcu::TestLog::Image("color", "Rendered image (color)", imagePixelAccess)
2500 << tcu::TestLog::EndImageSet;
2501 }
2502
2503 // Log early frag test images
2504 {
2505 tcu::TestLog &log = m_context.getTestContext().getLog();
2506
2507 invalidateAlloc(vk, device, *colorBufferAllocEarly);
2508
2509 const tcu::ConstPixelBufferAccess imagePixelAccess(
2510 mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAllocEarly->getHostPtr());
2511
2512 log << tcu::LogImageSet("Early Frag Test Images", "Early Fragment Test Images")
2513 << tcu::TestLog::Image("color", "Rendered image (color)", imagePixelAccess)
2514 << tcu::TestLog::EndImageSet;
2515 }
2516
2517 return tcu::TestStatus::fail("Sample count value outside expected range.");
2518 }
2519 }
2520 }
2521
2522 class EarlyFragmentSampleCountTest : public EarlyFragmentTest
2523 {
2524 public:
2525 EarlyFragmentSampleCountTest(tcu::TestContext &testCtx, const std::string name,
2526 const SampleCountTestParams &testParams);
2527
2528 void initPrograms(SourceCollections &programCollection) const override;
2529 TestInstance *createInstance(Context &context) const override;
2530 void checkSupport(Context &context) const override;
2531
2532 private:
2533 const SampleCountTestParams m_testParams;
2534 };
2535
EarlyFragmentSampleCountTest(tcu::TestContext & testCtx,const std::string name,const SampleCountTestParams & testParams)2536 EarlyFragmentSampleCountTest::EarlyFragmentSampleCountTest(tcu::TestContext &testCtx, const std::string name,
2537 const SampleCountTestParams &testParams)
2538 : EarlyFragmentTest(testCtx, name, FLAG_TEST_DEPTH)
2539 , m_testParams(testParams)
2540 {
2541 }
2542
createInstance(Context & context) const2543 TestInstance *EarlyFragmentSampleCountTest::createInstance(Context &context) const
2544 {
2545 return new EarlyFragmentSampleCountTestInstance(context, m_testParams);
2546 }
2547
initPrograms(SourceCollections & programCollection) const2548 void EarlyFragmentSampleCountTest::initPrograms(SourceCollections &programCollection) const
2549 {
2550 // Vertex shader
2551 {
2552 std::ostringstream vrt;
2553
2554 vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2555 << "\n"
2556 << "layout(location = 0) in highp vec4 position;\n"
2557 << "\n"
2558 << "out gl_PerVertex {\n"
2559 << " vec4 gl_Position;\n"
2560 << "};\n"
2561 << "\n"
2562 << "void main (void)\n"
2563 << "{\n"
2564 << " gl_Position = position;\n"
2565 << "}\n";
2566
2567 programCollection.glslSources.add("vert") << glu::VertexSource(vrt.str());
2568 }
2569
2570 // Fragment shader for runs without early fragment test
2571 if (m_testParams.earlyAndLate == false)
2572 {
2573 std::ostringstream frg;
2574
2575 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2576 << "\n"
2577 << "layout(location = 0) out highp vec4 fragColor;\n"
2578 << "\n"
2579 << "void main (void)\n"
2580 << "{\n"
2581 << " // This will kill half of the samples.\n"
2582 << " gl_SampleMask[0] = 0xAAAAAAAA;\n"
2583 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
2584 << "}\n";
2585
2586 programCollection.glslSources.add("frag") << glu::FragmentSource(frg.str());
2587 }
2588 else
2589 {
2590 const SpirVAsmBuildOptions buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
2591 const std::string src = "; SPIR - V\n"
2592 "; Version: 1.0\n"
2593 "; Generator: Khronos Glslang Reference Front End; 10\n"
2594 "; Bound: 23\n"
2595 "; Schema: 0\n"
2596 "OpCapability Shader\n"
2597 "OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
2598 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
2599 "OpMemoryModel Logical GLSL450\n"
2600 "OpEntryPoint Fragment %4 \"main\" %11 %19\n"
2601 "OpExecutionMode %4 OriginUpperLeft\n"
2602 "OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
2603 "OpExecutionMode %4 DepthReplacing\n"
2604 "OpExecutionMode %4 DepthLess\n"
2605 "OpDecorate %11 BuiltIn SampleMask\n"
2606 "OpDecorate %19 Location 0\n"
2607 "%2 = OpTypeVoid\n"
2608 "%3 = OpTypeFunction %2\n"
2609 "%6 = OpTypeInt 32 1\n"
2610 "%7 = OpTypeInt 32 0\n"
2611 "%8 = OpConstant %7 1\n"
2612 "%9 = OpTypeArray %6 %8\n"
2613 "%10 = OpTypePointer Output %9\n"
2614 "%11 = OpVariable %10 Output\n"
2615 "%12 = OpConstant %6 0\n"
2616 "%13 = OpConstant %6 -1431655766\n"
2617 "%14 = OpTypePointer Output %6\n"
2618 "%16 = OpTypeFloat 32\n"
2619 "%17 = OpTypeVector %16 4\n"
2620 "%18 = OpTypePointer Output %17\n"
2621 "%19 = OpVariable %18 Output\n"
2622 "%20 = OpConstant %16 1\n"
2623 "%21 = OpConstant %16 0\n"
2624 "%22 = OpConstantComposite %17 %20 %20 %21 %20\n"
2625 "%4 = OpFunction %2 None %3\n"
2626 "%5 = OpLabel\n"
2627 "%15 = OpAccessChain %14 %11 %12\n"
2628 "OpStore %15 %13\n"
2629 "OpStore %19 %22\n"
2630 "OpReturn\n"
2631 "OpFunctionEnd\n";
2632 programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
2633 }
2634
2635 // Fragment shader for early fragment tests
2636 if (m_testParams.earlyAndLate == false)
2637 {
2638 std::ostringstream frg;
2639
2640 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2641 << "\n"
2642 << "layout(early_fragment_tests) in;\n"
2643 << "\n"
2644 << "layout(location = 0) out highp vec4 fragColor;\n"
2645 << "\n"
2646 << "void main (void)\n"
2647 << "{\n";
2648
2649 if (m_testParams.alphaToCoverage)
2650 {
2651 frg << " // alphaToCoverageEnable = TRUE and emitting 0 alpha kills all the samples, but the sample "
2652 "counting has already happened.\n"
2653 << " fragColor = vec4(1.0, 1.0, 0.0, 0.0);\n"
2654 << "}\n";
2655 }
2656 else
2657 {
2658 frg << " // Sample mask kills all the samples, but the sample counting has already happened.\n"
2659 << " gl_SampleMask[0] = 0x0;\n"
2660 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
2661 << "}\n";
2662 }
2663
2664 programCollection.glslSources.add("frag_early") << glu::FragmentSource(frg.str());
2665 }
2666 else
2667 {
2668 const SpirVAsmBuildOptions buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
2669 const std::string src = "; SPIR - V\n"
2670 "; Version: 1.0\n"
2671 "; Generator: Khronos Glslang Reference Front End; 10\n"
2672 "; Bound: 22\n"
2673 "; Schema: 0\n"
2674 "OpCapability Shader\n"
2675 "OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
2676 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
2677 "OpMemoryModel Logical GLSL450\n"
2678 "OpEntryPoint Fragment %4 \"main\" %11 %18\n"
2679 "OpExecutionMode %4 OriginUpperLeft\n"
2680 "OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
2681 "OpDecorate %11 BuiltIn SampleMask\n"
2682 "OpDecorate %18 Location 0\n"
2683 "%2 = OpTypeVoid\n"
2684 "%3 = OpTypeFunction %2\n"
2685 "%6 = OpTypeInt 32 1\n"
2686 "%7 = OpTypeInt 32 0\n"
2687 "%8 = OpConstant %7 1\n"
2688 "%9 = OpTypeArray %6 %8\n"
2689 "%10 = OpTypePointer Output %9\n"
2690 "%11 = OpVariable %10 Output\n"
2691 "%12 = OpConstant %6 0\n"
2692 "%13 = OpTypePointer Output %6\n"
2693 "%15 = OpTypeFloat 32\n"
2694 "%16 = OpTypeVector %15 4\n"
2695 "%17 = OpTypePointer Output %16\n"
2696 "%18 = OpVariable %17 Output\n"
2697 "%19 = OpConstant %15 1\n"
2698 "%20 = OpConstant %15 0\n"
2699 "%21 = OpConstantComposite %16 %19 %19 %20 %19\n"
2700 "%4 = OpFunction %2 None %3\n"
2701 "%5 = OpLabel\n"
2702 "%14 = OpAccessChain %13 %11 %12\n"
2703 "OpStore %14 %12\n"
2704 "OpStore %18 %21\n"
2705 "OpReturn\n"
2706 "OpFunctionEnd\n";
2707 programCollection.spirvAsmSources.add("frag_early") << src << buildOptionsSpr;
2708 }
2709 }
2710
checkSupport(Context & context) const2711 void EarlyFragmentSampleCountTest::checkSupport(Context &context) const
2712 {
2713 EarlyFragmentTest::checkSupport(context);
2714
2715 // Check support for MSAA image formats used in the test.
2716 const InstanceInterface &vki = context.getInstanceInterface();
2717 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
2718 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
2719 const VkFormat depthFormat = VK_FORMAT_D16_UNORM;
2720
2721 VkImageFormatProperties formatProperties;
2722
2723 vki.getPhysicalDeviceImageFormatProperties(physDevice, colorFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
2724 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
2725 0u, &formatProperties);
2726 if ((formatProperties.sampleCounts & m_testParams.sampleCount) == 0)
2727 TCU_THROW(NotSupportedError, "Format does not support this number of samples for color format");
2728
2729 vki.getPhysicalDeviceImageFormatProperties(
2730 physDevice, depthFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
2731 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
2732 if ((formatProperties.sampleCounts & m_testParams.sampleCount) == 0)
2733 TCU_THROW(NotSupportedError, "Format does not support this number of samples for depth format");
2734
2735 if (!context.getDeviceFeatures().occlusionQueryPrecise)
2736 TCU_THROW(NotSupportedError, "Precise occlusion queries are not supported");
2737
2738 #ifndef CTS_USES_VULKANSC
2739 if (m_testParams.earlyAndLate)
2740 {
2741 context.requireDeviceFunctionality("VK_AMD_shader_early_and_late_fragment_tests");
2742 if (context.getShaderEarlyAndLateFragmentTestsFeaturesAMD().shaderEarlyAndLateFragmentTests == VK_FALSE)
2743 TCU_THROW(NotSupportedError, "shaderEarlyAndLateFragmentTests is not supported");
2744 }
2745
2746 if (m_testParams.useMaintenance5)
2747 context.requireDeviceFunctionality("VK_KHR_maintenance5");
2748 #endif
2749 }
2750
2751 } // namespace
2752
createEarlyFragmentTests(tcu::TestContext & testCtx)2753 tcu::TestCaseGroup *createEarlyFragmentTests(tcu::TestContext &testCtx)
2754 {
2755 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment"));
2756
2757 {
2758 struct TestCaseEarly
2759 {
2760 std::string caseName;
2761 uint32_t flags;
2762 };
2763
2764 static const TestCaseEarly cases[] = {
2765
2766 {"no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS},
2767 {"no_early_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS},
2768 {"early_fragment_tests_depth", FLAG_TEST_DEPTH},
2769 {"early_fragment_tests_stencil", FLAG_TEST_STENCIL},
2770 {"no_early_fragment_tests_depth_no_attachment",
2771 FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT},
2772 {"no_early_fragment_tests_stencil_no_attachment",
2773 FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT},
2774 {"early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_TEST_ATTACHMENT},
2775 {"early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT},
2776 };
2777
2778 #ifndef CTS_USES_VULKANSC
2779 static const TestCaseEarly casesEarlyAndLate[] = {
2780 {"early_and_late_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2781 {"early_and_late_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2782 {"early_and_late_fragment_tests_depth_no_attachment",
2783 FLAG_TEST_DEPTH | FLAG_DONT_USE_TEST_ATTACHMENT | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2784 {"early_and_late_fragment_tests_stencil_no_attachment",
2785 FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2786 };
2787 #endif
2788
2789 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2790 testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
2791 #ifndef CTS_USES_VULKANSC
2792 for (int i = 0; i < DE_LENGTH_OF_ARRAY(casesEarlyAndLate); ++i)
2793 testGroup->addChild(
2794 new EarlyFragmentTest(testCtx, casesEarlyAndLate[i].caseName, casesEarlyAndLate[i].flags));
2795 #endif
2796 }
2797
2798 // Check that discard does not affect depth test writes.
2799 {
2800 static const struct
2801 {
2802 std::string caseName;
2803 uint32_t flags;
2804 } cases[] = {
2805 {"discard_no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS},
2806 {"discard_no_early_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS},
2807 {"discard_early_fragment_tests_depth", FLAG_TEST_DEPTH},
2808 {"discard_early_fragment_tests_stencil", FLAG_TEST_STENCIL},
2809 #ifndef CTS_USES_VULKANSC
2810 {"discard_early_and_late_fragment_tests_depth",
2811 FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2812 {"discard_early_and_late_fragment_tests_stencil",
2813 FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2814 #endif
2815 };
2816
2817 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2818 testGroup->addChild(new EarlyFragmentDiscardTest(testCtx, cases[i].caseName, cases[i].flags));
2819 }
2820
2821 // Check that writing to gl_SampleMask does not affect depth test writes.
2822 {
2823 static const struct
2824 {
2825 std::string caseName;
2826 uint32_t flags;
2827 } cases[] = {
2828 {"samplemask_no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS},
2829 {"samplemask_early_fragment_tests_depth", FLAG_TEST_DEPTH},
2830 #ifndef CTS_USES_VULKANSC
2831 {"samplemask_early_and_late_fragment_tests_depth_replacing_mode",
2832 FLAG_TEST_DEPTH | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS},
2833 {"samplemask_early_and_late_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2834 #endif
2835 };
2836
2837 const VkSampleCountFlags sampleCounts[] = {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT,
2838 VK_SAMPLE_COUNT_16_BIT};
2839 const std::string sampleCountsStr[] = {"samples_2", "samples_4", "samples_8", "samples_16"};
2840
2841 for (uint32_t sampleCountsNdx = 0; sampleCountsNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountsNdx++)
2842 {
2843 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2844 testGroup->addChild(
2845 new EarlyFragmentSampleMaskTest(testCtx, cases[i].caseName + "_" + sampleCountsStr[sampleCountsNdx],
2846 cases[i].flags, sampleCounts[sampleCountsNdx]));
2847 }
2848 }
2849
2850 // We kill half of the samples at different points in the pipeline depending on early frag test, and then we verify the sample counting works as expected.
2851 {
2852 const VkSampleCountFlags sampleCounts[] = {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT,
2853 VK_SAMPLE_COUNT_16_BIT};
2854 const std::string sampleCountsStr[] = {"samples_2", "samples_4", "samples_8", "samples_16"};
2855
2856 for (uint32_t sampleCountsNdx = 0; sampleCountsNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountsNdx++)
2857 {
2858 SampleCountTestParams params{
2859 sampleCounts[sampleCountsNdx], // uint32_t sampleCount;
2860 false, // bool earlyAndLate;
2861 false, // bool alphaToCoverage;
2862 false, // bool useMaintenance5;
2863 };
2864
2865 testGroup->addChild(new EarlyFragmentSampleCountTest(
2866 testCtx, "sample_count_early_fragment_tests_depth_" + sampleCountsStr[sampleCountsNdx], params));
2867 #ifndef CTS_USES_VULKANSC
2868 params.earlyAndLate = true;
2869 testGroup->addChild(new EarlyFragmentSampleCountTest(
2870 testCtx, "sample_count_early_and_late_fragment_tests_depth_" + sampleCountsStr[sampleCountsNdx],
2871 params));
2872
2873 params.useMaintenance5 = true;
2874 testGroup->addChild(new EarlyFragmentSampleCountTest(testCtx,
2875 "sample_count_early_and_late_fragment_tests_depth_" +
2876 sampleCountsStr[sampleCountsNdx] + "_maintenance5",
2877 params));
2878 params.earlyAndLate = false;
2879 testGroup->addChild(new EarlyFragmentSampleCountTest(testCtx,
2880 "sample_count_early_fragment_tests_depth_" +
2881 sampleCountsStr[sampleCountsNdx] + "_maintenance5",
2882 params));
2883 params.alphaToCoverage = true;
2884 testGroup->addChild(
2885 new EarlyFragmentSampleCountTest(testCtx,
2886 "sample_count_early_fragment_tests_depth_alpha_to_coverage_" +
2887 sampleCountsStr[sampleCountsNdx] + "_maintenance5",
2888 params));
2889 #endif
2890 }
2891 }
2892
2893 return testGroup.release();
2894 }
2895
2896 } // namespace FragmentOperations
2897 } // namespace vkt
2898