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 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 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 class EarlyFragmentSampleCountTestInstance : public EarlyFragmentTestInstance
1843 {
1844 public:
1845 EarlyFragmentSampleCountTestInstance (Context& context, const deUint32 sampleCount);
1846
1847 tcu::TestStatus iterate (void);
1848
1849 private:
1850 tcu::TextureLevel generateReferenceColorImage (const tcu::TextureFormat format, const tcu::IVec2& renderSize);
1851
1852 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
1853 const VkDevice device,
1854 const VkFormat colorFormat,
1855 const VkFormat depthStencilFormat);
1856
1857 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
1858 const VkDevice device,
1859 const VkPipelineLayout pipelineLayout,
1860 const VkRenderPass renderPass,
1861 const VkShaderModule vertexModule,
1862 const VkShaderModule fragmentModule,
1863 const tcu::IVec2& renderSize,
1864 const VkSampleMask sampleMask);
1865
1866 const deUint32 m_sampleCount;
1867 };
1868
EarlyFragmentSampleCountTestInstance(Context & context,const deUint32 sampleCount)1869 EarlyFragmentSampleCountTestInstance::EarlyFragmentSampleCountTestInstance (Context& context, const deUint32 sampleCount)
1870 : EarlyFragmentTestInstance (context, FLAG_TEST_DEPTH)
1871 , m_sampleCount (sampleCount)
1872 {
1873 }
1874
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)1875 Move<VkPipeline> EarlyFragmentSampleCountTestInstance::makeGraphicsPipeline (const DeviceInterface& vk,
1876 const VkDevice device,
1877 const VkPipelineLayout pipelineLayout,
1878 const VkRenderPass renderPass,
1879 const VkShaderModule vertexModule,
1880 const VkShaderModule fragmentModule,
1881 const tcu::IVec2& renderSize,
1882 const VkSampleMask sampleMask)
1883 {
1884 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
1885 const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize));
1886
1887 const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
1888 {
1889 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
1890 DE_NULL, // const void* pNext
1891 0u, // VkPipelineDepthStencilStateCreateFlags flags
1892 VK_TRUE, // VkBool32 depthTestEnable
1893 VK_TRUE, // VkBool32 depthWriteEnable
1894 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp
1895 VK_FALSE, // VkBool32 depthBoundsTestEnable
1896 VK_FALSE, // VkBool32 stencilTestEnable
1897 {}, // VkStencilOpState front
1898 {}, // VkStencilOpState back
1899 0.0f, // float minDepthBounds
1900 1.0f // float maxDepthBounds
1901 };
1902
1903 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
1904 {
1905 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType
1906 DE_NULL, // const void* pNext
1907 0u, // VkPipelineMultisampleStateCreateFlags flags
1908 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits rasterizationSamples
1909 DE_FALSE, // VkBool32 sampleShadingEnable
1910 0.0f, // float minSampleShading
1911 &sampleMask, // const VkSampleMask* pSampleMask
1912 DE_FALSE, // VkBool32 alphaToCoverageEnable
1913 DE_FALSE, // VkBool32 alphaToOneEnable
1914 };
1915
1916 return vk::makeGraphicsPipeline(vk, // const DeviceInterface& vk
1917 device, // const VkDevice device
1918 pipelineLayout, // const VkPipelineLayout pipelineLayout
1919 vertexModule, // const VkShaderModule vertexShaderModule
1920 DE_NULL, // const VkShaderModule tessellationControlModule
1921 DE_NULL, // const VkShaderModule tessellationEvalModule
1922 DE_NULL, // const VkShaderModule geometryShaderModule
1923 fragmentModule, // const VkShaderModule fragmentShaderModule
1924 renderPass, // const VkRenderPass renderPass
1925 viewports, // const std::vector<VkViewport>& viewports
1926 scissors, // const std::vector<VkRect2D>& scissors
1927 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
1928 0u, // const deUint32 subpass
1929 0u, // const deUint32 patchControlPoints
1930 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
1931 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1932 &multisampleStateCreateInfo, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
1933 &depthStencilStateCreateInfo); // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
1934 }
1935
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat depthStencilFormat)1936 Move<VkRenderPass> EarlyFragmentSampleCountTestInstance::makeRenderPass (const DeviceInterface& vk,
1937 const VkDevice device,
1938 const VkFormat colorFormat,
1939 const VkFormat depthStencilFormat)
1940 {
1941 const VkAttachmentDescription colorAttachmentDescription =
1942 {
1943 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
1944 colorFormat, // VkFormat format;
1945 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples;
1946 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
1947 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1948 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
1949 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
1950 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
1951 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
1952 };
1953
1954 const VkAttachmentDescription depthStencilAttachmentDescription =
1955 {
1956 (VkAttachmentDescriptionFlags)0, // VkStructureType sType;
1957 depthStencilFormat, // VkFormat format
1958 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples
1959 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
1960 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
1961 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp
1962 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp
1963 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
1964 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
1965 };
1966
1967 const VkAttachmentDescription resolveAttachmentDescription =
1968 {
1969
1970 (VkAttachmentDescriptionFlags)0, // VkSubpassDescriptionFlags flags
1971 colorFormat, // VkFormat format
1972 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
1973 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
1974 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
1975 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
1976 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
1977 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
1978 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
1979 };
1980
1981 std::vector<VkAttachmentDescription> attachmentDescriptions;
1982
1983 attachmentDescriptions.push_back(colorAttachmentDescription);
1984 attachmentDescriptions.push_back(depthStencilAttachmentDescription);
1985 attachmentDescriptions.push_back(resolveAttachmentDescription);
1986
1987 const VkAttachmentReference colorAttachmentRef =
1988 {
1989 0u, // deUint32 attachment
1990 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
1991 };
1992
1993 const VkAttachmentReference depthStencilAttachmentRef =
1994 {
1995 1u, // deUint32 attachment
1996 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout layout
1997 };
1998
1999 const VkAttachmentReference resolveAttachmentRef =
2000 {
2001 2u, // deUint32 attachment
2002 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
2003 };
2004
2005 const VkSubpassDescription subpassDescription =
2006 {
2007 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
2008 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
2009 0u, // deUint32 inputAttachmentCount
2010 DE_NULL, // const VkAttachmentReference2* pInputAttachments
2011 1u, // deUint32 colorAttachmentCount
2012 &colorAttachmentRef, // const VkAttachmentReference2* pColorAttachments
2013 &resolveAttachmentRef, // const VkAttachmentReference2* pResolveAttachments
2014 &depthStencilAttachmentRef, // const VkAttachmentReference2* pDepthStencilAttachment
2015 0u, // deUint32 preserveAttachmentCount
2016 DE_NULL // const deUint32* pPreserveAttachments
2017 };
2018
2019 const VkRenderPassCreateInfo renderPassInfo =
2020 {
2021 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
2022 DE_NULL, // const void* pNext;
2023 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
2024 (deUint32)attachmentDescriptions.size(), // uint32_t attachmentCount;
2025 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments;
2026 1u, // uint32_t subpassCount;
2027 &subpassDescription, // const VkSubpassDescription* pSubpasses;
2028 0u, // uint32_t dependencyCount;
2029 DE_NULL // const VkSubpassDependency* pDependencies;
2030 };
2031
2032 return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
2033 }
2034
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)2035 tcu::TextureLevel EarlyFragmentSampleCountTestInstance::generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize)
2036 {
2037 tcu::TextureLevel image (format, renderSize.x(), renderSize.y());
2038 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
2039
2040 tcu::clear(image.getAccess(), clearColor);
2041
2042 return image;
2043 }
2044
iterate(void)2045 tcu::TestStatus EarlyFragmentSampleCountTestInstance::iterate (void)
2046 {
2047 const DeviceInterface& vk = m_context.getDeviceInterface();
2048 const VkDevice device = m_context.getDevice();
2049 const VkQueue queue = m_context.getUniversalQueue();
2050 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2051 Allocator& allocator = m_context.getDefaultAllocator();
2052 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
2053 const VkFormat depthFormat = VK_FORMAT_D16_UNORM;
2054 VkQueryPool queryPool;
2055 const deUint32 queryCount = 2u;
2056 std::vector<VkDeviceSize> sampleCounts (queryCount);
2057
2058 // Create a query pool for storing the occlusion query result
2059 {
2060 VkQueryPoolCreateInfo queryPoolInfo
2061 {
2062 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType;
2063 DE_NULL, // const void* pNext;
2064 (VkQueryPoolCreateFlags)0, // VkQueryPoolCreateFlags flags;
2065 VK_QUERY_TYPE_OCCLUSION, // VkQueryType queryType;
2066 queryCount, // uint32_t queryCount;
2067 0u, // VkQueryPipelineStatisticFlags pipelineStatistics;
2068 };
2069
2070 VK_CHECK(vk.createQueryPool(device, &queryPoolInfo, NULL, &queryPool));
2071 }
2072
2073 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth format " << getFormatName(VK_FORMAT_D16_UNORM) << tcu::TestLog::EndMessage;
2074
2075 // Color attachment
2076 const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
2077 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2078
2079 const VkImageCreateInfo imageParams =
2080 {
2081 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2082 DE_NULL, // const void* pNext;
2083 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
2084 VK_IMAGE_TYPE_2D, // VkImageType imageType;
2085 colorFormat, // VkFormat format;
2086 makeExtent3D(renderSize.x(), renderSize.y(), 1), // VkExtent3D extent;
2087 1u, // deUint32 mipLevels;
2088 1u, // deUint32 arrayLayers;
2089 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples;
2090 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
2091 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags usage;
2092 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
2093 0u, // deUint32 queueFamilyIndexCount;
2094 DE_NULL, // const deUint32* pQueueFamilyIndices;
2095 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
2096 };
2097
2098 const Unique<VkImage> colorImage (makeImage(vk, device, imageParams));
2099 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
2100 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
2101
2102 const Unique<VkImage> resolveColorImage (makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
2103 const UniquePtr<Allocation> resolveColorImageAlloc (bindImage(vk, device, allocator, *resolveColorImage, MemoryRequirement::Any));
2104 const Unique<VkImageView> resolveColorImageView (makeImageView(vk, device, *resolveColorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
2105
2106 // Depth-Stencil attachment
2107 const VkImageSubresourceRange depthSubresourceRange = makeImageSubresourceRange(getImageAspectFlags(depthFormat), 0u, 1u, 0u, 1u);
2108
2109 const VkImageCreateInfo depthImageParams =
2110 {
2111 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2112 DE_NULL, // const void* pNext;
2113 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
2114 VK_IMAGE_TYPE_2D, // VkImageType imageType;
2115 depthFormat, // VkFormat format;
2116 makeExtent3D(renderSize.x(), renderSize.y(), 1), // VkExtent3D extent;
2117 1u, // deUint32 mipLevels;
2118 1u, // deUint32 arrayLayers;
2119 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples;
2120 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
2121 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, // VkImageUsageFlags usage;
2122 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
2123 0u, // deUint32 queueFamilyIndexCount;
2124 DE_NULL, // const deUint32* pQueueFamilyIndices;
2125 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
2126 };
2127
2128 const Unique<VkImage> depthImage (makeImage(vk, device, depthImageParams));
2129 const UniquePtr<Allocation> depthImageAlloc (bindImage(vk, device, allocator, *depthImage, MemoryRequirement::Any));
2130 const Unique<VkImageView> depthImageView (makeImageView(vk, device, *depthImage, VK_IMAGE_VIEW_TYPE_2D, depthFormat, depthSubresourceRange));
2131
2132 const VkImageView attachmentImages[] = { *colorImageView, *depthImageView, *resolveColorImageView };
2133 const deUint32 numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
2134
2135 // Vertex buffer
2136 const deUint32 numVertices = 6u;
2137 const VkDeviceSize vertexBufferSizeBytes = 256 * numVertices;
2138 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
2139 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
2140
2141 {
2142 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
2143
2144 pVertices[0] = tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f);
2145 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
2146 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f);
2147
2148 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f);
2149 pVertices[4] = tcu::Vec4( 1.0f, 1.0f, 1.0f, 1.0f);
2150 pVertices[5] = tcu::Vec4( 1.0f, -1.0f, 1.0f, 1.0f);
2151
2152 flushAlloc(vk, device, *vertexBufferAlloc);
2153 // No barrier needed, flushed memory is automatically visible
2154 }
2155
2156 // Render result buffer (to retrieve color attachment contents)
2157
2158 const VkDeviceSize colorBufferSizeBytes = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
2159 const Unique<VkBuffer> colorBufferNoEarlyResults (makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2160 const UniquePtr<Allocation> colorBufferAllocNoEarly (bindBuffer(vk, device, allocator, *colorBufferNoEarlyResults, MemoryRequirement::HostVisible));
2161 const Unique<VkBuffer> colorBufferEarlyResults (makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2162 const UniquePtr<Allocation> colorBufferAllocEarly (bindBuffer(vk, device, allocator, *colorBufferEarlyResults, MemoryRequirement::HostVisible));
2163
2164 // Pipeline
2165
2166 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2167 const Unique<VkShaderModule> fragmentModuleNoEarly (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
2168 const Unique<VkShaderModule> fragmentModuleEarlyFrag (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_early"), 0u));
2169
2170 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat, depthFormat));
2171
2172 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
2173
2174 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, DE_NULL));
2175
2176 // When we are creating a pipeline for runs without early fragment test, we are enabling all the samples for full coverage.
2177 // Sample mask will be modified in a fragment shader.
2178 const Unique<VkPipeline> pipelineNoEarlyFrag (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModuleNoEarly, renderSize, 0xFFFFFFFF));
2179
2180 // For early fragment tests, we are enabling only half of the samples.
2181 const Unique<VkPipeline> pipelineEarlyFrag (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModuleEarlyFrag, renderSize, 0xAAAAAAAA));
2182
2183 // Build a command buffer
2184
2185 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2186 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2187
2188 enum QueryIndex
2189 {
2190 QUERY_INDEX_NO_EARLY_FRAG = 0,
2191 QUERY_INDEX_EARLY_FRAG = 1
2192 };
2193
2194 {
2195 const VkRect2D renderArea =
2196 {
2197 makeOffset2D(0, 0),
2198 makeExtent2D(renderSize.x(), renderSize.y()),
2199 };
2200
2201 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f);
2202 const VkDeviceSize vertexBufferOffset = 0ull;
2203
2204 beginCommandBuffer(vk, *cmdBuffer);
2205
2206 const VkClearValue clearValues[] =
2207 {
2208 makeClearValueColor(clearColor), // attachment 0
2209 makeClearValueDepthStencil(0.5f, 3u), // attachment 1
2210 makeClearValueColor(clearColor), // attachment 2
2211 makeClearValueDepthStencil(0.5f, 3u), // attachment 3
2212 };
2213
2214 const VkRenderPassBeginInfo renderPassBeginInfo =
2215 {
2216 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
2217 DE_NULL, // const void* pNext;
2218 *renderPass, // VkRenderPass renderPass;
2219 *framebuffer, // VkFramebuffer framebuffer;
2220 renderArea, // VkRect2D renderArea;
2221 DE_LENGTH_OF_ARRAY(clearValues), // deUint32 clearValueCount;
2222 clearValues, // const VkClearValue* pClearValues;
2223 };
2224
2225 // Reset query pool. Must be done outside of render pass
2226 vk.cmdResetQueryPool(*cmdBuffer, queryPool, 0, queryCount);
2227
2228 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2229
2230 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2231
2232 // Run without early fragment test.
2233 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineNoEarlyFrag);
2234
2235 vk.cmdBeginQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_NO_EARLY_FRAG, VK_QUERY_CONTROL_PRECISE_BIT);
2236 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
2237 vk.cmdEndQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_NO_EARLY_FRAG);
2238
2239 endRenderPass(vk, *cmdBuffer);
2240
2241 copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBufferNoEarlyResults, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
2242
2243 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2244
2245 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2246
2247 // Run with early fragment test.
2248 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineEarlyFrag);
2249
2250 vk.cmdBeginQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_EARLY_FRAG, VK_QUERY_CONTROL_PRECISE_BIT);
2251 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
2252 vk.cmdEndQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_EARLY_FRAG);
2253
2254 endRenderPass(vk, *cmdBuffer);
2255
2256 copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBufferEarlyResults, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
2257
2258 endCommandBuffer(vk, *cmdBuffer);
2259 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2260 }
2261
2262 // When early fragment test is enabled, all samples are killed in fragment shader. The result color should be black.
2263 {
2264 invalidateAlloc(vk, device, *colorBufferAllocEarly);
2265
2266 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAllocEarly->getHostPtr());
2267 const tcu::TextureLevel referenceImage = generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
2268
2269 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))
2270 return tcu::TestStatus::fail("Rendered color image is not correct");
2271 }
2272
2273 // The image has 32x32 pixels and each pixel has m_sampleCount samples. Half of these samples are discarded before sample counting.
2274 // This means the reference value for passed samples is ((32 x 32) / 2 / 2) * sampleCount.
2275 {
2276 deUint64 refValue = deUint64(deUint32((renderSize.x() * renderSize.y()) / 4) * m_sampleCount);
2277 deUint64 tolerance = deUint64(refValue * 5 / 100);
2278 deUint64 minValue = refValue - tolerance;
2279 deUint64 maxValue = refValue + tolerance;
2280
2281 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));
2282
2283 // Log test results
2284 {
2285 tcu::TestLog& log = m_context.getTestContext().getLog();
2286
2287 log << tcu::TestLog::Message << "\nAcceptable range: " << minValue << " - " << maxValue << tcu::TestLog::EndMessage;
2288 log << tcu::TestLog::Message << "Passed Samples (without early fragment test) : " << de::toString(sampleCounts[0]) << tcu::TestLog::EndMessage;
2289 log << tcu::TestLog::Message << "Passed Samples (with early fragment test) : " << de::toString(sampleCounts[1]) << tcu::TestLog::EndMessage;
2290 }
2291
2292 #ifndef CTS_USES_VULKANSC
2293 vk.destroyQueryPool(device, queryPool, nullptr);
2294 #endif // CTS_USES_VULKANSC
2295
2296 // Check that number of the all passed samples are within an acceptable range.
2297 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)
2298 {
2299 return tcu::TestStatus::pass("Success");
2300 }
2301 else if (sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] >= minValue && sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] <= maxValue && sampleCounts[QUERY_INDEX_EARLY_FRAG] == 0)
2302 {
2303 // Spec says: "If the fragment shader declares the EarlyFragmentTests execution mode, fragment shading and
2304 // multisample coverage operations should instead be performed after sample counting.
2305
2306 // since the specification says 'should', the opposite behavior is allowed, but not preferred
2307 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Sample count is 0 - sample counting performed after multisample coverage and fragment shading");
2308 }
2309 else if (sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] >= minValue && sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] <= maxValue &&
2310 sampleCounts[QUERY_INDEX_EARLY_FRAG] >= (minValue * 2) && sampleCounts[QUERY_INDEX_EARLY_FRAG] <= (maxValue * 2))
2311 {
2312 // If the sample count returned is double the expected value, the sample mask test has been executed after
2313 // sample counting.
2314
2315 // Spec says: "If there is a fragment shader and it declares the EarlyFragmentTests execution mode, ...
2316 // sample mask test may: instead be performed after sample counting"
2317
2318 // since the specification says 'may', the opposite behavior is allowed, but not preferred
2319 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Sample count is greater than expected - sample mask test performed after sample counting");
2320 }
2321 else
2322 {
2323 // Log no early frag test images
2324 {
2325 tcu::TestLog& log = m_context.getTestContext().getLog();
2326
2327 invalidateAlloc(vk, device, *colorBufferAllocNoEarly);
2328
2329 const tcu::ConstPixelBufferAccess imagePixelAccess (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAllocNoEarly->getHostPtr());
2330
2331 log << tcu::LogImageSet("No Early Frag Test Images", "No Early Fragment Test Images")
2332 << tcu::TestLog::Image("color", "Rendered image (color)", imagePixelAccess)
2333 << tcu::TestLog::EndImageSet;
2334 }
2335
2336 // Log early frag test images
2337 {
2338 tcu::TestLog& log = m_context.getTestContext().getLog();
2339
2340 invalidateAlloc(vk, device, *colorBufferAllocEarly);
2341
2342 const tcu::ConstPixelBufferAccess imagePixelAccess (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAllocEarly->getHostPtr());
2343
2344 log << tcu::LogImageSet("Early Frag Test Images", "Early Fragment Test Images")
2345 << tcu::TestLog::Image("color", "Rendered image (color)", imagePixelAccess)
2346 << tcu::TestLog::EndImageSet;
2347 }
2348
2349 return tcu::TestStatus::fail("Sample count value outside expected range.");
2350 }
2351 }
2352 }
2353
2354 class EarlyFragmentSampleCountTest : public EarlyFragmentTest
2355 {
2356 public:
2357 EarlyFragmentSampleCountTest (tcu::TestContext& testCtx,
2358 const std::string name,
2359 const deUint32 sampleCount,
2360 const bool earlyAndLate);
2361
2362 void initPrograms (SourceCollections& programCollection) const override;
2363 TestInstance* createInstance (Context& context) const override;
2364 void checkSupport (Context& context) const override;
2365
2366 private:
2367 const deUint32 m_sampleCount;
2368 const bool m_earlyAndLate;
2369 };
2370
EarlyFragmentSampleCountTest(tcu::TestContext & testCtx,const std::string name,const deUint32 sampleCount,const bool earlyAndLate)2371 EarlyFragmentSampleCountTest::EarlyFragmentSampleCountTest(tcu::TestContext& testCtx, const std::string name, const deUint32 sampleCount, const bool earlyAndLate)
2372 : EarlyFragmentTest (testCtx, name, FLAG_TEST_DEPTH)
2373 , m_sampleCount (sampleCount)
2374 , m_earlyAndLate (earlyAndLate)
2375 {
2376 }
2377
createInstance(Context & context) const2378 TestInstance* EarlyFragmentSampleCountTest::createInstance (Context& context) const
2379 {
2380 return new EarlyFragmentSampleCountTestInstance(context, m_sampleCount);
2381 }
2382
initPrograms(SourceCollections & programCollection) const2383 void EarlyFragmentSampleCountTest::initPrograms(SourceCollections& programCollection) const
2384 {
2385 // Vertex shader
2386 {
2387 std::ostringstream vrt;
2388
2389 vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2390 << "\n"
2391 << "layout(location = 0) in highp vec4 position;\n"
2392 << "\n"
2393 << "out gl_PerVertex {\n"
2394 << " vec4 gl_Position;\n"
2395 << "};\n"
2396 << "\n"
2397 << "void main (void)\n"
2398 << "{\n"
2399 << " gl_Position = position;\n"
2400 << "}\n";
2401
2402 programCollection.glslSources.add("vert") << glu::VertexSource(vrt.str());
2403 }
2404
2405 // Fragment shader for runs without early fragment test
2406 if (m_earlyAndLate == false)
2407 {
2408 std::ostringstream frg;
2409
2410 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2411 << "\n"
2412 << "layout(location = 0) out highp vec4 fragColor;\n"
2413 << "\n"
2414 << "void main (void)\n"
2415 << "{\n"
2416 << " // This will kill half of the samples.\n"
2417 << " gl_SampleMask[0] = 0xAAAAAAAA;\n"
2418 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
2419 << "}\n";
2420
2421 programCollection.glslSources.add("frag") << glu::FragmentSource(frg.str());
2422 }
2423 else
2424 {
2425 const SpirVAsmBuildOptions buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
2426 const std::string src =
2427 "; SPIR - V\n"
2428 "; Version: 1.0\n"
2429 "; Generator: Khronos Glslang Reference Front End; 10\n"
2430 "; Bound: 23\n"
2431 "; Schema: 0\n"
2432 "OpCapability Shader\n"
2433 "OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
2434 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
2435 "OpMemoryModel Logical GLSL450\n"
2436 "OpEntryPoint Fragment %4 \"main\" %11 %19\n"
2437 "OpExecutionMode %4 OriginUpperLeft\n"
2438 "OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
2439 "OpExecutionMode %4 DepthReplacing\n"
2440 "OpExecutionMode %4 DepthLess\n"
2441 "OpDecorate %11 BuiltIn SampleMask\n"
2442 "OpDecorate %19 Location 0\n"
2443 "%2 = OpTypeVoid\n"
2444 "%3 = OpTypeFunction %2\n"
2445 "%6 = OpTypeInt 32 1\n"
2446 "%7 = OpTypeInt 32 0\n"
2447 "%8 = OpConstant %7 1\n"
2448 "%9 = OpTypeArray %6 %8\n"
2449 "%10 = OpTypePointer Output %9\n"
2450 "%11 = OpVariable %10 Output\n"
2451 "%12 = OpConstant %6 0\n"
2452 "%13 = OpConstant %6 -1431655766\n"
2453 "%14 = OpTypePointer Output %6\n"
2454 "%16 = OpTypeFloat 32\n"
2455 "%17 = OpTypeVector %16 4\n"
2456 "%18 = OpTypePointer Output %17\n"
2457 "%19 = OpVariable %18 Output\n"
2458 "%20 = OpConstant %16 1\n"
2459 "%21 = OpConstant %16 0\n"
2460 "%22 = OpConstantComposite %17 %20 %20 %21 %20\n"
2461 "%4 = OpFunction %2 None %3\n"
2462 "%5 = OpLabel\n"
2463 "%15 = OpAccessChain %14 %11 %12\n"
2464 "OpStore %15 %13\n"
2465 "OpStore %19 %22\n"
2466 "OpReturn\n"
2467 "OpFunctionEnd\n";
2468 programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
2469 }
2470
2471 // Fragment shader for early fragment tests
2472 if (m_earlyAndLate == false)
2473 {
2474 std::ostringstream frg;
2475
2476 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2477 << "\n"
2478 << "layout(early_fragment_tests) in;\n"
2479 << "\n"
2480 << "layout(location = 0) out highp vec4 fragColor;\n"
2481 << "\n"
2482 << "void main (void)\n"
2483 << "{\n"
2484 << " // Sample mask kills all the samples, but the sample counting has already happened.\n"
2485 << " gl_SampleMask[0] = 0x0;\n"
2486 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
2487 << "}\n";
2488
2489 programCollection.glslSources.add("frag_early") << glu::FragmentSource(frg.str());
2490 }
2491 else
2492 {
2493 const SpirVAsmBuildOptions buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
2494 const std::string src =
2495 "; SPIR - V\n"
2496 "; Version: 1.0\n"
2497 "; Generator: Khronos Glslang Reference Front End; 10\n"
2498 "; Bound: 22\n"
2499 "; Schema: 0\n"
2500 "OpCapability Shader\n"
2501 "OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
2502 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
2503 "OpMemoryModel Logical GLSL450\n"
2504 "OpEntryPoint Fragment %4 \"main\" %11 %18\n"
2505 "OpExecutionMode %4 OriginUpperLeft\n"
2506 "OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
2507 "OpDecorate %11 BuiltIn SampleMask\n"
2508 "OpDecorate %18 Location 0\n"
2509 "%2 = OpTypeVoid\n"
2510 "%3 = OpTypeFunction %2\n"
2511 "%6 = OpTypeInt 32 1\n"
2512 "%7 = OpTypeInt 32 0\n"
2513 "%8 = OpConstant %7 1\n"
2514 "%9 = OpTypeArray %6 %8\n"
2515 "%10 = OpTypePointer Output %9\n"
2516 "%11 = OpVariable %10 Output\n"
2517 "%12 = OpConstant %6 0\n"
2518 "%13 = OpTypePointer Output %6\n"
2519 "%15 = OpTypeFloat 32\n"
2520 "%16 = OpTypeVector %15 4\n"
2521 "%17 = OpTypePointer Output %16\n"
2522 "%18 = OpVariable %17 Output\n"
2523 "%19 = OpConstant %15 1\n"
2524 "%20 = OpConstant %15 0\n"
2525 "%21 = OpConstantComposite %16 %19 %19 %20 %19\n"
2526 "%4 = OpFunction %2 None %3\n"
2527 "%5 = OpLabel\n"
2528 "%14 = OpAccessChain %13 %11 %12\n"
2529 "OpStore %14 %12\n"
2530 "OpStore %18 %21\n"
2531 "OpReturn\n"
2532 "OpFunctionEnd\n";
2533 programCollection.spirvAsmSources.add("frag_early") << src << buildOptionsSpr;
2534 }
2535 }
2536
checkSupport(Context & context) const2537 void EarlyFragmentSampleCountTest::checkSupport(Context& context) const
2538 {
2539 EarlyFragmentTest::checkSupport(context);
2540
2541 // Check support for MSAA image formats used in the test.
2542 const InstanceInterface& vki = context.getInstanceInterface();
2543 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
2544 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
2545 const VkFormat depthFormat = VK_FORMAT_D16_UNORM;
2546
2547 VkImageFormatProperties formatProperties;
2548
2549 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);
2550 if ((formatProperties.sampleCounts & m_sampleCount) == 0)
2551 TCU_THROW(NotSupportedError, "Format does not support this number of samples for color format");
2552
2553 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);
2554 if ((formatProperties.sampleCounts & m_sampleCount) == 0)
2555 TCU_THROW(NotSupportedError, "Format does not support this number of samples for depth format");
2556
2557 #ifndef CTS_USES_VULKANSC
2558 if (m_earlyAndLate)
2559 {
2560 context.requireDeviceFunctionality("VK_AMD_shader_early_and_late_fragment_tests");
2561 if (context.getShaderEarlyAndLateFragmentTestsFeaturesAMD().shaderEarlyAndLateFragmentTests == VK_FALSE)
2562 TCU_THROW(NotSupportedError, "shaderEarlyAndLateFragmentTests is not supported");
2563 }
2564 #endif
2565 }
2566
2567 } // anonymous ns
2568
createEarlyFragmentTests(tcu::TestContext & testCtx)2569 tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
2570 {
2571 de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases"));
2572
2573 {
2574 struct TestCaseEarly
2575 {
2576 std::string caseName;
2577 deUint32 flags;
2578 };
2579
2580 static const TestCaseEarly cases[] =
2581 {
2582
2583 { "no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
2584 { "no_early_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
2585 { "early_fragment_tests_depth", FLAG_TEST_DEPTH },
2586 { "early_fragment_tests_stencil", FLAG_TEST_STENCIL },
2587 { "no_early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT },
2588 { "no_early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT },
2589 { "early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_TEST_ATTACHMENT },
2590 { "early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT },
2591 };
2592
2593 #ifndef CTS_USES_VULKANSC
2594 static const TestCaseEarly casesEarlyAndLate[] =
2595 {
2596 { "early_and_late_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS },
2597 { "early_and_late_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS },
2598 { "early_and_late_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_TEST_ATTACHMENT | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS },
2599 { "early_and_late_fragment_tests_stencil_no_attachment",FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS },
2600 };
2601 #endif
2602
2603 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2604 testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
2605 #ifndef CTS_USES_VULKANSC
2606 for (int i = 0; i < DE_LENGTH_OF_ARRAY(casesEarlyAndLate); ++i)
2607 testGroup->addChild(new EarlyFragmentTest(testCtx, casesEarlyAndLate[i].caseName, casesEarlyAndLate[i].flags));
2608 #endif
2609 }
2610
2611 // Check that discard does not affect depth test writes.
2612 {
2613 static const struct
2614 {
2615 std::string caseName;
2616 deUint32 flags;
2617 } cases[] =
2618 {
2619 { "discard_no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
2620 { "discard_no_early_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
2621 { "discard_early_fragment_tests_depth", FLAG_TEST_DEPTH },
2622 { "discard_early_fragment_tests_stencil", FLAG_TEST_STENCIL },
2623 #ifndef CTS_USES_VULKANSC
2624 { "discard_early_and_late_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS },
2625 { "discard_early_and_late_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS },
2626 #endif
2627 };
2628
2629 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2630 testGroup->addChild(new EarlyFragmentDiscardTest(testCtx, cases[i].caseName, cases[i].flags));
2631 }
2632
2633 // Check that writing to gl_SampleMask does not affect depth test writes.
2634 {
2635 static const struct
2636 {
2637 std::string caseName;
2638 deUint32 flags;
2639 } cases[] =
2640 {
2641 { "samplemask_no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
2642 { "samplemask_early_fragment_tests_depth", FLAG_TEST_DEPTH },
2643 #ifndef CTS_USES_VULKANSC
2644 { "samplemask_early_and_late_fragment_tests_depth_replacing_mode", FLAG_TEST_DEPTH | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
2645 { "samplemask_early_and_late_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS },
2646 #endif
2647 };
2648
2649 const VkSampleCountFlags sampleCounts[] = { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT };
2650 const std::string sampleCountsStr[] = { "samples_2", "samples_4", "samples_8", "samples_16" };
2651
2652 for (deUint32 sampleCountsNdx = 0; sampleCountsNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountsNdx++)
2653 {
2654 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2655 testGroup->addChild(new EarlyFragmentSampleMaskTest(testCtx, cases[i].caseName + "_" + sampleCountsStr[sampleCountsNdx], cases[i].flags, sampleCounts[sampleCountsNdx]));
2656 }
2657 }
2658
2659 // 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.
2660 {
2661 const VkSampleCountFlags sampleCounts[] = { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT };
2662 const std::string sampleCountsStr[] = { "samples_2", "samples_4", "samples_8", "samples_16" };
2663
2664 for (deUint32 sampleCountsNdx = 0; sampleCountsNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountsNdx++)
2665 {
2666 testGroup->addChild(new EarlyFragmentSampleCountTest(testCtx, "sample_count_early_fragment_tests_depth_" + sampleCountsStr[sampleCountsNdx], sampleCounts[sampleCountsNdx], false));
2667 #ifndef CTS_USES_VULKANSC
2668 testGroup->addChild(new EarlyFragmentSampleCountTest(testCtx, "sample_count_early_and_late_fragment_tests_depth_" + sampleCountsStr[sampleCountsNdx], sampleCounts[sampleCountsNdx], true));
2669 #endif
2670 }
2671 }
2672
2673 return testGroup.release();
2674 }
2675
2676 } // FragmentOperations
2677 } // vkt
2678