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