1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2020 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file vktSynchronizationNoneStageTests.cpp
21 * \brief Tests for VK_PIPELINE_STAGE_NONE{_2}_KHR that iterate over each writable layout
22 and over each readable layout. Data to tested image is writen using method
23 appropriate for the writable layout and read via readable layout appropriate method.
24 Betwean read and write operation there are bariers that use none stage.
25 Implemented tests are also testing generalized layouts (VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR,
26 VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR) and access flags (MEMORY_ACCESS_READ|WRITE_BIT) to
27 test contextual synchronization introduced with VK_KHR_synchronization2 extension.
28 *//*--------------------------------------------------------------------*/
29
30 #include "vktSynchronizationNoneStageTests.hpp"
31 #include "vktSynchronizationOperation.hpp"
32 #include "vktSynchronizationUtil.hpp"
33 #include "vktTestCase.hpp"
34
35 #include "vkBuilderUtil.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41
42 #include "tcuImageCompare.hpp"
43 #include "tcuTextureUtil.hpp"
44 #include "tcuTestLog.hpp"
45 #include "tcuStringTemplate.hpp"
46
47 #include "deUniquePtr.hpp"
48
49 #include <vector>
50
51 namespace vkt
52 {
53 namespace synchronization
54 {
55
56 using namespace vk;
57 using namespace de;
58 using namespace tcu;
59
60 namespace
61 {
62
63 static const uint32_t IMAGE_ASPECT_DEPTH_STENCIL = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
64 static const uint32_t IMAGE_ASPECT_ALL = 0u;
65
66 struct TestParams
67 {
68 SynchronizationType type;
69 bool useGenericAccessFlags;
70 VkImageLayout writeLayout;
71 VkImageAspectFlags writeAspect;
72 VkImageLayout readLayout;
73 VkImageAspectFlags readAspect;
74 };
75
76 // Helper class representing image
77 class ImageWrapper
78 {
79 public:
80 ImageWrapper() = default;
81 void create(Context &context, SimpleAllocator &alloc, VkFormat format, VkExtent3D extent, VkImageUsageFlags usage);
82
83 public:
84 Move<VkImage> handle;
85 MovePtr<Allocation> memory;
86 };
87
create(Context & context,SimpleAllocator & alloc,VkFormat format,VkExtent3D extent,VkImageUsageFlags usage)88 void ImageWrapper::create(Context &context, SimpleAllocator &alloc, VkFormat format, VkExtent3D extent,
89 VkImageUsageFlags usage)
90 {
91 const DeviceInterface &vk = context.getDeviceInterface();
92 const VkDevice &device = context.getDevice();
93 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
94 const VkImageCreateInfo imageParams{
95 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
96 DE_NULL, // pNext
97 0u, // flags
98 VK_IMAGE_TYPE_2D, // imageType
99 format, // format
100 extent, // extent
101 1u, // mipLevels
102 1u, // arraySize
103 VK_SAMPLE_COUNT_1_BIT, // samples
104 VK_IMAGE_TILING_OPTIMAL, // tiling
105 usage, // usage
106 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
107 1u, // queueFamilyIndexCount
108 &queueFamilyIndex, // pQueueFamilyIndices
109 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
110 };
111
112 handle = createImage(vk, device, &imageParams);
113 memory = alloc.allocate(getImageMemoryRequirements(vk, device, *handle), MemoryRequirement::Any);
114
115 vk.bindImageMemory(device, *handle, memory->getMemory(), memory->getOffset());
116 }
117
118 // Helper class representing buffer
119 class BufferWrapper
120 {
121 public:
122 BufferWrapper() = default;
123 void create(Context &context, SimpleAllocator &alloc, VkDeviceSize size, VkBufferUsageFlags usage);
124
125 public:
126 Move<VkBuffer> handle;
127 MovePtr<Allocation> memory;
128 };
129
create(Context & context,SimpleAllocator & alloc,VkDeviceSize size,VkBufferUsageFlags usage)130 void BufferWrapper::create(Context &context, SimpleAllocator &alloc, VkDeviceSize size, VkBufferUsageFlags usage)
131 {
132 const DeviceInterface &vk = context.getDeviceInterface();
133 const VkDevice &device = context.getDevice();
134 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(size, usage);
135
136 handle = createBuffer(vk, device, &bufferCreateInfo);
137 memory = alloc.allocate(getBufferMemoryRequirements(vk, device, *handle), MemoryRequirement::HostVisible);
138
139 VK_CHECK(vk.bindBufferMemory(device, *handle, memory->getMemory(), memory->getOffset()));
140 }
141
142 class NoneStageTestInstance : public vkt::TestInstance
143 {
144 public:
145 NoneStageTestInstance(Context &context, const TestParams &testParams);
146 virtual ~NoneStageTestInstance(void) = default;
147
148 tcu::TestStatus iterate(void) override;
149
150 protected:
151 VkAccessFlags2KHR getAccessFlag(VkAccessFlags2KHR access);
152 VkBufferImageCopy buildCopyRegion(VkExtent3D extent, VkImageAspectFlags aspect);
153 void buildVertexBuffer(void);
154 Move<VkRenderPass> buildBasicRenderPass(VkFormat outputFormat, VkImageLayout outputLayout,
155 VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE);
156 Move<VkRenderPass> buildComplexRenderPass(VkFormat intermediateFormat, VkImageLayout intermediateLayout,
157 VkImageAspectFlags intermediateAspect, VkFormat outputFormat,
158 VkImageLayout outputLayout);
159 Move<VkImageView> buildImageView(VkImage image, VkFormat format, const VkImageSubresourceRange &subresourceRange);
160 Move<VkFramebuffer> buildFramebuffer(VkRenderPass renderPass, const VkImageView *outView1,
161 const VkImageView *outView2 = DE_NULL);
162 Move<VkSampler> buildSampler(void);
163 Move<VkDescriptorSetLayout> buildDescriptorSetLayout(VkDescriptorType descriptorType);
164 Move<VkDescriptorPool> buildDescriptorPool(VkDescriptorType descriptorType);
165 Move<VkDescriptorSet> buildDescriptorSet(VkDescriptorPool descriptorPool, VkDescriptorSetLayout descriptorSetLayout,
166 VkDescriptorType descriptorType, VkImageView inputView,
167 VkImageLayout inputLayout, const VkSampler *sampler = DE_NULL);
168 Move<VkPipeline> buildPipeline(uint32_t subpass, VkImageAspectFlags resultAspect, VkPipelineLayout pipelineLayout,
169 VkShaderModule vertShaderModule, VkShaderModule fragShaderModule,
170 VkRenderPass renderPass);
171 bool verifyResult(const PixelBufferAccess &reference, const PixelBufferAccess &result);
172
173 private:
174 const TestParams m_testParams;
175
176 VkFormat m_referenceImageFormat;
177 VkFormat m_transitionImageFormat;
178 VkFormat m_readImageFormat;
179 VkImageSubresourceRange m_referenceSubresourceRange;
180 VkImageSubresourceRange m_transitionSubresourceRange;
181 VkImageSubresourceRange m_readSubresourceRange;
182 VkImageAspectFlags m_transitionImageAspect;
183
184 VkExtent3D m_imageExtent;
185 VkImageLayout m_writeRenderPassOutputLayout;
186
187 // flag indicating that graphics pipeline is constructed to write data to tested image
188 bool m_usePipelineToWrite;
189
190 // flag indicating that graphics pipeline is constructed to read data from tested image
191 bool m_usePipelineToRead;
192
193 // flag indicating that write pipeline should be constructed in a special way to fill stencil buffer
194 bool m_useStencilDuringWrite;
195
196 // flag indicating that read pipeline should be constructed in a special way to use input attachment as a data source
197 bool m_useInputAttachmentToRead;
198
199 VkPipelineStageFlags2KHR m_srcStageToNoneStageMask;
200 VkAccessFlags2KHR m_srcAccessToNoneAccessMask;
201 VkPipelineStageFlags2KHR m_dstStageFromNoneStageMask;
202 VkAccessFlags2KHR m_dstAccessFromNoneAccessMask;
203
204 SimpleAllocator m_alloc;
205
206 ImageWrapper m_referenceImage;
207 VkImageUsageFlags m_referenceImageUsage;
208
209 // objects/variables initialized only when needed
210 ImageWrapper m_imageToWrite;
211 VkImageUsageFlags m_imageToWriteUsage;
212
213 ImageWrapper m_imageToRead;
214
215 BufferWrapper m_vertexBuffer;
216 std::vector<Move<VkImageView>> m_attachmentViews;
217
218 std::string m_writeFragShaderName;
219 Move<VkShaderModule> m_writeVertShaderModule;
220 Move<VkShaderModule> m_writeFragShaderModule;
221 Move<VkRenderPass> m_writeRenderPass;
222 Move<VkSampler> m_writeSampler;
223 Move<VkDescriptorSetLayout> m_writeDescriptorSetLayout;
224 Move<VkDescriptorPool> m_writeDescriptorPool;
225 Move<VkDescriptorSet> m_writeDescriptorSet;
226 Move<VkPipelineLayout> m_writePipelineLayout;
227 Move<VkPipeline> m_writePipeline;
228 Move<VkFramebuffer> m_writeFramebuffer;
229
230 std::string m_readFragShaderName;
231 Move<VkShaderModule> m_readVertShaderModule;
232 Move<VkShaderModule> m_readFragShaderModule;
233 Move<VkShaderModule> m_readFragShaderModule2;
234 Move<VkRenderPass> m_readRenderPass;
235 Move<VkSampler> m_readSampler;
236 Move<VkDescriptorSetLayout> m_readDescriptorSetLayout;
237 Move<VkDescriptorPool> m_readDescriptorPool;
238 Move<VkDescriptorSet> m_readDescriptorSet;
239 Move<VkPipelineLayout> m_readPipelineLayout;
240 Move<VkPipeline> m_readPipeline;
241 Move<VkFramebuffer> m_readFramebuffer;
242 };
243
NoneStageTestInstance(Context & context,const TestParams & testParams)244 NoneStageTestInstance::NoneStageTestInstance(Context &context, const TestParams &testParams)
245 : vkt::TestInstance(context)
246 , m_testParams(testParams)
247 , m_imageExtent{32, 32, 1}
248 , m_alloc(m_context.getDeviceInterface(), m_context.getDevice(),
249 getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()))
250 {
251 // note: for clarity whole configuration of whats going on in iterate method was moved here
252
253 const auto writeLayout = m_testParams.writeLayout;
254 const auto writeAspect = m_testParams.writeAspect;
255 const auto readLayout = m_testParams.readLayout;
256 const auto readAspect = m_testParams.readAspect;
257
258 // When testing depth stencil combined images, the stencil aspect is only tested when depth aspect is in ATTACHMENT_OPTIMAL layout.
259 // - it is invalid to read depth using sampler or input attachment in such layout
260 const auto readStencilFromCombinedDepthStencil =
261 (readLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL);
262
263 // select format that will be used for test
264 if ((writeAspect == VK_IMAGE_ASPECT_DEPTH_BIT) || (readAspect == VK_IMAGE_ASPECT_DEPTH_BIT))
265 {
266 m_transitionImageFormat = VK_FORMAT_D32_SFLOAT;
267 m_transitionImageAspect = VK_IMAGE_ASPECT_DEPTH_BIT;
268 m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
269 }
270 else if ((writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT) || (readAspect == VK_IMAGE_ASPECT_STENCIL_BIT))
271 {
272 m_transitionImageFormat = VK_FORMAT_S8_UINT;
273 m_transitionImageAspect = VK_IMAGE_ASPECT_STENCIL_BIT;
274 m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
275 }
276 else if ((writeAspect == IMAGE_ASPECT_DEPTH_STENCIL) || (readAspect == IMAGE_ASPECT_DEPTH_STENCIL))
277 {
278 m_transitionImageFormat = VK_FORMAT_D24_UNORM_S8_UINT;
279 m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
280
281 if (readStencilFromCombinedDepthStencil)
282 {
283 m_transitionImageAspect = VK_IMAGE_ASPECT_STENCIL_BIT;
284 }
285 else
286 {
287 // note: in test we focus only on depth aspect; no need to check both in those cases
288 m_transitionImageAspect = VK_IMAGE_ASPECT_DEPTH_BIT;
289 }
290 }
291 else
292 {
293 m_transitionImageFormat = VK_FORMAT_R8G8B8A8_UNORM;
294 m_transitionImageAspect = VK_IMAGE_ASPECT_COLOR_BIT;
295 m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
296 }
297
298 m_referenceSubresourceRange = {m_transitionImageAspect, 0u, 1u, 0u, 1u};
299 m_transitionSubresourceRange = {m_transitionImageAspect, 0u, 1u, 0u, 1u};
300 m_readSubresourceRange = {m_transitionImageAspect, 0u, 1u, 0u, 1u};
301 m_referenceImageFormat = m_transitionImageFormat;
302 m_readImageFormat = m_transitionImageFormat;
303 m_referenceImageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
304 m_imageToWriteUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
305
306 // pipeline is not created for transfer and general layouts (general layouts in tests follow same path as transfer layouts)
307 m_usePipelineToWrite =
308 (writeLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) && (writeLayout != VK_IMAGE_LAYOUT_GENERAL);
309 m_usePipelineToRead =
310 (readLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) && (readLayout != VK_IMAGE_LAYOUT_GENERAL);
311 m_useStencilDuringWrite = false;
312
313 m_srcStageToNoneStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
314 m_srcAccessToNoneAccessMask = getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR);
315 m_dstStageFromNoneStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
316 m_dstAccessFromNoneAccessMask = getAccessFlag(VK_ACCESS_2_TRANSFER_READ_BIT_KHR);
317
318 // when graphics pipelines are not created only image with gradient is used for test
319 if (!m_usePipelineToWrite && !m_usePipelineToRead)
320 {
321 m_referenceImageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
322 return;
323 }
324
325 if (m_usePipelineToWrite)
326 {
327 // depth/stencil layouts need diferent configuration
328 if (writeAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
329 {
330 if ((writeAspect & VK_IMAGE_ASPECT_DEPTH_BIT) && !readStencilFromCombinedDepthStencil)
331 {
332 m_referenceImageFormat = VK_FORMAT_R32_SFLOAT;
333 m_referenceImageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
334 m_referenceSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
335 m_writeFragShaderName = "frag-color-to-depth";
336 }
337 else
338 {
339 m_referenceImageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
340 m_useStencilDuringWrite = true;
341 m_writeFragShaderName = "frag-color-to-stencil";
342 }
343
344 m_srcStageToNoneStageMask = VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR;
345 m_srcAccessToNoneAccessMask = getAccessFlag(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR);
346 m_imageToWriteUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
347 }
348 else
349 {
350 m_referenceImageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
351 m_srcStageToNoneStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR;
352 m_srcAccessToNoneAccessMask = getAccessFlag(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR);
353 m_writeFragShaderName = "frag-color";
354 m_imageToWriteUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
355 }
356 }
357
358 if (m_usePipelineToRead)
359 {
360 m_dstStageFromNoneStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR;
361 m_dstAccessFromNoneAccessMask = getAccessFlag(VK_ACCESS_2_SHADER_READ_BIT_KHR);
362
363 m_readSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
364 if (((readAspect | writeAspect) & VK_IMAGE_ASPECT_DEPTH_BIT) && !readStencilFromCombinedDepthStencil)
365 m_readImageFormat = VK_FORMAT_R32_SFLOAT;
366 else if ((readAspect | writeAspect) & VK_IMAGE_ASPECT_STENCIL_BIT)
367 m_readImageFormat = VK_FORMAT_R8_UINT;
368
369 // for layouts that operate on depth or stencil (not depth_stencil) use input attachment to read
370 if ((readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) &&
371 (readAspect != IMAGE_ASPECT_DEPTH_STENCIL))
372 {
373 m_useInputAttachmentToRead = true;
374 m_readFragShaderName = "frag-depth-or-stencil-to-color";
375 m_imageToWriteUsage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
376 m_dstAccessFromNoneAccessMask = getAccessFlag(VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR);
377
378 if (!m_usePipelineToWrite)
379 m_referenceImageUsage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
380 }
381 else // use image sampler for color and depth_stencil layouts
382 {
383 m_useInputAttachmentToRead = false;
384 m_readFragShaderName = "frag-color";
385 m_referenceImageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
386 m_imageToWriteUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
387
388 // for depth_stencil layouts we need to have depth_stencil_attachment usage
389 if (!m_usePipelineToWrite && (readAspect & VK_IMAGE_ASPECT_STENCIL_BIT))
390 m_referenceImageUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
391
392 // when we read stencil as color we need to use usampler2D
393 if ((readAspect | writeAspect) == VK_IMAGE_ASPECT_STENCIL_BIT ||
394 (readAspect == IMAGE_ASPECT_DEPTH_STENCIL && readStencilFromCombinedDepthStencil))
395 m_readFragShaderName = "frag-stencil-to-color";
396 }
397 if (m_useInputAttachmentToRead && (m_testParams.readLayout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
398 m_testParams.readLayout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL))
399 m_referenceImageUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
400 }
401 }
402
getAccessFlag(VkAccessFlags2KHR access)403 VkAccessFlags2KHR NoneStageTestInstance::getAccessFlag(VkAccessFlags2KHR access)
404 {
405 if (m_testParams.useGenericAccessFlags)
406 {
407 switch (access)
408 {
409 case VK_ACCESS_2_HOST_READ_BIT_KHR:
410 case VK_ACCESS_2_TRANSFER_READ_BIT_KHR:
411 case VK_ACCESS_2_SHADER_READ_BIT_KHR:
412 case VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR:
413 return VK_ACCESS_2_MEMORY_READ_BIT_KHR;
414
415 case VK_ACCESS_2_HOST_WRITE_BIT_KHR:
416 case VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR:
417 case VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR:
418 case VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR:
419 return VK_ACCESS_2_MEMORY_WRITE_BIT_KHR;
420
421 default:
422 TCU_THROW(TestError, "Unhandled access flag");
423 }
424 }
425 return access;
426 }
427
buildCopyRegion(VkExtent3D extent,VkImageAspectFlags aspect)428 VkBufferImageCopy NoneStageTestInstance::buildCopyRegion(VkExtent3D extent, VkImageAspectFlags aspect)
429 {
430 return {
431 0u, // VkDeviceSize bufferOffset
432 extent.width, // uint32_t bufferRowLength
433 extent.height, // uint32_t bufferImageHeight
434 {aspect, 0u, 0u, 1u}, // VkImageSubresourceLayers imageSubresource
435 {0, 0, 0}, // VkOffset3D imageOffset
436 extent // VkExtent3D imageExtent
437 };
438 }
439
buildVertexBuffer()440 void NoneStageTestInstance::buildVertexBuffer()
441 {
442 const DeviceInterface &vk = m_context.getDeviceInterface();
443 const VkDevice &device = m_context.getDevice();
444
445 std::vector<float> vertices{
446 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f,
447 };
448 m_vertexBuffer.create(m_context, m_alloc, sizeof(float) * vertices.size(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
449
450 deMemcpy(m_vertexBuffer.memory->getHostPtr(), vertices.data(), vertices.size() * sizeof(float));
451 flushAlloc(vk, device, *m_vertexBuffer.memory);
452 }
453
buildBasicRenderPass(VkFormat outputFormat,VkImageLayout outputLayout,VkAttachmentLoadOp loadOp)454 Move<VkRenderPass> NoneStageTestInstance::buildBasicRenderPass(VkFormat outputFormat, VkImageLayout outputLayout,
455 VkAttachmentLoadOp loadOp)
456 {
457 // output color/depth attachment
458 VkAttachmentDescription2 attachmentDescription{
459 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType
460 DE_NULL, // const void* pNext
461 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
462 outputFormat, // VkFormat format
463 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
464 loadOp, // VkAttachmentLoadOp loadOp
465 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
466 loadOp, // VkAttachmentLoadOp stencilLoadOp
467 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp
468 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
469 outputLayout // VkImageLayout finalLayout
470 };
471
472 VkImageAspectFlags imageAspect = getImageAspectFlags(mapVkFormat(outputFormat));
473 VkAttachmentReference2 attachmentRef{VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, DE_NULL, 0u, outputLayout,
474 imageAspect};
475
476 VkAttachmentReference2 *pColorAttachment = DE_NULL;
477 VkAttachmentReference2 *pDepthStencilAttachment = DE_NULL;
478 if (imageAspect == VK_IMAGE_ASPECT_COLOR_BIT)
479 pColorAttachment = &attachmentRef;
480 else
481 pDepthStencilAttachment = &attachmentRef;
482
483 VkSubpassDescription2 subpassDescription{
484 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
485 DE_NULL,
486 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
487 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
488 0u, // uint32_t viewMask
489 0u, // uint32_t inputAttachmentCount
490 DE_NULL, // const VkAttachmentReference2* pInputAttachments
491 !!pColorAttachment, // uint32_t colorAttachmentCount
492 pColorAttachment, // const VkAttachmentReference2* pColorAttachments
493 DE_NULL, // const VkAttachmentReference2* pResolveAttachments
494 pDepthStencilAttachment, // const VkAttachmentReference2* pDepthStencilAttachment
495 0u, // uint32_t preserveAttachmentCount
496 DE_NULL // const uint32_t* pPreserveAttachments
497 };
498
499 const VkRenderPassCreateInfo2 renderPassInfo{
500 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
501 DE_NULL, // const void* pNext
502 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
503 1u, // uint32_t attachmentCount
504 &attachmentDescription, // const VkAttachmentDescription* pAttachments
505 1u, // uint32_t subpassCount
506 &subpassDescription, // const VkSubpassDescription* pSubpasses
507 0u, // uint32_t dependencyCount
508 DE_NULL, // const VkSubpassDependency* pDependencies
509 0u, // uint32_t correlatedViewMaskCount
510 DE_NULL // const uint32_t* pCorrelatedViewMasks
511 };
512
513 return vk::createRenderPass2(m_context.getDeviceInterface(), m_context.getDevice(), &renderPassInfo);
514 }
515
buildComplexRenderPass(VkFormat intermediateFormat,VkImageLayout intermediateLayout,VkImageAspectFlags intermediateAspect,VkFormat outputFormat,VkImageLayout outputLayout)516 Move<VkRenderPass> NoneStageTestInstance::buildComplexRenderPass(VkFormat intermediateFormat,
517 VkImageLayout intermediateLayout,
518 VkImageAspectFlags intermediateAspect,
519 VkFormat outputFormat, VkImageLayout outputLayout)
520 {
521 std::vector<VkAttachmentDescription2> attachmentDescriptions{
522 // depth/stencil attachment (when used in read pipeline it loads data filed in write pipeline)
523 {
524 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType
525 DE_NULL, // const void* pNext
526 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
527 intermediateFormat, // VkFormat format
528 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
529 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp
530 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
531 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
532 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp
533 intermediateLayout, // VkImageLayout initialLayout
534 intermediateLayout // VkImageLayout finalLayout
535 },
536 // color attachment
537 {
538 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType
539 DE_NULL, // const void* pNext
540 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
541 outputFormat, // VkFormat format
542 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
543 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp
544 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
545 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
546 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
547 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
548 outputLayout // VkImageLayout finalLayout
549 }};
550
551 VkImageAspectFlags outputAspect = getImageAspectFlags(mapVkFormat(outputFormat));
552 std::vector<VkAttachmentReference2> attachmentRefs{
553 {VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, DE_NULL, 0u, intermediateLayout, intermediateAspect},
554 {VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, DE_NULL, 1u, outputLayout, outputAspect}};
555
556 VkAttachmentReference2 *pDepthStencilAttachment = &attachmentRefs[0];
557 VkAttachmentReference2 *pColorAttachment = &attachmentRefs[1];
558
559 std::vector<VkSubpassDescription2> subpassDescriptions{{
560 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, DE_NULL,
561 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
562 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
563 0u, // uint32_t viewMask
564 1u, // uint32_t inputAttachmentCount
565 pDepthStencilAttachment, // const VkAttachmentReference2* pInputAttachments
566 1u, // uint32_t colorAttachmentCount
567 pColorAttachment, // const VkAttachmentReference2* pColorAttachments
568 DE_NULL, // const VkAttachmentReference2* pResolveAttachments
569 DE_NULL, // const VkAttachmentReference2* pDepthStencilAttachment
570 0u, // uint32_t preserveAttachmentCount
571 DE_NULL // uint32_t* pPreserveAttachments
572 }};
573
574 const VkRenderPassCreateInfo2 renderPassInfo{
575 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
576 DE_NULL, // const void* pNext
577 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
578 (uint32_t)attachmentDescriptions.size(), // uint32_t attachmentCount
579 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments
580 (uint32_t)subpassDescriptions.size(), // uint32_t subpassCount
581 subpassDescriptions.data(), // const VkSubpassDescription* pSubpasses
582 0u, // uint32_t dependencyCount
583 DE_NULL, // const VkSubpassDependency* pDependencies
584 0u, // uint32_t correlatedViewMaskCount
585 DE_NULL // const uint32_t* pCorrelatedViewMasks
586 };
587
588 return vk::createRenderPass2(m_context.getDeviceInterface(), m_context.getDevice(), &renderPassInfo);
589 }
590
buildImageView(VkImage image,VkFormat format,const VkImageSubresourceRange & subresourceRange)591 Move<VkImageView> NoneStageTestInstance::buildImageView(VkImage image, VkFormat format,
592 const VkImageSubresourceRange &subresourceRange)
593 {
594 const DeviceInterface &vk = m_context.getDeviceInterface();
595 const VkDevice &device = m_context.getDevice();
596
597 const VkImageViewCreateInfo imageViewParams{
598 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType
599 DE_NULL, // const void* pNext
600 0u, // VkImageViewCreateFlags flags
601 image, // VkImage image
602 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType
603 format, // VkFormat format
604 makeComponentMappingRGBA(), // VkComponentMapping components
605 subresourceRange, // VkImageSubresourceRange subresourceRange
606 };
607
608 return createImageView(vk, device, &imageViewParams);
609 }
610
buildFramebuffer(VkRenderPass renderPass,const VkImageView * outView1,const VkImageView * outView2)611 Move<VkFramebuffer> NoneStageTestInstance::buildFramebuffer(VkRenderPass renderPass, const VkImageView *outView1,
612 const VkImageView *outView2)
613 {
614 const DeviceInterface &vk = m_context.getDeviceInterface();
615 const VkDevice &device = m_context.getDevice();
616
617 std::vector<VkImageView> imageViews = {*outView1};
618 if (outView2)
619 imageViews.push_back(*outView2);
620
621 const VkFramebufferCreateInfo framebufferParams{
622 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType
623 DE_NULL, // const void* pNext
624 0u, // VkFramebufferCreateFlags flags
625 renderPass, // VkRenderPass renderPass
626 (uint32_t)imageViews.size(), // uint32_t attachmentCount
627 imageViews.data(), // const VkImageView* pAttachments
628 m_imageExtent.width, // uint32_t width
629 m_imageExtent.height, // uint32_t height
630 1u, // uint32_t layers
631 };
632 return createFramebuffer(vk, device, &framebufferParams);
633 }
634
buildSampler()635 Move<VkSampler> NoneStageTestInstance::buildSampler()
636 {
637 const DeviceInterface &vk = m_context.getDeviceInterface();
638 const VkDevice &device = m_context.getDevice();
639
640 const VkSamplerCreateInfo samplerInfo{
641 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType
642 DE_NULL, // const void* pNext
643 0u, // VkSamplerCreateFlags flags
644 VK_FILTER_NEAREST, // VkFilter magFilter
645 VK_FILTER_NEAREST, // VkFilter minFilter
646 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode
647 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU
648 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV
649 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW
650 0.0f, // float mipLodBias
651 VK_FALSE, // VkBool32 anisotropyEnable
652 1.0f, // float maxAnisotropy
653 false, // VkBool32 compareEnable
654 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp
655 0.0f, // float minLod
656 0.0f, // float maxLod
657 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor
658 VK_FALSE, // VkBool32 unnormalizedCoords
659 };
660 return createSampler(vk, device, &samplerInfo);
661 }
662
buildDescriptorSetLayout(VkDescriptorType descriptorType)663 Move<VkDescriptorSetLayout> NoneStageTestInstance::buildDescriptorSetLayout(VkDescriptorType descriptorType)
664 {
665 const DeviceInterface &vk = m_context.getDeviceInterface();
666 const VkDevice &device = m_context.getDevice();
667
668 return DescriptorSetLayoutBuilder()
669 .addSingleSamplerBinding(descriptorType, VK_SHADER_STAGE_FRAGMENT_BIT, DE_NULL)
670 .build(vk, device);
671 }
672
buildDescriptorPool(VkDescriptorType descriptorType)673 Move<VkDescriptorPool> NoneStageTestInstance::buildDescriptorPool(VkDescriptorType descriptorType)
674 {
675 const DeviceInterface &vk = m_context.getDeviceInterface();
676 const VkDevice &device = m_context.getDevice();
677
678 return DescriptorPoolBuilder()
679 .addType(descriptorType, 1u)
680 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
681 }
682
buildDescriptorSet(VkDescriptorPool descriptorPool,VkDescriptorSetLayout descriptorSetLayout,VkDescriptorType descriptorType,VkImageView inputView,VkImageLayout inputLayout,const VkSampler * sampler)683 Move<VkDescriptorSet> NoneStageTestInstance::buildDescriptorSet(VkDescriptorPool descriptorPool,
684 VkDescriptorSetLayout descriptorSetLayout,
685 VkDescriptorType descriptorType, VkImageView inputView,
686 VkImageLayout inputLayout, const VkSampler *sampler)
687 {
688 const DeviceInterface &vk = m_context.getDeviceInterface();
689 const VkDevice &device = m_context.getDevice();
690
691 const VkDescriptorImageInfo inputImageInfo =
692 makeDescriptorImageInfo(sampler ? *sampler : 0u, inputView, inputLayout);
693 Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout);
694
695 DescriptorSetUpdateBuilder()
696 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &inputImageInfo)
697 .update(vk, device);
698
699 return descriptorSet;
700 }
701
buildPipeline(uint32_t subpass,VkImageAspectFlags resultAspect,VkPipelineLayout pipelineLayout,VkShaderModule vertShaderModule,VkShaderModule fragShaderModule,VkRenderPass renderPass)702 Move<VkPipeline> NoneStageTestInstance::buildPipeline(uint32_t subpass, VkImageAspectFlags resultAspect,
703 VkPipelineLayout pipelineLayout, VkShaderModule vertShaderModule,
704 VkShaderModule fragShaderModule, VkRenderPass renderPass)
705 {
706 const DeviceInterface &vk = m_context.getDeviceInterface();
707 const VkDevice &device = m_context.getDevice();
708 const std::vector<VkViewport> viewports{makeViewport(m_imageExtent)};
709 const std::vector<VkRect2D> scissors{makeRect2D(m_imageExtent)};
710 const bool useDepth = resultAspect & VK_IMAGE_ASPECT_DEPTH_BIT;
711 const bool useStencil = resultAspect & VK_IMAGE_ASPECT_STENCIL_BIT;
712
713 const VkStencilOpState stencilOpState = makeStencilOpState(VK_STENCIL_OP_REPLACE, // stencil fail
714 VK_STENCIL_OP_REPLACE, // depth & stencil pass
715 VK_STENCIL_OP_REPLACE, // depth only fail
716 VK_COMPARE_OP_ALWAYS, // compare op
717 1u, // compare mask
718 1u, // write mask
719 1u); // reference
720
721 const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo{
722 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
723 DE_NULL, // const void* pNext
724 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags
725 useDepth, // VkBool32 depthTestEnable
726 useDepth, // VkBool32 depthWriteEnable
727 VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp
728 VK_FALSE, // VkBool32 depthBoundsTestEnable
729 useStencil, // VkBool32 stencilTestEnable
730 stencilOpState, // VkStencilOpState front
731 stencilOpState, // VkStencilOpState back
732 0.0f, // float minDepthBounds
733 1.0f, // float maxDepthBounds
734 };
735
736 return makeGraphicsPipeline(
737 vk, // DeviceInterface& vk
738 device, // VkDevice device
739 pipelineLayout, // VkPipelineLayout pipelineLayout
740 vertShaderModule, // VkShaderModule vertexShaderModule
741 DE_NULL, // VkShaderModule tessellationControlModule
742 DE_NULL, // VkShaderModule tessellationEvalModule
743 DE_NULL, // VkShaderModule geometryShaderModule
744 fragShaderModule, // VkShaderModule fragmentShaderModule
745 renderPass, // VkRenderPass renderPass
746 viewports, // std::vector<VkViewport>& viewports
747 scissors, // std::vector<VkRect2D>& scissors
748 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology
749 subpass, // uint32_t subpass
750 0u, // uint32_t patchControlPoints
751 DE_NULL, // VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
752 DE_NULL, // VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
753 DE_NULL, // VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
754 &depthStencilStateCreateInfo); // VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
755 }
756
iterate(void)757 tcu::TestStatus NoneStageTestInstance::iterate(void)
758 {
759 const DeviceInterface &vk = m_context.getDeviceInterface();
760 const VkDevice &device = m_context.getDevice();
761 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
762 VkQueue queue = m_context.getUniversalQueue();
763 Move<VkCommandPool> cmdPool =
764 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
765 Move<VkCommandBuffer> cmdBuffer = makeCommandBuffer(vk, device, *cmdPool);
766 const VkDeviceSize vertexBufferOffset = 0;
767 ImageWrapper *transitionImagePtr = &m_referenceImage;
768 ImageWrapper *imageToVerifyPtr = &m_referenceImage;
769 const uint32_t imageSizeInBytes = m_imageExtent.width * m_imageExtent.height * 4;
770 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_testParams.type, vk, false);
771 const VkRect2D renderArea = makeRect2D(0, 0, m_imageExtent.width, m_imageExtent.height);
772 const VkBufferImageCopy transitionCopyRegion = buildCopyRegion(m_imageExtent, m_transitionImageAspect);
773 const VkBufferImageCopy colorCopyRegion = buildCopyRegion(m_imageExtent, VK_IMAGE_ASPECT_COLOR_BIT);
774
775 // create image that will have gradient (without data atm)
776 m_referenceImage.create(m_context, m_alloc, m_referenceImageFormat, m_imageExtent, m_referenceImageUsage);
777
778 // create buffer used for gradient data source
779 BufferWrapper srcBuffer;
780 srcBuffer.create(m_context, m_alloc, imageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
781
782 // generate gradient
783 std::vector<uint32_t> referenceData(m_imageExtent.width * m_imageExtent.height);
784 tcu::TextureFormat referenceFormat(mapVkFormat(m_referenceImageFormat));
785 if (m_testParams.readLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
786 {
787 // when testing stencil aspect of depth stencil combined image, prepare reference date only with stencil,
788 // as the copy operation (used when m_usePipelineToWrite == false) sources just one aspect
789
790 // this format is used for tcu operations only - does not need to be supported by the Vulkan implementation
791 referenceFormat = mapVkFormat(VK_FORMAT_S8_UINT);
792 }
793 PixelBufferAccess referencePBA(referenceFormat, m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth,
794 referenceData.data());
795 fillWithComponentGradients(referencePBA, tcu::Vec4(0.0f), tcu::Vec4(1.0f));
796 deMemcpy(srcBuffer.memory->getHostPtr(), referenceData.data(), static_cast<size_t>(imageSizeInBytes));
797 flushAlloc(vk, device, *srcBuffer.memory);
798
799 // create buffer for result transfer
800 BufferWrapper dstBuffer;
801 tcu::TextureFormat resultFormat(mapVkFormat(m_readImageFormat));
802 dstBuffer.create(m_context, m_alloc, imageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
803
804 if (m_usePipelineToWrite || m_usePipelineToRead)
805 {
806 buildVertexBuffer();
807
808 // create image view for reference image (its always at index 0)
809 m_attachmentViews.push_back(
810 buildImageView(*m_referenceImage.handle, m_referenceImageFormat, m_referenceSubresourceRange));
811
812 // create graphics pipeline used to write image data
813 if (m_usePipelineToWrite)
814 {
815 // create image that will be used as attachment to write to
816 m_imageToWrite.create(m_context, m_alloc, m_transitionImageFormat, m_imageExtent, m_imageToWriteUsage);
817 m_attachmentViews.push_back(
818 buildImageView(*m_imageToWrite.handle, m_transitionImageFormat, m_transitionSubresourceRange));
819
820 m_writeVertShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
821 m_writeFragShaderModule =
822 createShaderModule(vk, device, m_context.getBinaryCollection().get(m_writeFragShaderName), 0);
823
824 if (m_useStencilDuringWrite)
825 {
826 // this is used only for cases where writable layout is VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL
827 // in this case generated gradient is only used for verification
828 m_writeRenderPass = buildBasicRenderPass(m_transitionImageFormat, m_writeRenderPassOutputLayout,
829 VK_ATTACHMENT_LOAD_OP_CLEAR);
830 m_writePipelineLayout = makePipelineLayout(vk, device, DE_NULL);
831 m_writePipeline = buildPipeline(0u, m_transitionImageAspect, *m_writePipelineLayout,
832 *m_writeVertShaderModule, *m_writeFragShaderModule, *m_writeRenderPass);
833 m_writeFramebuffer = buildFramebuffer(*m_writeRenderPass, &m_attachmentViews[1].get());
834 }
835 else
836 {
837 m_writeRenderPass = buildBasicRenderPass(m_transitionImageFormat, m_writeRenderPassOutputLayout);
838 m_writeSampler = buildSampler();
839 m_writeDescriptorSetLayout = buildDescriptorSetLayout(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
840 m_writeDescriptorPool = buildDescriptorPool(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
841 m_writeDescriptorSet = buildDescriptorSet(
842 *m_writeDescriptorPool, *m_writeDescriptorSetLayout, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
843 *m_attachmentViews[0], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, &m_writeSampler.get());
844 m_writePipelineLayout = makePipelineLayout(vk, device, *m_writeDescriptorSetLayout);
845 m_writePipeline = buildPipeline(0u, m_transitionImageAspect, *m_writePipelineLayout,
846 *m_writeVertShaderModule, *m_writeFragShaderModule, *m_writeRenderPass);
847 m_writeFramebuffer = buildFramebuffer(*m_writeRenderPass, &m_attachmentViews[1].get());
848 }
849
850 transitionImagePtr = &m_imageToWrite;
851 imageToVerifyPtr = &m_imageToWrite;
852 }
853
854 // create graphics pipeline used to read image data
855 if (m_usePipelineToRead)
856 {
857 m_imageToRead.create(m_context, m_alloc, m_readImageFormat, m_imageExtent,
858 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
859 m_attachmentViews.push_back(
860 buildImageView(*m_imageToRead.handle, m_readImageFormat, m_readSubresourceRange));
861 imageToVerifyPtr = &m_imageToRead;
862
863 m_readVertShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
864 m_readFragShaderModule =
865 createShaderModule(vk, device, m_context.getBinaryCollection().get(m_readFragShaderName), 0);
866
867 if (m_useInputAttachmentToRead)
868 {
869 m_readDescriptorSetLayout = buildDescriptorSetLayout(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
870 m_readDescriptorPool = buildDescriptorPool(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
871 m_readDescriptorSet = buildDescriptorSet(
872 *m_readDescriptorPool, *m_readDescriptorSetLayout, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
873 *m_attachmentViews[m_usePipelineToWrite], m_testParams.readLayout);
874 m_readRenderPass =
875 buildComplexRenderPass(m_transitionImageFormat, m_testParams.readLayout, m_transitionImageAspect,
876 m_readImageFormat, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
877 m_readFramebuffer = buildFramebuffer(*m_readRenderPass, &m_attachmentViews[m_usePipelineToWrite].get(),
878 &m_attachmentViews[m_usePipelineToWrite + 1].get());
879 m_readPipelineLayout = makePipelineLayout(vk, device, *m_readDescriptorSetLayout);
880 m_readPipeline = buildPipeline(0u, VK_IMAGE_ASPECT_COLOR_BIT, *m_readPipelineLayout,
881 *m_readVertShaderModule, *m_readFragShaderModule, *m_readRenderPass);
882 }
883 else
884 {
885 m_readSampler = buildSampler();
886 m_readDescriptorSetLayout = buildDescriptorSetLayout(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
887 m_readDescriptorPool = buildDescriptorPool(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
888 m_readDescriptorSet = buildDescriptorSet(
889 *m_readDescriptorPool, *m_readDescriptorSetLayout, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
890 *m_attachmentViews[m_usePipelineToWrite], m_testParams.readLayout, &m_readSampler.get());
891 m_readRenderPass = buildBasicRenderPass(m_readImageFormat, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
892 m_readFramebuffer =
893 buildFramebuffer(*m_readRenderPass, &m_attachmentViews[m_usePipelineToWrite + 1].get());
894 m_readPipelineLayout = makePipelineLayout(vk, device, *m_readDescriptorSetLayout);
895 m_readPipeline = buildPipeline(0u, m_transitionImageAspect, *m_readPipelineLayout,
896 *m_readVertShaderModule, *m_readFragShaderModule, *m_readRenderPass);
897 }
898 }
899 }
900
901 beginCommandBuffer(vk, *cmdBuffer);
902
903 // write data from buffer with gradient to image (for stencil_attachment cases we dont need to do that)
904 if (!m_useStencilDuringWrite)
905 {
906 // wait for reference data to be in buffer
907 const VkBufferMemoryBarrier2KHR preBufferMemoryBarrier2 = makeBufferMemoryBarrier2(
908 VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
909 getAccessFlag(VK_ACCESS_2_HOST_WRITE_BIT_KHR), // VkAccessFlags2KHR srcAccessMask
910 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
911 getAccessFlag(VK_ACCESS_2_TRANSFER_READ_BIT_KHR), // VkAccessFlags2KHR dstAccessMask
912 *srcBuffer.handle, // VkBuffer buffer
913 0u, // VkDeviceSize offset
914 imageSizeInBytes // VkDeviceSize size
915 );
916
917 VkImageLayout copyBufferToImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
918 if (m_testParams.writeLayout == VK_IMAGE_LAYOUT_GENERAL)
919 copyBufferToImageLayout = VK_IMAGE_LAYOUT_GENERAL;
920
921 // change image layout so that we can copy to it data from buffer
922 const VkImageMemoryBarrier2KHR preImageMemoryBarrier2 = makeImageMemoryBarrier2(
923 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
924 getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR srcAccessMask
925 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
926 getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR dstAccessMask
927 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
928 copyBufferToImageLayout, // VkImageLayout newLayout
929 *m_referenceImage.handle, // VkImage image
930 m_referenceSubresourceRange // VkImageSubresourceRange subresourceRange
931 );
932 VkDependencyInfoKHR buffDependencyInfo =
933 makeCommonDependencyInfo(DE_NULL, &preBufferMemoryBarrier2, &preImageMemoryBarrier2);
934 synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &buffDependencyInfo);
935
936 const VkBufferImageCopy *copyRegion = m_usePipelineToWrite ? &colorCopyRegion : &transitionCopyRegion;
937 vk.cmdCopyBufferToImage(*cmdBuffer, *srcBuffer.handle, *m_referenceImage.handle, copyBufferToImageLayout, 1u,
938 copyRegion);
939 }
940
941 if (m_usePipelineToWrite)
942 {
943 // wait till data is transfered to image (in all cases except when stencil_attachment is tested)
944 if (!m_useStencilDuringWrite)
945 {
946 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
947 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
948 getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR srcAccessMask
949 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
950 getAccessFlag(VK_ACCESS_2_SHADER_READ_BIT_KHR), // VkAccessFlags2KHR dstAccessMask
951 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout
952 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout
953 *m_referenceImage.handle, // VkImage image
954 m_referenceSubresourceRange // VkImageSubresourceRange subresourceRange
955 );
956 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
957 synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo);
958 }
959
960 beginRenderPass(vk, *cmdBuffer, *m_writeRenderPass, *m_writeFramebuffer, renderArea,
961 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
962
963 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_writePipeline);
964 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &m_vertexBuffer.handle.get(), &vertexBufferOffset);
965 if (m_useStencilDuringWrite)
966 {
967 // when writing to stencil buffer draw single triangle (to simulate gradient over 1bit)
968 vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
969 }
970 else
971 {
972 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_writePipelineLayout, 0, 1,
973 &m_writeDescriptorSet.get(), 0, DE_NULL);
974 vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
975 }
976
977 endRenderPass(vk, *cmdBuffer);
978 }
979
980 // use none stage to wait till data is transfered to image
981 {
982 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 =
983 makeImageMemoryBarrier2(m_srcStageToNoneStageMask, // VkPipelineStageFlags2KHR srcStageMask
984 m_srcAccessToNoneAccessMask, // VkAccessFlags2KHR srcAccessMask
985 VK_PIPELINE_STAGE_2_NONE_KHR, // VkPipelineStageFlags2KHR dstStageMask
986 VK_ACCESS_2_NONE_KHR, // VkAccessFlags2KHR dstAccessMask
987 m_testParams.writeLayout, // VkImageLayout oldLayout
988 m_testParams.writeLayout, // VkImageLayout newLayout
989 *transitionImagePtr->handle, // VkImage image
990 m_transitionSubresourceRange // VkImageSubresourceRange subresourceRange
991 );
992 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
993 synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo);
994 }
995
996 // use all commands stage to change image layout
997 {
998 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
999 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
1000 VK_ACCESS_2_NONE_KHR, // VkAccessFlags2KHR srcAccessMask
1001 m_dstStageFromNoneStageMask, // VkPipelineStageFlags2KHR dstStageMask
1002 m_dstAccessFromNoneAccessMask, // VkAccessFlags2KHR dstAccessMask
1003 m_testParams.writeLayout, // VkImageLayout oldLayout
1004 m_testParams.readLayout, // VkImageLayout newLayout
1005 *transitionImagePtr->handle, // VkImage image
1006 m_transitionSubresourceRange // VkImageSubresourceRange subresourceRange
1007 );
1008 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1009 synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo);
1010 }
1011
1012 VkImageLayout copyImageToBufferLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1013 if (m_testParams.readLayout == VK_IMAGE_LAYOUT_GENERAL)
1014 copyImageToBufferLayout = VK_IMAGE_LAYOUT_GENERAL;
1015
1016 if (m_usePipelineToRead)
1017 {
1018 beginRenderPass(vk, *cmdBuffer, *m_readRenderPass, *m_readFramebuffer, renderArea);
1019
1020 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_readPipeline);
1021 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_readPipelineLayout, 0, 1,
1022 &m_readDescriptorSet.get(), 0, DE_NULL);
1023 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &m_vertexBuffer.handle.get(), &vertexBufferOffset);
1024 vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1025
1026 endRenderPass(vk, *cmdBuffer);
1027
1028 // wait till data is transfered to image
1029 const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1030 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
1031 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR, // VkAccessFlags2KHR srcAccessMask
1032 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
1033 getAccessFlag(VK_ACCESS_2_TRANSFER_READ_BIT_KHR), // VkAccessFlags2KHR dstAccessMask
1034 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout
1035 copyImageToBufferLayout, // VkImageLayout newLayout
1036 *imageToVerifyPtr->handle, // VkImage image
1037 m_readSubresourceRange // VkImageSubresourceRange subresourceRange
1038 );
1039 VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1040 synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo);
1041 }
1042
1043 // read back image
1044 {
1045 const VkBufferImageCopy *copyRegion = m_usePipelineToRead ? &colorCopyRegion : &transitionCopyRegion;
1046 vk.cmdCopyImageToBuffer(*cmdBuffer, *imageToVerifyPtr->handle, copyImageToBufferLayout, *dstBuffer.handle, 1u,
1047 copyRegion);
1048
1049 const VkBufferMemoryBarrier2KHR postBufferMemoryBarrier2 = makeBufferMemoryBarrier2(
1050 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
1051 getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR srcAccessMask
1052 VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
1053 getAccessFlag(VK_ACCESS_2_HOST_READ_BIT_KHR), // VkAccessFlags2KHR dstAccessMask
1054 *dstBuffer.handle, // VkBuffer buffer
1055 0u, // VkDeviceSize offset
1056 imageSizeInBytes // VkDeviceSize size
1057 );
1058 VkDependencyInfoKHR bufDependencyInfo = makeCommonDependencyInfo(DE_NULL, &postBufferMemoryBarrier2);
1059 synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &bufDependencyInfo);
1060 }
1061
1062 endCommandBuffer(vk, *cmdBuffer);
1063
1064 Move<VkFence> fence = createFence(vk, device);
1065 VkCommandBufferSubmitInfoKHR cmdBuffersInfo = makeCommonCommandBufferSubmitInfo(*cmdBuffer);
1066 synchronizationWrapper->addSubmitInfo(0u, DE_NULL, 1u, &cmdBuffersInfo, 0u, DE_NULL);
1067 VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence));
1068 VK_CHECK(vk.waitForFences(device, 1, &fence.get(), VK_TRUE, ~0ull));
1069
1070 // read image data
1071 invalidateAlloc(vk, device, *dstBuffer.memory);
1072 PixelBufferAccess resultPBA(resultFormat, m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth,
1073 dstBuffer.memory->getHostPtr());
1074
1075 // if result/reference is depth-stencil format then focus only on tested component
1076 if (isCombinedDepthStencilType(referenceFormat.type))
1077 referencePBA = getEffectiveDepthStencilAccess(
1078 referencePBA, (m_referenceSubresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) ?
1079 tcu::Sampler::MODE_DEPTH :
1080 tcu::Sampler::MODE_STENCIL);
1081 if (isCombinedDepthStencilType(resultFormat.type))
1082 resultPBA = getEffectiveDepthStencilAccess(
1083 resultPBA, (m_readSubresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) ? tcu::Sampler::MODE_DEPTH :
1084 tcu::Sampler::MODE_STENCIL);
1085
1086 if (verifyResult(referencePBA, resultPBA))
1087 return TestStatus::pass("Pass");
1088 return TestStatus::fail("Fail");
1089 }
1090
verifyResult(const PixelBufferAccess & reference,const PixelBufferAccess & result)1091 bool NoneStageTestInstance::verifyResult(const PixelBufferAccess &reference, const PixelBufferAccess &result)
1092 {
1093 TestLog &log = m_context.getTestContext().getLog();
1094
1095 const auto forceStencil = (m_testParams.readLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL);
1096
1097 if (isIntFormat(m_referenceImageFormat) || isUintFormat(m_referenceImageFormat) || forceStencil)
1098 {
1099 // special case for stencil (1bit gradient - top-left of image is 0, bottom-right is 1)
1100
1101 bool isResultCorrect = true;
1102 TextureLevel errorMaskStorage(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), m_imageExtent.width,
1103 m_imageExtent.height, 1);
1104 PixelBufferAccess errorMask = errorMaskStorage.getAccess();
1105
1106 for (uint32_t y = 0; y < m_imageExtent.height; y++)
1107 for (uint32_t x = 0; x < m_imageExtent.width; x++)
1108 {
1109 // skip textels on diagonal (gradient lights texels on diagonal and stencil operation in test does not)
1110 if ((x + y) == (m_imageExtent.width - 1))
1111 {
1112 errorMask.setPixel(IVec4(0, 0xff, 0, 0xff), x, y, 0);
1113 continue;
1114 }
1115
1116 IVec4 refPix = reference.getPixelInt(x, y, 0);
1117 IVec4 cmpPix = result.getPixelInt(x, y, 0);
1118 bool isOk = (refPix[0] == cmpPix[0]);
1119 errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, 0);
1120 isResultCorrect &= isOk;
1121 }
1122
1123 Vec4 pixelBias(0.0f);
1124 Vec4 pixelScale(1.0f);
1125 if (isResultCorrect)
1126 {
1127 log << TestLog::ImageSet("Image comparison", "")
1128 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) << TestLog::EndImageSet;
1129 return true;
1130 }
1131
1132 log << TestLog::ImageSet("Image comparison", "")
1133 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
1134 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
1135 << TestLog::Image("ErrorMask", "Error mask", errorMask) << TestLog::EndImageSet;
1136 return false;
1137 }
1138
1139 return floatThresholdCompare(log, "Image comparison", "", reference, result, tcu::Vec4(0.01f),
1140 tcu::COMPARE_LOG_RESULT);
1141 }
1142
1143 class NoneStageTestCase : public vkt::TestCase
1144 {
1145 public:
1146 NoneStageTestCase(tcu::TestContext &testContext, const std::string &name, const TestParams &testParams);
1147 ~NoneStageTestCase(void) = default;
1148
1149 void initPrograms(SourceCollections &sourceCollections) const override;
1150 TestInstance *createInstance(Context &context) const override;
1151 void checkSupport(Context &context) const override;
1152
1153 private:
1154 const TestParams m_testParams;
1155 };
1156
NoneStageTestCase(tcu::TestContext & testContext,const std::string & name,const TestParams & testParams)1157 NoneStageTestCase::NoneStageTestCase(tcu::TestContext &testContext, const std::string &name,
1158 const TestParams &testParams)
1159 : vkt::TestCase(testContext, name)
1160 , m_testParams(testParams)
1161 {
1162 }
1163
initPrograms(SourceCollections & sourceCollections) const1164 void NoneStageTestCase::initPrograms(SourceCollections &sourceCollections) const
1165 {
1166 const auto writeLayout = m_testParams.writeLayout;
1167 const auto writeAspect = m_testParams.writeAspect;
1168 const auto readLayout = m_testParams.readLayout;
1169 const auto readAspect = m_testParams.readAspect;
1170
1171 // for tests that use only transfer and general layouts we don't create pipeline
1172 if (((writeLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) || (readLayout == VK_IMAGE_LAYOUT_GENERAL)) &&
1173 ((writeLayout == VK_IMAGE_LAYOUT_GENERAL) || (readLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)))
1174 return;
1175
1176 sourceCollections.glslSources.add("vert")
1177 << glu::VertexSource("#version 450\n"
1178 "layout(location = 0) in vec4 inPosition;\n"
1179 "layout(location = 0) out vec2 outUV;\n"
1180 "void main(void)\n"
1181 "{\n"
1182 " outUV = vec2(inPosition.x * 0.5 + 0.5, inPosition.y * 0.5 + 0.5);\n"
1183 " gl_Position = inPosition;\n"
1184 "}\n");
1185
1186 sourceCollections.glslSources.add("frag-color")
1187 << glu::FragmentSource("#version 450\n"
1188 "layout(binding = 0) uniform sampler2D u_sampler;\n"
1189 "layout(location = 0) in vec2 inUV;\n"
1190 "layout(location = 0) out vec4 fragColor;\n"
1191 "void main(void)\n"
1192 "{\n"
1193 " fragColor = texture(u_sampler, inUV);\n"
1194 "}\n");
1195
1196 if (writeAspect & VK_IMAGE_ASPECT_DEPTH_BIT)
1197 {
1198 sourceCollections.glslSources.add("frag-color-to-depth")
1199 << glu::FragmentSource("#version 450\n"
1200 "layout(binding = 0) uniform sampler2D u_sampler;\n"
1201 "layout(location = 0) in vec2 inUV;\n"
1202 "void main(void)\n"
1203 "{\n"
1204 " gl_FragDepth = texture(u_sampler, inUV).r;\n"
1205 "}\n");
1206 }
1207
1208 if (writeAspect & VK_IMAGE_ASPECT_STENCIL_BIT)
1209 {
1210 sourceCollections.glslSources.add("frag-color-to-stencil") << glu::FragmentSource("#version 450\n"
1211 "void main(void)\n"
1212 "{\n"
1213 "}\n");
1214 }
1215 if ((readLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) && (readLayout != VK_IMAGE_LAYOUT_GENERAL) &&
1216 ((readAspect | writeAspect) == VK_IMAGE_ASPECT_STENCIL_BIT ||
1217 (readAspect == IMAGE_ASPECT_DEPTH_STENCIL &&
1218 m_testParams.readLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)))
1219 {
1220 // use usampler2D and uvec4 for color
1221 sourceCollections.glslSources.add("frag-stencil-to-color")
1222 << glu::FragmentSource("#version 450\n"
1223 "layout(binding = 0) uniform usampler2D u_sampler;\n"
1224 "layout(location = 0) in vec2 inUV;\n"
1225 "layout(location = 0) out uvec4 fragColor;\n"
1226 "void main(void)\n"
1227 "{\n"
1228 " fragColor = texture(u_sampler, inUV);\n"
1229 "}\n");
1230 }
1231
1232 if (readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
1233 {
1234 // for stencil only cases we need to use usubpassInput (for depth and depth_stencil we need to use subpassInput)
1235 const bool readDepth = readAspect & VK_IMAGE_ASPECT_DEPTH_BIT;
1236 const std::map<std::string, std::string> specializations{
1237 {"SUBPASS_INPUT", (readDepth ? "subpassInput" : "usubpassInput")},
1238 {"VALUE_TYPE", (readDepth ? "float" : "uint")}};
1239
1240 std::string source =
1241 "#version 450\n"
1242 "layout (input_attachment_index = 0, binding = 0) uniform ${SUBPASS_INPUT} depthOrStencilInput;\n"
1243 "layout(location = 0) in vec2 inUV;\n"
1244 "layout(location = 0) out ${VALUE_TYPE} fragColor;\n"
1245 "void main (void)\n"
1246 "{\n"
1247 " fragColor = subpassLoad(depthOrStencilInput).x;\n"
1248 "}\n";
1249 sourceCollections.glslSources.add("frag-depth-or-stencil-to-color")
1250 << glu::FragmentSource(tcu::StringTemplate(source).specialize(specializations));
1251 }
1252 }
1253
createInstance(Context & context) const1254 TestInstance *NoneStageTestCase::createInstance(Context &context) const
1255 {
1256 return new NoneStageTestInstance(context, m_testParams);
1257 }
1258
checkSupport(Context & context) const1259 void NoneStageTestCase::checkSupport(Context &context) const
1260 {
1261 context.requireDeviceFunctionality("VK_KHR_synchronization2");
1262
1263 const auto writeAspect = m_testParams.writeAspect;
1264 const auto readAspect = m_testParams.readAspect;
1265
1266 // check whether implementation supports separate depth/stencil layouts
1267 if (((writeAspect == VK_IMAGE_ASPECT_DEPTH_BIT) && (readAspect == VK_IMAGE_ASPECT_DEPTH_BIT)) ||
1268 ((writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT) && (readAspect == VK_IMAGE_ASPECT_STENCIL_BIT)))
1269 {
1270 if (!context.getSeparateDepthStencilLayoutsFeatures().separateDepthStencilLayouts)
1271 TCU_THROW(NotSupportedError, "Implementation does not support separateDepthStencilLayouts");
1272 }
1273
1274 const auto writeLayout = m_testParams.writeLayout;
1275 const auto readLayout = m_testParams.readLayout;
1276 bool usePipelineToWrite =
1277 (writeLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) && (writeLayout != VK_IMAGE_LAYOUT_GENERAL);
1278 bool usePipelineToRead =
1279 (readLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) && (readLayout != VK_IMAGE_LAYOUT_GENERAL);
1280
1281 if (!usePipelineToWrite && !usePipelineToRead)
1282 return;
1283
1284 VkFormat transitionImageFormat = VK_FORMAT_R8G8B8A8_UNORM;
1285 if ((writeAspect == VK_IMAGE_ASPECT_DEPTH_BIT) || (readAspect == VK_IMAGE_ASPECT_DEPTH_BIT))
1286 transitionImageFormat = VK_FORMAT_D32_SFLOAT;
1287 else if ((writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT) || (readAspect == VK_IMAGE_ASPECT_STENCIL_BIT))
1288 transitionImageFormat = VK_FORMAT_S8_UINT;
1289 else if ((writeAspect == IMAGE_ASPECT_DEPTH_STENCIL) || (readAspect == IMAGE_ASPECT_DEPTH_STENCIL))
1290 transitionImageFormat = VK_FORMAT_D24_UNORM_S8_UINT;
1291
1292 struct FormatToCheck
1293 {
1294 VkFormat format;
1295 VkImageUsageFlags usage;
1296 };
1297 std::vector<FormatToCheck> formatsToCheck{
1298 // reference image
1299 {transitionImageFormat, (VkImageUsageFlags)VK_IMAGE_USAGE_TRANSFER_DST_BIT},
1300
1301 // image to write
1302 {transitionImageFormat, (VkImageUsageFlags)VK_IMAGE_USAGE_TRANSFER_SRC_BIT}};
1303
1304 // note: conditions here are analogic to conditions in test case constructor
1305 // everything not needed was cout out leaving only logic related to
1306 // m_referenceImage and m_imageToWrite
1307 if (usePipelineToWrite)
1308 {
1309 if (writeAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
1310 {
1311 if (writeAspect & VK_IMAGE_ASPECT_DEPTH_BIT)
1312 {
1313 formatsToCheck[0].format = VK_FORMAT_R32_SFLOAT;
1314 formatsToCheck[0].usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
1315 }
1316 else
1317 formatsToCheck[0].usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1318
1319 formatsToCheck[1].usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1320 }
1321 else
1322 {
1323 formatsToCheck[0].usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
1324 formatsToCheck[1].usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1325 }
1326 }
1327
1328 if (usePipelineToRead)
1329 {
1330 // for layouts that operate on depth or stencil (not depth_stencil) use input attachment to read
1331 if ((readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) &&
1332 (readAspect != IMAGE_ASPECT_DEPTH_STENCIL))
1333 {
1334 formatsToCheck[1].usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1335
1336 if (!usePipelineToWrite)
1337 formatsToCheck[0].usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1338 }
1339 else // use image sampler for color and depth_stencil layouts
1340 {
1341 formatsToCheck[0].usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
1342
1343 // for depth_stencil layouts we need to have depth_stencil_attachment usage
1344 if (!usePipelineToWrite && (readAspect & VK_IMAGE_ASPECT_STENCIL_BIT))
1345 formatsToCheck[0].usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1346 }
1347 if ((readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) &&
1348 (readAspect != IMAGE_ASPECT_DEPTH_STENCIL))
1349 if ((m_testParams.readLayout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
1350 m_testParams.readLayout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL))
1351 formatsToCheck[0].usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1352 }
1353
1354 // it simplifies logic to pop image to write then to add conditions everywhere above
1355 if (!usePipelineToWrite)
1356 formatsToCheck.pop_back();
1357
1358 for (const auto &formatData : formatsToCheck)
1359 {
1360 VkImageFormatProperties properties;
1361 const vk::InstanceInterface &vki = context.getInstanceInterface();
1362 if (vki.getPhysicalDeviceImageFormatProperties(context.getPhysicalDevice(), formatData.format, VK_IMAGE_TYPE_2D,
1363 VK_IMAGE_TILING_OPTIMAL, formatData.usage, 0,
1364 &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
1365 {
1366 std::string error = std::string("Format (") + vk::getFormatName(formatData.format) +
1367 ") doesn't support required capabilities.";
1368 TCU_THROW(NotSupportedError, error.c_str());
1369 }
1370 }
1371 }
1372
1373 } // namespace
1374
createNoneStageTests(tcu::TestContext & testCtx)1375 tcu::TestCaseGroup *createNoneStageTests(tcu::TestContext &testCtx)
1376 {
1377 de::MovePtr<tcu::TestCaseGroup> noneStageTests(new tcu::TestCaseGroup(testCtx, "none_stage"));
1378
1379 struct LayoutData
1380 {
1381 VkImageLayout token;
1382 VkImageAspectFlags aspect;
1383 std::string name;
1384 };
1385
1386 const std::vector<LayoutData> writableLayoutsData{
1387 {VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, IMAGE_ASPECT_ALL, "transfer_dst"},
1388 {VK_IMAGE_LAYOUT_GENERAL, IMAGE_ASPECT_ALL, "general"},
1389 {VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT, "color_attachment"},
1390 {VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL, "depth_stencil_attachment"},
1391 {VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT, "depth_attachment"},
1392 {VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_STENCIL_BIT, "stencil_attachment"},
1393 {VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_ASPECT_COLOR_BIT, "generic_color_attachment"},
1394 {VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_ASPECT_DEPTH_BIT, "generic_depth_attachment"},
1395 {VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_ASPECT_STENCIL_BIT, "generic_stencil_attachment"},
1396 {VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, IMAGE_ASPECT_DEPTH_STENCIL, "generic_depth_stencil_attachment"},
1397 };
1398 const std::vector<LayoutData> readableLayoutsData{
1399 {VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, IMAGE_ASPECT_ALL, "transfer_src"},
1400 {VK_IMAGE_LAYOUT_GENERAL, IMAGE_ASPECT_ALL, "general"},
1401 {VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, IMAGE_ASPECT_ALL, "shader_read"},
1402 {VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL, "depth_stencil_read"},
1403 {VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL,
1404 "depth_read_stencil_attachment"},
1405 {VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL,
1406 "depth_attachment_stencil_read"},
1407 {VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT, "depth_read"},
1408 {VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_STENCIL_BIT, "stencil_read"},
1409 {VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, IMAGE_ASPECT_ALL, "generic_color_read"},
1410 {VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_ASPECT_DEPTH_BIT, "generic_depth_read"},
1411 {VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_ASPECT_STENCIL_BIT, "generic_stencil_read"},
1412 {VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, IMAGE_ASPECT_DEPTH_STENCIL, "generic_depth_stencil_read"},
1413 };
1414
1415 struct SynchronizationData
1416 {
1417 SynchronizationType type;
1418 std::string casePrefix;
1419 bool useGenericAccessFlags;
1420 };
1421 std::vector<SynchronizationData> synchronizationData{{SynchronizationType::SYNCHRONIZATION2, "", true},
1422 {SynchronizationType::SYNCHRONIZATION2, "old_access_", false},
1423
1424 // using legacy synchronization structures with NONE_STAGE
1425 {SynchronizationType::LEGACY, "legacy_", false}};
1426
1427 for (const auto &syncData : synchronizationData)
1428 {
1429 for (const auto &writeData : writableLayoutsData)
1430 {
1431 for (const auto &readData : readableLayoutsData)
1432 {
1433 if (readData.aspect && writeData.aspect && (readData.aspect != writeData.aspect))
1434 continue;
1435
1436 const std::string name = syncData.casePrefix + writeData.name + "_to_" + readData.name;
1437 noneStageTests->addChild(
1438 new NoneStageTestCase(testCtx, name,
1439 {syncData.type, syncData.useGenericAccessFlags, writeData.token,
1440 writeData.aspect, readData.token, readData.aspect}));
1441 }
1442 }
1443 }
1444
1445 return noneStageTests.release();
1446 }
1447
1448 } // namespace synchronization
1449 } // namespace vkt
1450