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 "vktPipelineEarlyFragmentTests.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
40 #include "deUniquePtr.hpp"
41 #include "deStringUtil.hpp"
42
43 #include <string>
44
45 using namespace vk;
46
47 namespace vkt
48 {
49 namespace pipeline
50 {
51 namespace
52 {
53
54 // \note Some utility functions are general, but others are custom tailored to this test.
55
56 class Buffer
57 {
58 public:
Buffer(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const VkBufferCreateInfo & bufferCreateInfo,const MemoryRequirement memoryRequirement)59 Buffer (const DeviceInterface& vk,
60 const VkDevice device,
61 Allocator& allocator,
62 const VkBufferCreateInfo& bufferCreateInfo,
63 const MemoryRequirement memoryRequirement)
64
65 : m_buffer (createBuffer(vk, device, &bufferCreateInfo))
66 , m_allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), memoryRequirement))
67 {
68 VK_CHECK(vk.bindBufferMemory(device, *m_buffer, m_allocation->getMemory(), m_allocation->getOffset()));
69 }
70
get(void) const71 const VkBuffer& get (void) const { return *m_buffer; }
operator *(void) const72 const VkBuffer& operator* (void) const { return get(); }
getAllocation(void) const73 Allocation& getAllocation (void) const { return *m_allocation; }
74
75 private:
76 const Unique<VkBuffer> m_buffer;
77 const de::UniquePtr<Allocation> m_allocation;
78
79 // "deleted"
80 Buffer (const Buffer&);
81 Buffer& operator= (const Buffer&);
82 };
83
84 class Image
85 {
86 public:
Image(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const VkImageCreateInfo & imageCreateInfo,const MemoryRequirement memoryRequirement)87 Image (const DeviceInterface& vk,
88 const VkDevice device,
89 Allocator& allocator,
90 const VkImageCreateInfo& imageCreateInfo,
91 const MemoryRequirement memoryRequirement)
92
93 : m_image (createImage(vk, device, &imageCreateInfo))
94 , m_allocation (allocator.allocate(getImageMemoryRequirements(vk, device, *m_image), memoryRequirement))
95 {
96 VK_CHECK(vk.bindImageMemory(device, *m_image, m_allocation->getMemory(), m_allocation->getOffset()));
97 }
98
get(void) const99 const VkImage& get (void) const { return *m_image; }
operator *(void) const100 const VkImage& operator* (void) const { return get(); }
getAllocation(void) const101 Allocation& getAllocation (void) const { return *m_allocation; }
102
103 private:
104 const Unique<VkImage> m_image;
105 const de::UniquePtr<Allocation> m_allocation;
106
107 // "deleted"
108 Image (const Image&);
109 Image& operator= (const Image&);
110 };
111
makeImageView(const DeviceInterface & vk,const VkDevice vkDevice,const VkImage image,const VkImageViewType imageViewType,const VkFormat format,const VkImageSubresourceRange subresourceRange)112 Move<VkImageView> makeImageView (const DeviceInterface& vk,
113 const VkDevice vkDevice,
114 const VkImage image,
115 const VkImageViewType imageViewType,
116 const VkFormat format,
117 const VkImageSubresourceRange subresourceRange)
118 {
119 const VkImageViewCreateInfo imageViewParams =
120 {
121 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
122 DE_NULL, // const void* pNext;
123 (VkImageViewCreateFlags)0, // VkImageViewCreateFlags flags;
124 image, // VkImage image;
125 imageViewType, // VkImageViewType viewType;
126 format, // VkFormat format;
127 makeComponentMappingRGBA(), // VkComponentMapping components;
128 subresourceRange, // VkImageSubresourceRange subresourceRange;
129 };
130 return createImageView(vk, vkDevice, &imageViewParams);
131 }
132
makeBufferCreateInfo(const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)133 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize bufferSize,
134 const VkBufferUsageFlags usage)
135 {
136 const VkBufferCreateInfo bufferCreateInfo =
137 {
138 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
139 DE_NULL, // const void* pNext;
140 (VkBufferCreateFlags)0, // VkBufferCreateFlags flags;
141 bufferSize, // VkDeviceSize size;
142 usage, // VkBufferUsageFlags usage;
143 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
144 0u, // deUint32 queueFamilyIndexCount;
145 DE_NULL, // const deUint32* pQueueFamilyIndices;
146 };
147 return bufferCreateInfo;
148 }
149
makeDescriptorSet(const DeviceInterface & vk,const VkDevice device,const VkDescriptorPool descriptorPool,const VkDescriptorSetLayout setLayout)150 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface& vk,
151 const VkDevice device,
152 const VkDescriptorPool descriptorPool,
153 const VkDescriptorSetLayout setLayout)
154 {
155 const VkDescriptorSetAllocateInfo allocateParams =
156 {
157 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
158 DE_NULL, // const void* pNext;
159 descriptorPool, // VkDescriptorPool descriptorPool;
160 1u, // deUint32 setLayoutCount;
161 &setLayout, // const VkDescriptorSetLayout* pSetLayouts;
162 };
163 return allocateDescriptorSet(vk, device, &allocateParams);
164 }
165
makePipelineLayout(const DeviceInterface & vk,const VkDevice device,const VkDescriptorSetLayout descriptorSetLayout)166 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface& vk,
167 const VkDevice device,
168 const VkDescriptorSetLayout descriptorSetLayout)
169 {
170 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
171 {
172 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
173 DE_NULL, // const void* pNext;
174 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags;
175 1u, // deUint32 setLayoutCount;
176 &descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts;
177 0u, // deUint32 pushConstantRangeCount;
178 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
179 };
180 return createPipelineLayout(vk, device, &pipelineLayoutParams);
181 }
182
makeCommandPool(const DeviceInterface & vk,const VkDevice device,const deUint32 queueFamilyIndex)183 Move<VkCommandPool> makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
184 {
185 const VkCommandPoolCreateInfo commandPoolParams =
186 {
187 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
188 DE_NULL, // const void* pNext;
189 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
190 queueFamilyIndex, // deUint32 queueFamilyIndex;
191 };
192 return createCommandPool(vk, device, &commandPoolParams);
193 }
194
makeCommandBuffer(const DeviceInterface & vk,const VkDevice device,const VkCommandPool commandPool)195 Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
196 {
197 const VkCommandBufferAllocateInfo bufferAllocateParams =
198 {
199 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
200 DE_NULL, // const void* pNext;
201 commandPool, // VkCommandPool commandPool;
202 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
203 1u, // deUint32 bufferCount;
204 };
205 return allocateCommandBuffer(vk, device, &bufferAllocateParams);
206 }
207
beginCommandBuffer(const DeviceInterface & vk,const VkCommandBuffer commandBuffer)208 void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
209 {
210 const VkCommandBufferBeginInfo commandBufBeginParams =
211 {
212 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
213 DE_NULL, // const void* pNext;
214 (VkCommandBufferUsageFlags)0, // VkCommandBufferUsageFlags flags;
215 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
216 };
217 VK_CHECK(vk.beginCommandBuffer(commandBuffer, &commandBufBeginParams));
218 }
219
endCommandBuffer(const DeviceInterface & vk,const VkCommandBuffer commandBuffer)220 void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
221 {
222 VK_CHECK(vk.endCommandBuffer(commandBuffer));
223 }
224
submitCommandsAndWait(const DeviceInterface & vk,const VkDevice device,const VkQueue queue,const VkCommandBuffer commandBuffer)225 void submitCommandsAndWait (const DeviceInterface& vk,
226 const VkDevice device,
227 const VkQueue queue,
228 const VkCommandBuffer commandBuffer)
229 {
230 const VkFenceCreateInfo fenceParams =
231 {
232 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
233 DE_NULL, // const void* pNext;
234 (VkFenceCreateFlags)0, // VkFenceCreateFlags flags;
235 };
236 const Unique<VkFence> fence(createFence(vk, device, &fenceParams));
237
238 const VkSubmitInfo submitInfo =
239 {
240 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
241 DE_NULL, // const void* pNext;
242 0u, // deUint32 waitSemaphoreCount;
243 DE_NULL, // const VkSemaphore* pWaitSemaphores;
244 DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask;
245 1u, // deUint32 commandBufferCount;
246 &commandBuffer, // const VkCommandBuffer* pCommandBuffers;
247 0u, // deUint32 signalSemaphoreCount;
248 DE_NULL, // const VkSemaphore* pSignalSemaphores;
249 };
250
251 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
252 VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
253 }
254
makeImageMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkImageLayout oldLayout,const VkImageLayout newLayout,const VkImage image,const VkImageSubresourceRange subresourceRange)255 VkImageMemoryBarrier makeImageMemoryBarrier (const VkAccessFlags srcAccessMask,
256 const VkAccessFlags dstAccessMask,
257 const VkImageLayout oldLayout,
258 const VkImageLayout newLayout,
259 const VkImage image,
260 const VkImageSubresourceRange subresourceRange)
261 {
262 const VkImageMemoryBarrier barrier =
263 {
264 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
265 DE_NULL, // const void* pNext;
266 srcAccessMask, // VkAccessFlags outputMask;
267 dstAccessMask, // VkAccessFlags inputMask;
268 oldLayout, // VkImageLayout oldLayout;
269 newLayout, // VkImageLayout newLayout;
270 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
271 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
272 image, // VkImage image;
273 subresourceRange, // VkImageSubresourceRange subresourceRange;
274 };
275 return barrier;
276 }
277
makeBufferMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkBuffer buffer,const VkDeviceSize offset,const VkDeviceSize bufferSizeBytes)278 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags srcAccessMask,
279 const VkAccessFlags dstAccessMask,
280 const VkBuffer buffer,
281 const VkDeviceSize offset,
282 const VkDeviceSize bufferSizeBytes)
283 {
284 const VkBufferMemoryBarrier barrier =
285 {
286 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
287 DE_NULL, // const void* pNext;
288 srcAccessMask, // VkAccessFlags srcAccessMask;
289 dstAccessMask, // VkAccessFlags dstAccessMask;
290 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
291 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
292 buffer, // VkBuffer buffer;
293 offset, // VkDeviceSize offset;
294 bufferSizeBytes, // VkDeviceSize size;
295 };
296 return barrier;
297 }
298
299 //! Basic 2D image.
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)300 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
301 {
302 const VkImageCreateInfo imageParams =
303 {
304 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
305 DE_NULL, // const void* pNext;
306 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
307 VK_IMAGE_TYPE_2D, // VkImageType imageType;
308 format, // VkFormat format;
309 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
310 1u, // deUint32 mipLevels;
311 1u, // deUint32 arrayLayers;
312 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
313 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
314 usage, // VkImageUsageFlags usage;
315 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
316 0u, // deUint32 queueFamilyIndexCount;
317 DE_NULL, // const deUint32* pQueueFamilyIndices;
318 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
319 };
320 return imageParams;
321 }
322
beginRenderPass(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkRenderPass renderPass,const VkFramebuffer framebuffer,const VkRect2D & renderArea,const tcu::Vec4 & clearColor,const float clearDepth,const deUint32 clearStencil)323 void beginRenderPass (const DeviceInterface& vk,
324 const VkCommandBuffer commandBuffer,
325 const VkRenderPass renderPass,
326 const VkFramebuffer framebuffer,
327 const VkRect2D& renderArea,
328 const tcu::Vec4& clearColor,
329 const float clearDepth,
330 const deUint32 clearStencil)
331 {
332 const VkClearValue clearValues[] =
333 {
334 makeClearValueColor(clearColor), // attachment 0
335 makeClearValueDepthStencil(clearDepth, clearStencil), // attachment 1
336 };
337
338 const VkRenderPassBeginInfo renderPassBeginInfo = {
339 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
340 DE_NULL, // const void* pNext;
341 renderPass, // VkRenderPass renderPass;
342 framebuffer, // VkFramebuffer framebuffer;
343 renderArea, // VkRect2D renderArea;
344 DE_LENGTH_OF_ARRAY(clearValues), // uint32_t clearValueCount;
345 clearValues, // const VkClearValue* pClearValues;
346 };
347
348 vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
349 }
350
endRenderPass(const DeviceInterface & vk,const VkCommandBuffer commandBuffer)351 void endRenderPass (const DeviceInterface& vk,
352 const VkCommandBuffer commandBuffer)
353 {
354 vk.cmdEndRenderPass(commandBuffer);
355 }
356
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const bool useDepthStencilAttachment,const VkFormat depthStencilFormat)357 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
358 const VkDevice device,
359 const VkFormat colorFormat,
360 const bool useDepthStencilAttachment,
361 const VkFormat depthStencilFormat)
362 {
363 const VkAttachmentDescription attachments[] =
364 {
365 // color
366 {
367 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
368 colorFormat, // VkFormat format;
369 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
370 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
371 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
372 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
373 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
374 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
375 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
376 },
377 // depth/stencil
378 {
379 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
380 depthStencilFormat, // VkFormat format;
381 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
382 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
383 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
384 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
385 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
386 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
387 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
388 }
389 };
390
391 const VkAttachmentReference unusedAttachmentReference =
392 {
393 VK_ATTACHMENT_UNUSED, // deUint32 attachment;
394 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout layout;
395 };
396
397 const VkAttachmentReference colorAttachmentReference =
398 {
399 0u, // deUint32 attachment;
400 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
401 };
402
403 const VkAttachmentReference depthStencilAttachmentReference =
404 {
405 1u, // deUint32 attachment;
406 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout;
407 };
408
409 const VkAttachmentReference* pDepthStencilAttachment = (useDepthStencilAttachment ? &depthStencilAttachmentReference : &unusedAttachmentReference);
410
411 const VkSubpassDescription subpassDescription =
412 {
413 0u, // VkSubpassDescriptionFlags flags;
414 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
415 0u, // deUint32 inputAttachmentCount;
416 DE_NULL, // const VkAttachmentReference* pInputAttachments;
417 1u, // deUint32 colorAttachmentCount;
418 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
419 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
420 pDepthStencilAttachment, // const VkAttachmentReference* pDepthStencilAttachment;
421 0u, // deUint32 preserveAttachmentCount;
422 DE_NULL // const deUint32* pPreserveAttachments;
423 };
424
425 const VkRenderPassCreateInfo renderPassInfo =
426 {
427 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
428 DE_NULL, // const void* pNext;
429 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
430 (useDepthStencilAttachment ? 2u : 1u), // deUint32 attachmentCount;
431 attachments, // const VkAttachmentDescription* pAttachments;
432 1u, // deUint32 subpassCount;
433 &subpassDescription, // const VkSubpassDescription* pSubpasses;
434 0u, // deUint32 dependencyCount;
435 DE_NULL // const VkSubpassDependency* pDependencies;
436 };
437
438 return createRenderPass(vk, device, &renderPassInfo);
439 }
440
makeFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass,const deUint32 attachmentCount,const VkImageView * pAttachments,const tcu::IVec2 size)441 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface& vk,
442 const VkDevice device,
443 const VkRenderPass renderPass,
444 const deUint32 attachmentCount,
445 const VkImageView* pAttachments,
446 const tcu::IVec2 size)
447 {
448 const VkFramebufferCreateInfo framebufferInfo = {
449 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
450 DE_NULL, // const void* pNext;
451 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags;
452 renderPass, // VkRenderPass renderPass;
453 attachmentCount, // uint32_t attachmentCount;
454 pAttachments, // const VkImageView* pAttachments;
455 static_cast<deUint32>(size.x()), // uint32_t width;
456 static_cast<deUint32>(size.y()), // uint32_t height;
457 1u, // uint32_t layers;
458 };
459
460 return createFramebuffer(vk, device, &framebufferInfo);
461 }
462
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)463 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
464 const VkDevice device,
465 const VkPipelineLayout pipelineLayout,
466 const VkRenderPass renderPass,
467 const VkShaderModule vertexModule,
468 const VkShaderModule fragmentModule,
469 const tcu::IVec2& renderSize,
470 const bool enableDepthTest,
471 const bool enableStencilTest)
472 {
473 const VkVertexInputBindingDescription vertexInputBindingDescription =
474 {
475 0u, // uint32_t binding;
476 sizeof(tcu::Vec4), // uint32_t stride; // Vertex is a 4-element vector XYZW, position only
477 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
478 };
479
480 const VkVertexInputAttributeDescription vertexInputAttributeDescription =
481 {
482 0u, // uint32_t location;
483 0u, // uint32_t binding;
484 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
485 0u, // uint32_t offset;
486 };
487
488 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
489 {
490 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
491 DE_NULL, // const void* pNext;
492 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
493 1u, // uint32_t vertexBindingDescriptionCount;
494 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
495 1u, // uint32_t vertexAttributeDescriptionCount;
496 &vertexInputAttributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
497 };
498
499 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
500 {
501 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
502 DE_NULL, // const void* pNext;
503 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
504 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
505 VK_FALSE, // VkBool32 primitiveRestartEnable;
506 };
507
508 const VkViewport viewport = makeViewport(
509 0.0f, 0.0f,
510 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
511 0.0f, 1.0f);
512
513 const VkRect2D scissor = {
514 makeOffset2D(0, 0),
515 makeExtent2D(renderSize.x(), renderSize.y()),
516 };
517
518 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
519 {
520 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
521 DE_NULL, // const void* pNext;
522 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
523 1u, // uint32_t viewportCount;
524 &viewport, // const VkViewport* pViewports;
525 1u, // uint32_t scissorCount;
526 &scissor, // const VkRect2D* pScissors;
527 };
528
529 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
530 {
531 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
532 DE_NULL, // const void* pNext;
533 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
534 VK_FALSE, // VkBool32 depthClampEnable;
535 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
536 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
537 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
538 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
539 VK_FALSE, // VkBool32 depthBiasEnable;
540 0.0f, // float depthBiasConstantFactor;
541 0.0f, // float depthBiasClamp;
542 0.0f, // float depthBiasSlopeFactor;
543 1.0f, // float lineWidth;
544 };
545
546 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
547 {
548 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
549 DE_NULL, // const void* pNext;
550 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
551 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
552 VK_FALSE, // VkBool32 sampleShadingEnable;
553 0.0f, // float minSampleShading;
554 DE_NULL, // const VkSampleMask* pSampleMask;
555 VK_FALSE, // VkBool32 alphaToCoverageEnable;
556 VK_FALSE // VkBool32 alphaToOneEnable;
557 };
558
559 const VkStencilOpState stencilOpState = makeStencilOpState(
560 VK_STENCIL_OP_KEEP, // stencil fail
561 VK_STENCIL_OP_KEEP, // depth & stencil pass
562 VK_STENCIL_OP_KEEP, // depth only fail
563 VK_COMPARE_OP_EQUAL, // compare op
564 1u, // compare mask
565 1u, // write mask
566 1u); // reference
567
568 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
569 {
570 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
571 DE_NULL, // const void* pNext;
572 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
573 enableDepthTest, // VkBool32 depthTestEnable;
574 VK_TRUE, // VkBool32 depthWriteEnable;
575 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
576 VK_FALSE, // VkBool32 depthBoundsTestEnable;
577 enableStencilTest, // VkBool32 stencilTestEnable;
578 stencilOpState, // VkStencilOpState front;
579 stencilOpState, // VkStencilOpState back;
580 0.0f, // float minDepthBounds;
581 1.0f, // float maxDepthBounds;
582 };
583
584 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
585 // Number of blend attachments must equal the number of color attachments.
586 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
587 {
588 VK_FALSE, // VkBool32 blendEnable;
589 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
590 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
591 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
592 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
593 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
594 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
595 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
596 };
597
598 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
599 {
600 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
601 DE_NULL, // const void* pNext;
602 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
603 VK_FALSE, // VkBool32 logicOpEnable;
604 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
605 1u, // deUint32 attachmentCount;
606 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
607 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
608 };
609
610 const VkPipelineShaderStageCreateInfo pShaderStages[] =
611 {
612 {
613 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
614 DE_NULL, // const void* pNext;
615 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
616 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
617 vertexModule, // VkShaderModule module;
618 "main", // const char* pName;
619 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
620 },
621 {
622 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
623 DE_NULL, // const void* pNext;
624 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
625 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
626 fragmentModule, // VkShaderModule module;
627 "main", // const char* pName;
628 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
629 }
630 };
631
632 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
633 {
634 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
635 DE_NULL, // const void* pNext;
636 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
637 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
638 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
639 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
640 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
641 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
642 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
643 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
644 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
645 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
646 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
647 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
648 pipelineLayout, // VkPipelineLayout layout;
649 renderPass, // VkRenderPass renderPass;
650 0u, // deUint32 subpass;
651 DE_NULL, // VkPipeline basePipelineHandle;
652 0, // deInt32 basePipelineIndex;
653 };
654
655 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
656 }
657
makeBufferImageCopy(const VkImageAspectFlags aspectFlags,const tcu::IVec2 & renderSize)658 VkBufferImageCopy makeBufferImageCopy (const VkImageAspectFlags aspectFlags, const tcu::IVec2& renderSize)
659 {
660 const VkBufferImageCopy copyParams =
661 {
662 0ull, // VkDeviceSize bufferOffset;
663 0u, // deUint32 bufferRowLength;
664 0u, // deUint32 bufferImageHeight;
665 makeImageSubresourceLayers(aspectFlags, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource;
666 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
667 makeExtent3D(renderSize.x(), renderSize.y(), 1u), // VkExtent3D imageExtent;
668 };
669 return copyParams;
670 }
671
commandClearStencilAttachment(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkOffset2D & offset,const VkExtent2D & extent,const deUint32 clearValue)672 void commandClearStencilAttachment (const DeviceInterface& vk,
673 const VkCommandBuffer commandBuffer,
674 const VkOffset2D& offset,
675 const VkExtent2D& extent,
676 const deUint32 clearValue)
677 {
678 const VkClearAttachment stencilAttachment =
679 {
680 VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask;
681 0u, // uint32_t colorAttachment;
682 makeClearValueDepthStencil(0.0f, clearValue), // VkClearValue clearValue;
683 };
684
685 const VkClearRect rect =
686 {
687 { offset, extent }, // VkRect2D rect;
688 0u, // uint32_t baseArrayLayer;
689 1u, // uint32_t layerCount;
690 };
691
692 vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
693 }
694
getImageAspectFlags(const VkFormat format)695 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
696 {
697 const tcu::TextureFormat tcuFormat = mapVkFormat(format);
698
699 if (tcuFormat.order == tcu::TextureFormat::DS) return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
700 else if (tcuFormat.order == tcu::TextureFormat::D) return VK_IMAGE_ASPECT_DEPTH_BIT;
701 else if (tcuFormat.order == tcu::TextureFormat::S) return VK_IMAGE_ASPECT_STENCIL_BIT;
702
703 DE_ASSERT(false);
704 return 0u;
705 }
706
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const VkFormat format)707 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
708 {
709 VkFormatProperties formatProps;
710 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
711 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
712 }
713
pickSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const deUint32 numFormats,const VkFormat * pFormats)714 VkFormat pickSupportedDepthStencilFormat (const InstanceInterface& instanceInterface,
715 const VkPhysicalDevice device,
716 const deUint32 numFormats,
717 const VkFormat* pFormats)
718 {
719 for (deUint32 i = 0; i < numFormats; ++i)
720 if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
721 return pFormats[i];
722 return VK_FORMAT_UNDEFINED;
723 }
724
725 enum Flags
726 {
727 FLAG_TEST_DEPTH = 1u << 0,
728 FLAG_TEST_STENCIL = 1u << 1,
729 FLAG_DONT_USE_TEST_ATTACHMENT = 1u << 2,
730 FLAG_DONT_USE_EARLY_FRAGMENT_TESTS = 1u << 3,
731 };
732
733 class EarlyFragmentTest : public TestCase
734 {
735 public:
736 EarlyFragmentTest (tcu::TestContext& testCtx,
737 const std::string name,
738 const deUint32 flags);
739
740 void initPrograms (SourceCollections& programCollection) const;
741 TestInstance* createInstance (Context& context) const;
742
743 private:
744 const deUint32 m_flags;
745 };
746
EarlyFragmentTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags)747 EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
748 : TestCase (testCtx, name, "")
749 , m_flags (flags)
750 {
751 }
752
initPrograms(SourceCollections & programCollection) const753 void EarlyFragmentTest::initPrograms (SourceCollections& programCollection) const
754 {
755 // Vertex
756 {
757 std::ostringstream src;
758 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
759 << "\n"
760 << "layout(location = 0) in highp vec4 position;\n"
761 << "\n"
762 << "void main (void)\n"
763 << "{\n"
764 << " gl_Position = position;\n"
765 << "}\n";
766
767 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
768 }
769
770 // Fragment
771 {
772 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
773 std::ostringstream src;
774 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
775 << "\n"
776 << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
777 << "layout(location = 0) out highp vec4 fragColor;\n"
778 << "\n"
779 << "layout(binding = 0) coherent buffer Output {\n"
780 << " uint result;\n"
781 << "} sb_out;\n"
782 << "\n"
783 << "void main (void)\n"
784 << "{\n"
785 << " atomicAdd(sb_out.result, 1u);\n"
786 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
787 << "}\n";
788
789 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
790 }
791 }
792
793 class EarlyFragmentTestInstance : public TestInstance
794 {
795 public:
796 EarlyFragmentTestInstance (Context& context, const deUint32 flags);
797
798 tcu::TestStatus iterate (void);
799
800 private:
801 enum TestMode
802 {
803 MODE_INVALID,
804 MODE_DEPTH,
805 MODE_STENCIL,
806 };
807
808 const TestMode m_testMode;
809 const bool m_useTestAttachment;
810 const bool m_useEarlyTests;
811 };
812
EarlyFragmentTestInstance(Context & context,const deUint32 flags)813 EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags)
814 : TestInstance (context)
815 , m_testMode (flags & FLAG_TEST_DEPTH ? MODE_DEPTH :
816 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
817 , m_useTestAttachment ((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
818 , m_useEarlyTests ((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
819 {
820 DE_ASSERT(m_testMode != MODE_INVALID);
821 }
822
iterate(void)823 tcu::TestStatus EarlyFragmentTestInstance::iterate (void)
824 {
825 const DeviceInterface& vk = m_context.getDeviceInterface();
826 const InstanceInterface& vki = m_context.getInstanceInterface();
827 const VkDevice device = m_context.getDevice();
828 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
829 const VkQueue queue = m_context.getUniversalQueue();
830 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
831 Allocator& allocator = m_context.getDefaultAllocator();
832
833 // Color attachment
834
835 const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
836 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
837 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
838 const Image colorImage (vk, device, allocator, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::Any);
839 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
840
841 // Test attachment (depth or stencil)
842 static const VkFormat stencilFormats[] =
843 {
844 // One of the following formats must be supported, as per spec requirement.
845 VK_FORMAT_S8_UINT,
846 VK_FORMAT_D16_UNORM_S8_UINT,
847 VK_FORMAT_D24_UNORM_S8_UINT,
848 VK_FORMAT_D32_SFLOAT_S8_UINT,
849 };
850
851 const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
852 : VK_FORMAT_D16_UNORM); // spec requires this format to be supported
853 if (testFormat == VK_FORMAT_UNDEFINED)
854 return tcu::TestStatus::fail("Required depth/stencil format not supported");
855
856 if (m_useTestAttachment)
857 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
858
859 const VkImageSubresourceRange testSubresourceRange = makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
860 const Image testImage (vk, device, allocator, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT), MemoryRequirement::Any);
861 const Unique<VkImageView> testImageView (makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
862 const VkImageView attachmentImages[] = { *colorImageView, *testImageView };
863 const deUint32 numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
864
865 // Vertex buffer
866
867 const deUint32 numVertices = 6;
868 const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
869 const Buffer vertexBuffer (vk, device, allocator, makeBufferCreateInfo(vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible);
870
871 {
872 const Allocation& alloc = vertexBuffer.getAllocation();
873 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(alloc.getHostPtr());
874
875 pVertices[0] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f);
876 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
877 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
878
879 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
880 pVertices[4] = tcu::Vec4( 1.0f, 1.0f, 1.0f, 1.0f);
881 pVertices[5] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f);
882
883 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), vertexBufferSizeBytes);
884 // No barrier needed, flushed memory is automatically visible
885 }
886
887 // Result buffer
888
889 const VkDeviceSize resultBufferSizeBytes = sizeof(deUint32);
890 const Buffer resultBuffer(vk, device, allocator, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
891
892 {
893 const Allocation& alloc = resultBuffer.getAllocation();
894 deUint32* const pData = static_cast<deUint32*>(alloc.getHostPtr());
895
896 *pData = 0;
897 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), resultBufferSizeBytes);
898 }
899
900 // Render result buffer (to retrieve color attachment contents)
901
902 const VkDeviceSize colorBufferSizeBytes = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
903 const Buffer colorBuffer (vk, device, allocator, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible);
904
905 // Descriptors
906
907 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
908 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
909 .build(vk, device));
910
911 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
912 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
913 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
914
915 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
916 const VkDescriptorBufferInfo resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
917
918 DescriptorSetUpdateBuilder()
919 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
920 .update(vk, device);
921
922 // Pipeline
923
924 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
925 const Unique<VkShaderModule> fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
926 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
927 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize));
928 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
929 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
930 (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL)));
931 const Unique<VkCommandPool> cmdPool (makeCommandPool(vk, device, queueFamilyIndex));
932 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
933
934 // Draw commands
935
936 {
937 const VkRect2D renderArea = {
938 makeOffset2D(0, 0),
939 makeExtent2D(renderSize.x(), renderSize.y()),
940 };
941 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
942 const VkDeviceSize vertexBufferOffset = 0ull;
943
944 beginCommandBuffer(vk, *cmdBuffer);
945
946 {
947 const VkImageMemoryBarrier barriers[] = {
948 makeImageMemoryBarrier(
949 0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
950 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
951 *colorImage, colorSubresourceRange),
952 makeImageMemoryBarrier(
953 0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
954 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
955 *testImage, testSubresourceRange),
956 };
957
958 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
959 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
960 }
961
962 // Will clear the attachments with specified depth and stencil values.
963 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
964
965 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
966 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
967 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
968
969 // Mask half of the attachment image with value that will pass the stencil test.
970 if (m_useTestAttachment && m_testMode == MODE_STENCIL)
971 commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
972
973 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
974 endRenderPass(vk, *cmdBuffer);
975
976 {
977 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
978 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, resultBufferSizeBytes);
979
980 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
981 0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL);
982
983 const VkImageMemoryBarrier preCopyColorImageBarrier = makeImageMemoryBarrier(
984 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
985 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
986 *colorImage, colorSubresourceRange);
987
988 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
989 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyColorImageBarrier);
990
991 const VkBufferImageCopy copyRegion = makeBufferImageCopy(VK_IMAGE_ASPECT_COLOR_BIT, renderSize);
992 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ©Region);
993
994 const VkBufferMemoryBarrier postCopyColorBufferBarrier = makeBufferMemoryBarrier(
995 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, colorBufferSizeBytes);
996
997 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
998 0u, DE_NULL, 1u, &postCopyColorBufferBarrier, 0u, DE_NULL);
999 }
1000
1001 endCommandBuffer(vk, *cmdBuffer);
1002 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1003 }
1004
1005 // Log result image
1006 {
1007 const Allocation& alloc = colorBuffer.getAllocation();
1008 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), colorBufferSizeBytes);
1009
1010 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, alloc.getHostPtr());
1011
1012 tcu::TestLog& log = m_context.getTestContext().getLog();
1013 log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
1014 }
1015
1016 // Verify results
1017 {
1018 const Allocation& alloc = resultBuffer.getAllocation();
1019 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), resultBufferSizeBytes);
1020
1021 const int actualCounter = *static_cast<deInt32*>(alloc.getHostPtr());
1022 const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
1023 const int expectedCounter = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
1024 const int tolerance = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3 : 0;
1025 const int expectedMin = de::max(0, expectedCounter - tolerance);
1026 const int expectedMax = expectedCounter + tolerance;
1027
1028 tcu::TestLog& log = m_context.getTestContext().getLog();
1029 log << tcu::TestLog::Message << "Expected value"
1030 << (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
1031 << tcu::TestLog::EndMessage;
1032 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
1033
1034 if (expectedMin <= actualCounter && actualCounter <= expectedMax)
1035 return tcu::TestStatus::pass("Success");
1036 else
1037 return tcu::TestStatus::fail("Value out of range");
1038 }
1039 }
1040
createInstance(Context & context) const1041 TestInstance* EarlyFragmentTest::createInstance (Context& context) const
1042 {
1043 // Check required features
1044 {
1045 VkPhysicalDeviceFeatures features;
1046 context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
1047
1048 // SSBO writes in fragment shader
1049 if (!features.fragmentStoresAndAtomics)
1050 throw tcu::NotSupportedError("Missing required feature: fragmentStoresAndAtomics");
1051 }
1052
1053 return new EarlyFragmentTestInstance(context, m_flags);
1054 }
1055
1056 } // anonymous ns
1057
createEarlyFragmentTests(tcu::TestContext & testCtx)1058 tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
1059 {
1060 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases"));
1061
1062 static const struct
1063 {
1064 std::string caseName;
1065 deUint32 flags;
1066 } cases[] =
1067 {
1068 { "no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
1069 { "no_early_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
1070 { "early_fragment_tests_depth", FLAG_TEST_DEPTH },
1071 { "early_fragment_tests_stencil", FLAG_TEST_STENCIL },
1072 { "no_early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT },
1073 { "no_early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT },
1074 { "early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_TEST_ATTACHMENT },
1075 { "early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT },
1076 };
1077
1078 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
1079 testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
1080
1081 return testGroup.release();
1082 }
1083
1084 } // pipeline
1085 } // vkt
1086