1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 The Khronos Group Inc.
6 * Copyright (c) 2021 Google 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 Transient attachment tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktFragmentOperationsTransientAttachmentTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28
29 #include "vkDefs.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkBarrierUtil.hpp"
38
39 #include "tcuImageCompare.hpp"
40 #include "tcuTestLog.hpp"
41 #include "tcuTextureUtil.hpp"
42 #include "tcuVector.hpp"
43
44 #include "deUniquePtr.hpp"
45
46 namespace vkt
47 {
48 namespace FragmentOperations
49 {
50 using namespace vk;
51 using de::UniquePtr;
52
53 namespace
54 {
55
56 enum class TestMode
57 {
58 MODE_INVALID = 1u << 0,
59 MODE_COLOR = 1u << 1,
60 MODE_DEPTH = 1u << 2,
61 MODE_STENCIL = 1u << 3
62 };
63
memoryPropertyFlagBitToString(VkMemoryPropertyFlags flagBit)64 const char* memoryPropertyFlagBitToString(VkMemoryPropertyFlags flagBit)
65 {
66 switch (flagBit)
67 {
68 case VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT:
69 return "VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT";
70
71 case VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT:
72 return "VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT";
73
74 case VK_MEMORY_PROPERTY_HOST_COHERENT_BIT:
75 return "VK_MEMORY_PROPERTY_HOST_COHERENT_BIT";
76
77 case VK_MEMORY_PROPERTY_HOST_CACHED_BIT:
78 return "VK_MEMORY_PROPERTY_HOST_CACHED_BIT";
79
80 case VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT:
81 return "VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT";
82
83 case VK_MEMORY_PROPERTY_PROTECTED_BIT:
84 return "VK_MEMORY_PROPERTY_PROTECTED_BIT";
85
86 #ifndef CTS_USES_VULKANSC
87 case VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD:
88 return "VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD";
89
90 case VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD:
91 return "VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD";
92
93 case VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV:
94 return "VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV";
95 #endif // CTS_USES_VULKANSC
96
97 default:
98 TCU_THROW(InternalError, "Unknown memory property flag bit");
99 }
100 };
101
getSupportedStencilFormat(const VkPhysicalDevice physDevice,const InstanceInterface & instanceInterface)102 VkFormat getSupportedStencilFormat(const VkPhysicalDevice physDevice, const InstanceInterface& instanceInterface)
103 {
104 static const VkFormat stencilFormats[] =
105 {
106 VK_FORMAT_D16_UNORM_S8_UINT,
107 VK_FORMAT_D24_UNORM_S8_UINT,
108 VK_FORMAT_D32_SFLOAT_S8_UINT,
109 };
110
111 for (const auto& sFormat : stencilFormats)
112 {
113 VkFormatProperties formatProps;
114 instanceInterface.getPhysicalDeviceFormatProperties(physDevice, sFormat, &formatProps);
115
116 if ((formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0)
117 {
118 return sFormat;
119 };
120 }
121
122 return VK_FORMAT_UNDEFINED;
123 }
124
getMemoryTypeIndices(VkMemoryPropertyFlags propertyFlag,const VkPhysicalDeviceMemoryProperties & pMemoryProperties)125 std::vector<deUint32> getMemoryTypeIndices(VkMemoryPropertyFlags propertyFlag, const VkPhysicalDeviceMemoryProperties& pMemoryProperties)
126 {
127 std::vector<deUint32> indices;
128 for (deUint32 typeIndex = 0u; typeIndex < pMemoryProperties.memoryTypeCount; ++typeIndex)
129 {
130 if ((pMemoryProperties.memoryTypes[typeIndex].propertyFlags & propertyFlag) == propertyFlag)
131 indices.push_back(typeIndex);
132 }
133 return indices;
134 }
135
makeImageCreateInfo(const VkFormat format,const tcu::IVec2 & size,VkImageUsageFlags usage)136 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const tcu::IVec2& size, VkImageUsageFlags usage)
137 {
138 const VkImageCreateInfo imageParams =
139 {
140 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
141 DE_NULL, // const void* pNext;
142 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
143 VK_IMAGE_TYPE_2D, // VkImageType imageType;
144 format, // VkFormat format;
145 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
146 1u, // deUint32 mipLevels;
147 1u, // deUint32 arrayLayers;
148 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
149 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
150 usage, // VkImageUsageFlags usage;
151 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
152 0u, // deUint32 queueFamilyIndexCount;
153 DE_NULL, // const deUint32* pQueueFamilyIndices;
154 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
155 };
156 return imageParams;
157 }
158
makeAttachment(const VkFormat format,const VkAttachmentLoadOp loadOp,const VkAttachmentStoreOp storeOp,const VkImageLayout initialLayout,const VkImageLayout finalLayout)159 VkAttachmentDescription makeAttachment (
160 const VkFormat format,
161 const VkAttachmentLoadOp loadOp,
162 const VkAttachmentStoreOp storeOp,
163 const VkImageLayout initialLayout,
164 const VkImageLayout finalLayout)
165 {
166 const tcu::TextureFormat tcuFormat = mapVkFormat(format);
167 const bool hasStencil = (tcuFormat.order == tcu::TextureFormat::DS
168 || tcuFormat.order == tcu::TextureFormat::S);
169
170 const VkAttachmentDescription attachmentDesc =
171 {
172 VkAttachmentDescriptionFlags(0), // VkAttachmentDescriptionFlags flags;
173 format, // VkFormat format;
174 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
175 loadOp, // VkAttachmentLoadOp loadOp;
176 storeOp, // VkAttachmentStoreOp storeOp;
177 hasStencil ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
178 hasStencil ? storeOp : VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
179 initialLayout, // VkImageLayout initialLayout;
180 finalLayout // VkImageLayout finalLayout;
181 };
182
183 return attachmentDesc;
184 }
185
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const std::vector<VkAttachmentDescription> attachmentDescriptions,const bool hasInputAttachment)186 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk, const VkDevice device, const std::vector<VkAttachmentDescription> attachmentDescriptions, const bool hasInputAttachment)
187 {
188 const tcu::TextureFormat tcuFormat = mapVkFormat(attachmentDescriptions[0].format);
189 const bool hasDepthStencil = (tcuFormat.order == tcu::TextureFormat::DS
190 || tcuFormat.order == tcu::TextureFormat::S
191 || tcuFormat.order == tcu::TextureFormat::D);
192
193 std::vector< VkAttachmentReference> testReferences;
194 const deUint32 maxAttachmentIndex = deUint32(attachmentDescriptions.size()) - 1u;
195
196 for (deUint32 ref = 0; ref < attachmentDescriptions.size(); ref++)
197 {
198 testReferences.push_back({ ref, attachmentDescriptions[ref].finalLayout });
199 }
200
201 const VkSubpassDescription subpassDescription =
202 {
203 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
204 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
205 hasInputAttachment ? 1u :0u, // deUint32 inputAttachmentCount
206 hasInputAttachment ? &testReferences[0] : DE_NULL, // const VkAttachmentReference* pInputAttachments
207 !hasDepthStencil || hasInputAttachment ? 1u : 0u, // deUint32 colorAttachmentCount
208 !hasDepthStencil || hasInputAttachment ? &testReferences[maxAttachmentIndex] : DE_NULL, // const VkAttachmentReference* pColorAttachments
209 DE_NULL, // const VkAttachmentReference* pResolveAttachments
210 hasDepthStencil && !hasInputAttachment ? &testReferences[0] : DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
211 0u, // deUint32 preserveAttachmentCount
212 DE_NULL // const deUint32* pPreserveAttachments
213 };
214
215 const VkRenderPassCreateInfo renderPassInfo =
216 {
217 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
218 DE_NULL, // const void* pNext
219 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
220 deUint32(attachmentDescriptions.size()), // deUint32 attachmentCount
221 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments
222 1u, // deUint32 subpassCount
223 &subpassDescription, // const VkSubpassDescription* pSubpasses
224 0u, // deUint32 dependencyCount
225 DE_NULL // const VkSubpassDependency* pDependencies
226 };
227
228 return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
229 }
230
231 class TransientAttachmentTest : public TestCase
232 {
233 public:
234 TransientAttachmentTest (tcu::TestContext& testCtx,
235 const std::string name,
236 const TestMode testMode,
237 const VkMemoryPropertyFlags flags,
238 const tcu::IVec2 renderSize);
239
240 void initPrograms (SourceCollections& programCollection) const;
241 TestInstance* createInstance (Context& context) const;
242 virtual void checkSupport (Context& context) const;
243
244 private:
245 const TestMode m_testMode;
246 const VkMemoryPropertyFlags m_flags;
247 const tcu::IVec2 m_renderSize;
248 };
249
TransientAttachmentTest(tcu::TestContext & testCtx,const std::string name,const TestMode testMode,const VkMemoryPropertyFlags flags,const tcu::IVec2 renderSize)250 TransientAttachmentTest::TransientAttachmentTest (
251 tcu::TestContext& testCtx,
252 const std::string name,
253 const TestMode testMode,
254 const VkMemoryPropertyFlags flags,
255 const tcu::IVec2 renderSize)
256 : TestCase (testCtx, name, "")
257 , m_testMode (testMode)
258 , m_flags (flags)
259 , m_renderSize (renderSize)
260 {
261 }
262
initPrograms(SourceCollections & programCollection) const263 void TransientAttachmentTest::initPrograms (SourceCollections& programCollection) const
264 {
265 // Vertex shader
266 {
267 std::ostringstream src;
268
269 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
270 << "\n"
271 << "layout(location = 0) in vec4 position;\n"
272 << "\n"
273 << "out gl_PerVertex\n"
274 << "{\n"
275 << " vec4 gl_Position;\n"
276 << "};\n"
277 << "\n"
278 << "void main (void)\n"
279 << "{\n"
280 << " gl_Position = position;\n"
281 << "}\n";
282
283 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
284 }
285
286 // Fragment shader
287 {
288 std::ostringstream src;
289
290 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
291 << "\n"
292 << "layout(input_attachment_index = 0, binding = 0) uniform " << (m_testMode == TestMode::MODE_STENCIL ? "usubpassInput " : "subpassInput ") << "inputValue;\n"
293 << "\n"
294 << "layout(location = 0) out vec4 fragColor;\n"
295 << "\n"
296 << "void main (void)\n"
297 << "{\n"
298 << " fragColor = " << (m_testMode == TestMode::MODE_COLOR ? "subpassLoad(inputValue);\n"
299 : m_testMode == TestMode::MODE_DEPTH ? "vec4(subpassLoad(inputValue).r, 0.0, 0.0, 1.0);\n"
300 : /* TestMode::MODE_STENCIL */"vec4(0.0, 0.0, float(subpassLoad(inputValue).r) / 256.0, 1.0);\n")
301 << "}\n";
302
303 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
304 }
305 }
306
checkSupport(Context & context) const307 void TransientAttachmentTest::checkSupport (Context& context) const
308 {
309 const InstanceInterface& vki = context.getInstanceInterface();
310 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
311 VkImageFormatProperties formatProperties;
312 const VkPhysicalDeviceMemoryProperties pMemoryProperties = getPhysicalDeviceMemoryProperties(vki,physicalDevice);
313 const std::vector<deUint32> memoryTypeIndices = getMemoryTypeIndices(m_flags, pMemoryProperties);
314
315 const VkFormat testFormat = m_testMode == TestMode::MODE_DEPTH
316 ? VK_FORMAT_D16_UNORM
317 : m_testMode == TestMode::MODE_STENCIL
318 ? getSupportedStencilFormat(context.getPhysicalDevice(), context.getInstanceInterface())
319 : VK_FORMAT_R8G8B8A8_UNORM;
320
321 if (memoryTypeIndices.empty())
322 {
323 TCU_THROW(NotSupportedError, std::string(memoryPropertyFlagBitToString(m_flags)) + " is not supported by any memory type");
324 }
325
326 vki.getPhysicalDeviceImageFormatProperties (physicalDevice, testFormat,
327 VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
328 (m_testMode == TestMode::MODE_DEPTH || m_testMode == TestMode::MODE_STENCIL)
329 ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT
330 : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
331 0u, &formatProperties);
332
333 if (formatProperties.sampleCounts == 0 || testFormat == VK_FORMAT_UNDEFINED)
334 TCU_THROW(NotSupportedError, de::toString(testFormat) + " not supported");
335 }
336
337 class TransientAttachmentTestInstance : public TestInstance
338 {
339 public:
340 TransientAttachmentTestInstance (Context& context,
341 const TestMode testMode,
342 const VkMemoryPropertyFlags flags,
343 const tcu::IVec2 renderSize);
344
345 tcu::TestStatus iterate (void);
346
347 private:
348 const TestMode m_testMode;
349 const tcu::IVec2 m_renderSize;
350 const VkImageAspectFlags m_aspectFlags;
351 const VkImageUsageFlags m_usageFlags;
352 const VkFormat m_testFormat;
353 const vk::MemoryRequirement m_memReq;
354 };
355
TransientAttachmentTestInstance(Context & context,const TestMode testMode,const VkMemoryPropertyFlags flags,const tcu::IVec2 renderSize)356 TransientAttachmentTestInstance::TransientAttachmentTestInstance (Context& context, const TestMode testMode, const VkMemoryPropertyFlags flags, const tcu::IVec2 renderSize)
357 : TestInstance (context)
358 , m_testMode (testMode)
359 , m_renderSize (renderSize)
360 , m_aspectFlags ( testMode == TestMode::MODE_DEPTH ? VkImageAspectFlagBits::VK_IMAGE_ASPECT_DEPTH_BIT
361 : testMode == TestMode::MODE_STENCIL ? VkImageAspectFlagBits::VK_IMAGE_ASPECT_STENCIL_BIT
362 : VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT)
363 , m_usageFlags ( testMode == TestMode::MODE_COLOR ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
364 : VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
365 , m_testFormat ( testMode == TestMode::MODE_DEPTH ? VK_FORMAT_D16_UNORM
366 : testMode == TestMode::MODE_STENCIL ? getSupportedStencilFormat(m_context.getPhysicalDevice(), m_context.getInstanceInterface())
367 : VK_FORMAT_R8G8B8A8_UNORM)
368 , m_memReq (flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
369 ? MemoryRequirement::LazilyAllocated
370 : MemoryRequirement::Local)
371 {
372 DE_ASSERT(m_testMode != TestMode::MODE_INVALID);
373 }
374
iterate(void)375 tcu::TestStatus TransientAttachmentTestInstance::iterate (void)
376 {
377 const DeviceInterface& vk = m_context.getDeviceInterface();
378 const VkDevice device = m_context.getDevice();
379 const VkQueue queue = m_context.getUniversalQueue();
380 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
381 Allocator& allocator = m_context.getDefaultAllocator();
382 const VkImageSubresourceRange testSubresourceRange = makeImageSubresourceRange(m_aspectFlags, 0u, 1u, 0u, 1u);
383 const VkFormat outputFormat = VK_FORMAT_R8G8B8A8_UNORM;
384 const VkImageAspectFlags outputAspectFlags = VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT;
385 const VkImageUsageFlags outputUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
386
387 // Test attachment
388 const Unique<VkImage> inputImage (makeImage(vk, device, makeImageCreateInfo(m_testFormat, m_renderSize, m_usageFlags)));
389 const UniquePtr<Allocation> inputImageAllocator (bindImage(vk, device, allocator, *inputImage, m_memReq));
390 const Unique<VkImageView> inputImageView (makeImageView(vk, device, *inputImage, VK_IMAGE_VIEW_TYPE_2D, m_testFormat, testSubresourceRange));
391 const VkImageView firstAttachmentImages[] = { *inputImageView };
392
393 const VkImageSubresourceRange outputSubresourceRange = makeImageSubresourceRange(outputAspectFlags, 0u, 1u, 0u, 1u);
394 const Unique<VkImage> outputImage (makeImage(vk, device, makeImageCreateInfo(outputFormat, m_renderSize, outputUsageFlags)));
395 const UniquePtr<Allocation> outputImageAllocator (bindImage(vk, device, allocator, *outputImage, MemoryRequirement::Local));
396 const Unique<VkImageView> outputImageView (makeImageView(vk, device, *outputImage, VK_IMAGE_VIEW_TYPE_2D, outputFormat, outputSubresourceRange));
397 const VkImageView secondAttachmentImages[] = { *inputImageView, *outputImageView };
398
399 const VkDeviceSize resultBufferSizeBytes = tcu::getPixelSize(mapVkFormat(outputFormat)) * m_renderSize.x() * m_renderSize.y();
400 const Unique<VkBuffer> resultBuffer (makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
401 const UniquePtr<Allocation> resultBufferAlloc (bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
402
403 // Main vertex buffer
404 const deUint32 numVertices = 6;
405 const VkDeviceSize vertexBufferSizeBytes = 256;
406 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
407 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
408
409 {
410 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
411
412 pVertices[0] = tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f);
413 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
414 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f);
415 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f);
416 pVertices[4] = tcu::Vec4( 1.0f, 1.0f, 1.0f, 1.0f);
417 pVertices[5] = tcu::Vec4( 1.0f, -1.0f, 1.0f, 1.0f);
418
419 flushAlloc(vk, device, *vertexBufferAlloc);
420 }
421
422 // Shader modules
423 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
424 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
425
426 // Descriptor pool and descriptor set
427 DescriptorPoolBuilder poolBuilder;
428 {
429 poolBuilder.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u);
430 }
431
432 const auto descriptorPool = poolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
433
434 DescriptorSetLayoutBuilder layoutBuilderAttachments;
435 {
436 layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT);
437 }
438
439 const auto inputAttachmentsSetLayout = layoutBuilderAttachments.build(vk, device);
440 const auto descriptorSetAttachments = makeDescriptorSet(vk, device, descriptorPool.get(), inputAttachmentsSetLayout.get());
441 const std::vector<VkDescriptorSet> descriptorSets = { descriptorSetAttachments.get() };
442
443 const VkDescriptorImageInfo imageInfo =
444 {
445 DE_NULL, // VkSampler sampler;
446 *inputImageView, // VkImageView imageView;
447 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout;
448 };
449
450 DescriptorSetUpdateBuilder updater;
451 {
452 updater.writeSingle(descriptorSetAttachments.get(), DescriptorSetUpdateBuilder::Location::binding(static_cast<deUint32>(0)), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfo);
453 updater.update(vk, device);
454 }
455
456 const bool isDepthStencil = isDepthStencilFormat(m_testFormat);
457 VkImageLayout inputLayout = isDepthStencil
458 ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
459 : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
460
461 // Renderpasses
462 VkAttachmentDescription clearPassAttachment = makeAttachment(m_testFormat, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, inputLayout);
463 VkAttachmentDescription inputPassAttachment = makeAttachment(m_testFormat, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, inputLayout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
464 VkAttachmentDescription outputPassAttachment = makeAttachment(outputFormat, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
465
466 const Unique<VkRenderPass> renderPassOne (makeRenderPass(vk, device, { clearPassAttachment }, false));
467 const Unique<VkRenderPass> renderPassTwo (makeRenderPass(vk, device, { inputPassAttachment, outputPassAttachment }, true));
468
469 const Unique<VkFramebuffer> framebufferOne (makeFramebuffer(vk, device, *renderPassOne, 1, firstAttachmentImages, m_renderSize.x(), m_renderSize.y()));
470 const Unique<VkFramebuffer> framebufferTwo (makeFramebuffer(vk, device, *renderPassTwo, 2, secondAttachmentImages, m_renderSize.x(), m_renderSize.y()));
471
472 // Pipeline
473 const std::vector<VkViewport> viewports (1, makeViewport(m_renderSize));
474 const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize));
475 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *inputAttachmentsSetLayout));
476 const Unique<VkPipeline> pipeline (vk::makeGraphicsPipeline(vk, // const DeviceInterface& vk
477 device, // const VkDevice device
478 *pipelineLayout, // const VkPipelineLayout pipelineLayout
479 *vertexModule, // const VkShaderModule vertexShaderModule
480 DE_NULL, // const VkShaderModule essellationControlModule
481 DE_NULL, // const VkShaderModule tessellationEvalModule
482 DE_NULL, // const VkShaderModule geometryShaderModule
483 *fragmentModule, // const VkShaderModule fragmentShaderModule
484 *renderPassTwo, // const VkRenderPass renderPass
485 viewports, // const std::vector<VkViewport>& viewports
486 scissors, // const std::vector<VkRect2D>& scissors
487 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
488 0u, // const deUint32 subpass
489 0u)); // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
490
491 // Command buffer
492 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
493 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
494
495 {
496 const VkDeviceSize vertexBufferOffset = 0ull;
497 VkClearValue clearValue;
498
499 if (m_testMode == TestMode::MODE_COLOR) clearValue.color = { { 1.0f, 1.0f, 0.0f, 1.0f } };
500 else if (m_testMode == TestMode::MODE_DEPTH) clearValue.depthStencil.depth = 0.5f;
501 else if (m_testMode == TestMode::MODE_STENCIL) clearValue.depthStencil = { 0.0f, 128u };
502
503 const VkRect2D renderArea =
504 {
505 makeOffset2D(0, 0),
506 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
507 };
508
509 beginCommandBuffer(vk, *cmdBuffer);
510
511 // Clear attachment
512 beginRenderPass(vk, *cmdBuffer, *renderPassOne, *framebufferOne, renderArea, clearValue);
513 endRenderPass(vk, *cmdBuffer);
514
515 // Synchronize clear and read operations.
516 {
517 const auto srcAccess = isDepthStencil ? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
518 const auto dstAccess = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
519 const auto srcStage = isDepthStencil ? (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT) : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
520 const auto dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
521 const auto clearToLoad = makeMemoryBarrier(srcAccess, dstAccess);
522 cmdPipelineMemoryBarrier(vk, *cmdBuffer, srcStage, dstStage, &clearToLoad);
523 }
524
525 // Draw with input attachment
526 beginRenderPass(vk, *cmdBuffer, *renderPassTwo, *framebufferTwo, renderArea);
527 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
528 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
529 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, static_cast<deUint32>(descriptorSets.size()), descriptorSets.data(), 0u, nullptr);
530 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
531 endRenderPass(vk, *cmdBuffer);
532
533 copyImageToBuffer(vk, *cmdBuffer, *outputImage, *resultBuffer, m_renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, outputPassAttachment.finalLayout, 1u, outputAspectFlags, outputAspectFlags);
534
535 endCommandBuffer(vk, *cmdBuffer);
536 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
537 }
538
539 // Verify results
540 {
541 invalidateAlloc(vk, device, *resultBufferAlloc);
542
543 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(outputFormat), m_renderSize.x(), m_renderSize.y(), 1, resultBufferAlloc->getHostPtr());
544 tcu::TextureLevel referenceImage(mapVkFormat(outputFormat), m_renderSize.x(), m_renderSize.y());
545 const tcu::Vec4 clearColor = m_testMode == TestMode::MODE_COLOR
546 ? tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f)
547 : m_testMode == TestMode::MODE_DEPTH ? tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f)
548 : tcu::Vec4(0.0f, 0.0f, 0.5f, 1.0f);
549
550 tcu::clear(referenceImage.getAccess(), clearColor);
551
552 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
553 {
554 return tcu::TestStatus::fail("Rendered color image is not correct");
555 }
556 }
557
558 return tcu::TestStatus::pass("Success");
559 }
560
createInstance(Context & context) const561 TestInstance* TransientAttachmentTest::createInstance (Context& context) const
562 {
563 return new TransientAttachmentTestInstance(context, m_testMode, m_flags, m_renderSize);
564 }
565
566 } // anonymous
567
createTransientAttachmentTests(tcu::TestContext & testCtx)568 tcu::TestCaseGroup* createTransientAttachmentTests(tcu::TestContext& testCtx)
569 {
570 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "transient_attachment_bit", "image usage transient attachment bit load and store op test"));
571
572 {
573 static const struct
574 {
575 std::string caseName;
576 TestMode testMode;
577 const VkMemoryPropertyFlags flags;
578 } cases[] =
579 {
580 { "color_load_store_op_test_lazy_bit", TestMode::MODE_COLOR , VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT},
581 { "depth_load_store_op_test_lazy_bit", TestMode::MODE_DEPTH , VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT},
582 { "stencil_load_store_op_test_lazy_bit", TestMode::MODE_STENCIL , VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT},
583 { "color_load_store_op_test_local_bit", TestMode::MODE_COLOR , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT},
584 { "depth_load_store_op_test_local_bit", TestMode::MODE_DEPTH , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT},
585 { "stencil_load_store_op_test_local_bit", TestMode::MODE_STENCIL , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT}
586 };
587
588 for (const auto& testCase: cases)
589 {
590 testGroup->addChild(new TransientAttachmentTest(testCtx, testCase.caseName, testCase.testMode, testCase.flags, tcu::IVec2(32, 32)));
591 }
592 }
593
594 return testGroup.release();
595 }
596
597 } // FragmentOperations
598 } // vkt
599