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