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 "vktFragmentOperationsMakeUtil.hpp"
27 #include "vktTestCaseUtil.hpp"
28
29 #include "vkDefs.hpp"
30 #include "vkRef.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vkPlatform.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkStrUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkImageUtil.hpp"
40 #include "vkBarrierUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43
44 #include "tcuTestLog.hpp"
45
46 #include "deUniquePtr.hpp"
47 #include "deStringUtil.hpp"
48
49 #include <string>
50
51 namespace vkt
52 {
53 namespace FragmentOperations
54 {
55 namespace
56 {
57 using namespace vk;
58 using de::UniquePtr;
59
60 //! Basic 2D image.
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)61 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
62 {
63 const VkImageCreateInfo imageParams =
64 {
65 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
66 DE_NULL, // const void* pNext;
67 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
68 VK_IMAGE_TYPE_2D, // VkImageType imageType;
69 format, // VkFormat format;
70 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
71 1u, // deUint32 mipLevels;
72 1u, // deUint32 arrayLayers;
73 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
74 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
75 usage, // VkImageUsageFlags usage;
76 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
77 0u, // deUint32 queueFamilyIndexCount;
78 DE_NULL, // const deUint32* pQueueFamilyIndices;
79 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
80 };
81 return imageParams;
82 }
83
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const bool useDepthStencilAttachment,const VkFormat depthStencilFormat)84 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
85 const VkDevice device,
86 const VkFormat colorFormat,
87 const bool useDepthStencilAttachment,
88 const VkFormat depthStencilFormat)
89 {
90 return makeRenderPass(vk, device, colorFormat, useDepthStencilAttachment ? depthStencilFormat : VK_FORMAT_UNDEFINED);
91 }
92
makeFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass,const deUint32 attachmentCount,const VkImageView * pAttachments,const tcu::IVec2 size)93 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface& vk,
94 const VkDevice device,
95 const VkRenderPass renderPass,
96 const deUint32 attachmentCount,
97 const VkImageView* pAttachments,
98 const tcu::IVec2 size)
99 {
100 const VkFramebufferCreateInfo framebufferInfo = {
101 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
102 DE_NULL, // const void* pNext;
103 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags;
104 renderPass, // VkRenderPass renderPass;
105 attachmentCount, // uint32_t attachmentCount;
106 pAttachments, // const VkImageView* pAttachments;
107 static_cast<deUint32>(size.x()), // uint32_t width;
108 static_cast<deUint32>(size.y()), // uint32_t height;
109 1u, // uint32_t layers;
110 };
111
112 return createFramebuffer(vk, device, &framebufferInfo);
113 }
114
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)115 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
116 const VkDevice device,
117 const VkPipelineLayout pipelineLayout,
118 const VkRenderPass renderPass,
119 const VkShaderModule vertexModule,
120 const VkShaderModule fragmentModule,
121 const tcu::IVec2& renderSize,
122 const bool enableDepthTest,
123 const bool enableStencilTest)
124 {
125 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
126 const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize));
127
128 const VkStencilOpState stencilOpState = makeStencilOpState(
129 VK_STENCIL_OP_KEEP, // stencil fail
130 VK_STENCIL_OP_KEEP, // depth & stencil pass
131 VK_STENCIL_OP_KEEP, // depth only fail
132 VK_COMPARE_OP_EQUAL, // compare op
133 1u, // compare mask
134 1u, // write mask
135 1u); // reference
136
137 VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
138 {
139 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
140 DE_NULL, // const void* pNext
141 0u, // VkPipelineDepthStencilStateCreateFlags flags
142 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthTestEnable
143 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthWriteEnable
144 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp
145 VK_FALSE, // VkBool32 depthBoundsTestEnable
146 enableStencilTest ? VK_TRUE : VK_FALSE, // VkBool32 stencilTestEnable
147 stencilOpState, // VkStencilOpState front
148 stencilOpState, // VkStencilOpState back
149 0.0f, // float minDepthBounds
150 1.0f // float maxDepthBounds
151 };
152
153 return vk::makeGraphicsPipeline(vk, // const DeviceInterface& vk
154 device, // const VkDevice device
155 pipelineLayout, // const VkPipelineLayout pipelineLayout
156 vertexModule, // const VkShaderModule vertexShaderModule
157 DE_NULL, // const VkShaderModule tessellationControlModule
158 DE_NULL, // const VkShaderModule tessellationEvalModule
159 DE_NULL, // const VkShaderModule geometryShaderModule
160 fragmentModule, // const VkShaderModule fragmentShaderModule
161 renderPass, // const VkRenderPass renderPass
162 viewports, // const std::vector<VkViewport>& viewports
163 scissors, // const std::vector<VkRect2D>& scissors
164 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
165 0u, // const deUint32 subpass
166 0u, // const deUint32 patchControlPoints
167 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
168 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
169 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
170 &depthStencilStateCreateInfo); // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
171 }
172
commandClearStencilAttachment(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkOffset2D & offset,const VkExtent2D & extent,const deUint32 clearValue)173 void commandClearStencilAttachment (const DeviceInterface& vk,
174 const VkCommandBuffer commandBuffer,
175 const VkOffset2D& offset,
176 const VkExtent2D& extent,
177 const deUint32 clearValue)
178 {
179 const VkClearAttachment stencilAttachment =
180 {
181 VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask;
182 0u, // uint32_t colorAttachment;
183 makeClearValueDepthStencil(0.0f, clearValue), // VkClearValue clearValue;
184 };
185
186 const VkClearRect rect =
187 {
188 { offset, extent }, // VkRect2D rect;
189 0u, // uint32_t baseArrayLayer;
190 1u, // uint32_t layerCount;
191 };
192
193 vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
194 }
195
getImageAspectFlags(const VkFormat format)196 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
197 {
198 const tcu::TextureFormat tcuFormat = mapVkFormat(format);
199
200 if (tcuFormat.order == tcu::TextureFormat::DS) return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
201 else if (tcuFormat.order == tcu::TextureFormat::D) return VK_IMAGE_ASPECT_DEPTH_BIT;
202 else if (tcuFormat.order == tcu::TextureFormat::S) return VK_IMAGE_ASPECT_STENCIL_BIT;
203
204 DE_ASSERT(false);
205 return 0u;
206 }
207
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const VkFormat format)208 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
209 {
210 VkFormatProperties formatProps;
211 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
212 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
213 }
214
pickSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const deUint32 numFormats,const VkFormat * pFormats)215 VkFormat pickSupportedDepthStencilFormat (const InstanceInterface& instanceInterface,
216 const VkPhysicalDevice device,
217 const deUint32 numFormats,
218 const VkFormat* pFormats)
219 {
220 for (deUint32 i = 0; i < numFormats; ++i)
221 if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
222 return pFormats[i];
223 return VK_FORMAT_UNDEFINED;
224 }
225
226 enum Flags
227 {
228 FLAG_TEST_DEPTH = 1u << 0,
229 FLAG_TEST_STENCIL = 1u << 1,
230 FLAG_DONT_USE_TEST_ATTACHMENT = 1u << 2,
231 FLAG_DONT_USE_EARLY_FRAGMENT_TESTS = 1u << 3,
232 };
233
234 class EarlyFragmentTest : public TestCase
235 {
236 public:
237 EarlyFragmentTest (tcu::TestContext& testCtx,
238 const std::string name,
239 const deUint32 flags);
240
241 void initPrograms (SourceCollections& programCollection) const;
242 TestInstance* createInstance (Context& context) const;
243
244 private:
245 const deUint32 m_flags;
246 };
247
EarlyFragmentTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags)248 EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
249 : TestCase (testCtx, name, "")
250 , m_flags (flags)
251 {
252 }
253
initPrograms(SourceCollections & programCollection) const254 void EarlyFragmentTest::initPrograms (SourceCollections& programCollection) const
255 {
256 // Vertex
257 {
258 std::ostringstream src;
259 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
260 << "\n"
261 << "layout(location = 0) in highp vec4 position;\n"
262 << "\n"
263 << "out gl_PerVertex {\n"
264 << " vec4 gl_Position;\n"
265 << "};\n"
266 << "\n"
267 << "void main (void)\n"
268 << "{\n"
269 << " gl_Position = position;\n"
270 << "}\n";
271
272 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
273 }
274
275 // Fragment
276 {
277 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
278 std::ostringstream src;
279 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
280 << "\n"
281 << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
282 << "layout(location = 0) out highp vec4 fragColor;\n"
283 << "\n"
284 << "layout(binding = 0) coherent buffer Output {\n"
285 << " uint result;\n"
286 << "} sb_out;\n"
287 << "\n"
288 << "void main (void)\n"
289 << "{\n"
290 << " atomicAdd(sb_out.result, 1u);\n"
291 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
292 << "}\n";
293
294 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
295 }
296 }
297
298 class EarlyFragmentTestInstance : public TestInstance
299 {
300 public:
301 EarlyFragmentTestInstance (Context& context, const deUint32 flags);
302
303 tcu::TestStatus iterate (void);
304
305 private:
306 enum TestMode
307 {
308 MODE_INVALID,
309 MODE_DEPTH,
310 MODE_STENCIL,
311 };
312
313 const TestMode m_testMode;
314 const bool m_useTestAttachment;
315 const bool m_useEarlyTests;
316 };
317
EarlyFragmentTestInstance(Context & context,const deUint32 flags)318 EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags)
319 : TestInstance (context)
320 , m_testMode (flags & FLAG_TEST_DEPTH ? MODE_DEPTH :
321 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
322 , m_useTestAttachment ((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
323 , m_useEarlyTests ((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
324 {
325 DE_ASSERT(m_testMode != MODE_INVALID);
326 }
327
iterate(void)328 tcu::TestStatus EarlyFragmentTestInstance::iterate (void)
329 {
330 const DeviceInterface& vk = m_context.getDeviceInterface();
331 const InstanceInterface& vki = m_context.getInstanceInterface();
332 const VkDevice device = m_context.getDevice();
333 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
334 const VkQueue queue = m_context.getUniversalQueue();
335 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
336 Allocator& allocator = m_context.getDefaultAllocator();
337
338 // Color attachment
339
340 const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
341 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
342 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
343 const Unique<VkImage> colorImage (makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
344 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
345 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
346
347 // Test attachment (depth or stencil)
348 static const VkFormat stencilFormats[] =
349 {
350 // One of the following formats must be supported, as per spec requirement.
351 VK_FORMAT_S8_UINT,
352 VK_FORMAT_D16_UNORM_S8_UINT,
353 VK_FORMAT_D24_UNORM_S8_UINT,
354 VK_FORMAT_D32_SFLOAT_S8_UINT,
355 };
356
357 const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
358 : VK_FORMAT_D16_UNORM); // spec requires this format to be supported
359 if (testFormat == VK_FORMAT_UNDEFINED)
360 return tcu::TestStatus::fail("Required depth/stencil format not supported");
361
362 if (m_useTestAttachment)
363 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
364
365 const VkImageSubresourceRange testSubresourceRange = makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
366 const Unique<VkImage> testImage (makeImage(vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
367 const UniquePtr<Allocation> testImageAlloc (bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
368 const Unique<VkImageView> testImageView (makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
369 const VkImageView attachmentImages[] = { *colorImageView, *testImageView };
370 const deUint32 numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
371
372 // Vertex buffer
373
374 const deUint32 numVertices = 6;
375 const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
376 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, makeBufferCreateInfo(vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)));
377 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
378
379 {
380 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
381
382 pVertices[0] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f);
383 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
384 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
385
386 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
387 pVertices[4] = tcu::Vec4( 1.0f, 1.0f, 1.0f, 1.0f);
388 pVertices[5] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f);
389
390 flushAlloc(vk, device, *vertexBufferAlloc);
391 // No barrier needed, flushed memory is automatically visible
392 }
393
394 // Result buffer
395
396 const VkDeviceSize resultBufferSizeBytes = sizeof(deUint32);
397 const Unique<VkBuffer> resultBuffer (makeBuffer(vk, device, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)));
398 const UniquePtr<Allocation> resultBufferAlloc (bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
399
400 {
401 deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
402
403 *pData = 0;
404 flushAlloc(vk, device, *resultBufferAlloc);
405 }
406
407 // Render result buffer (to retrieve color attachment contents)
408
409 const VkDeviceSize colorBufferSizeBytes = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
410 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
411 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
412
413 // Descriptors
414
415 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
416 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
417 .build(vk, device));
418
419 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
420 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
421 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
422
423 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
424 const VkDescriptorBufferInfo resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
425
426 DescriptorSetUpdateBuilder()
427 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
428 .update(vk, device);
429
430 // Pipeline
431
432 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
433 const Unique<VkShaderModule> fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
434 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
435 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize));
436 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
437 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
438 (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL)));
439 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
440 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
441
442 // Draw commands
443
444 {
445 const VkRect2D renderArea = {
446 makeOffset2D(0, 0),
447 makeExtent2D(renderSize.x(), renderSize.y()),
448 };
449 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
450 const VkDeviceSize vertexBufferOffset = 0ull;
451
452 beginCommandBuffer(vk, *cmdBuffer);
453
454 {
455 const VkImageMemoryBarrier barriers[] = {
456 makeImageMemoryBarrier(
457 0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
458 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
459 *colorImage, colorSubresourceRange),
460 makeImageMemoryBarrier(
461 0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
462 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
463 *testImage, testSubresourceRange),
464 };
465
466 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
467 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
468 }
469
470 // Will clear the attachments with specified depth and stencil values.
471 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
472
473 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
474 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
475 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
476
477 // Mask half of the attachment image with value that will pass the stencil test.
478 if (m_useTestAttachment && m_testMode == MODE_STENCIL)
479 commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
480
481 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
482 endRenderPass(vk, *cmdBuffer);
483
484 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_SHADER_WRITE_BIT);
485
486 endCommandBuffer(vk, *cmdBuffer);
487 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
488 }
489
490 // Log result image
491 {
492 invalidateAlloc(vk, device, *colorBufferAlloc);
493
494 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
495
496 tcu::TestLog& log = m_context.getTestContext().getLog();
497 log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
498 }
499
500 // Verify results
501 {
502 invalidateAlloc(vk, device, *resultBufferAlloc);
503
504 const int actualCounter = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
505 const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
506 const int expectedCounter = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
507 const int tolerance = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3 : 0;
508 const int expectedMin = de::max(0, expectedCounter - tolerance);
509 const int expectedMax = expectedCounter + tolerance;
510
511 tcu::TestLog& log = m_context.getTestContext().getLog();
512 log << tcu::TestLog::Message << "Expected value"
513 << (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
514 << tcu::TestLog::EndMessage;
515 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
516
517 if (expectedMin <= actualCounter && actualCounter <= expectedMax)
518 return tcu::TestStatus::pass("Success");
519 else
520 return tcu::TestStatus::fail("Value out of range");
521 }
522 }
523
createInstance(Context & context) const524 TestInstance* EarlyFragmentTest::createInstance (Context& context) const
525 {
526 // Check required features
527 {
528 VkPhysicalDeviceFeatures features;
529 context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
530
531 // SSBO writes in fragment shader
532 if (!features.fragmentStoresAndAtomics)
533 throw tcu::NotSupportedError("Missing required feature: fragmentStoresAndAtomics");
534 }
535
536 return new EarlyFragmentTestInstance(context, m_flags);
537 }
538
539 } // anonymous ns
540
createEarlyFragmentTests(tcu::TestContext & testCtx)541 tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
542 {
543 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases"));
544
545 static const struct
546 {
547 std::string caseName;
548 deUint32 flags;
549 } cases[] =
550 {
551 { "no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
552 { "no_early_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
553 { "early_fragment_tests_depth", FLAG_TEST_DEPTH },
554 { "early_fragment_tests_stencil", FLAG_TEST_STENCIL },
555 { "no_early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT },
556 { "no_early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT },
557 { "early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_TEST_ATTACHMENT },
558 { "early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT },
559 };
560
561 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
562 testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
563
564 return testGroup.release();
565 }
566
567 } // FragmentOperations
568 } // vkt
569