1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 The Khronos Group Inc.
6 * Copyright (c) 2018 Google Inc.
7 * Copyright (c) 2015 Imagination Technologies Ltd.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Tests attachments unused by subpasses
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktRenderPassUnusedAttachmentTests.hpp"
27 #include "pipeline/vktPipelineImageUtil.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkRef.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkCmdUtil.hpp"
39 #include "vkObjUtil.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuPlatform.hpp"
42 #include "tcuTextureUtil.hpp"
43 #include "tcuTestLog.hpp"
44 #include "deStringUtil.hpp"
45 #include "deUniquePtr.hpp"
46 #include "deRandom.hpp"
47 #include <cstring>
48 #include <set>
49 #include <sstream>
50 #include <vector>
51
52 namespace vkt
53 {
54 namespace renderpass
55 {
56
57 using namespace vk;
58
59 namespace
60 {
61
62 struct TestParams
63 {
64 VkAttachmentLoadOp loadOp;
65 VkAttachmentStoreOp storeOp;
66 VkAttachmentLoadOp stencilLoadOp;
67 VkAttachmentStoreOp stencilStoreOp;
68 RenderPassType renderPassType;
69 };
70
71 struct Vertex4RGBA
72 {
73 tcu::Vec4 position;
74 tcu::Vec4 color;
75 };
76
createQuad(void)77 std::vector<Vertex4RGBA> createQuad (void)
78 {
79 std::vector<Vertex4RGBA> vertices;
80
81 const float size = 0.8f;
82 const tcu::Vec4 color (0.2f, 0.3f, 0.1f, 1.0f);
83 const Vertex4RGBA lowerLeftVertex = {tcu::Vec4(-size, -size, 0.0f, 1.0f), color};
84 const Vertex4RGBA lowerRightVertex = {tcu::Vec4(size, -size, 0.0f, 1.0f), color};
85 const Vertex4RGBA upperLeftVertex = {tcu::Vec4(-size, size, 0.0f, 1.0f), color};
86 const Vertex4RGBA upperRightVertex = {tcu::Vec4(size, size, 0.0f, 1.0f), color};
87
88 vertices.push_back(lowerLeftVertex);
89 vertices.push_back(lowerRightVertex);
90 vertices.push_back(upperLeftVertex);
91 vertices.push_back(upperLeftVertex);
92 vertices.push_back(lowerRightVertex);
93 vertices.push_back(upperRightVertex);
94
95 return vertices;
96 }
97
98 template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vk,VkDevice vkDevice,const TestParams testParams)99 Move<VkRenderPass> createRenderPass (const DeviceInterface& vk,
100 VkDevice vkDevice,
101 const TestParams testParams)
102 {
103 const VkImageAspectFlags aspectMask = testParams.renderPassType == RENDERPASS_TYPE_LEGACY ? 0 : VK_IMAGE_ASPECT_COLOR_BIT;
104 const AttachmentDesc attachmentDescriptions[] =
105 {
106 // Result attachment
107 AttachmentDesc (
108 DE_NULL, // const void* pNext
109 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
110 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format
111 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
112 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
113 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
114 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
115 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
116 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
117 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
118 ),
119 // Unused attachment
120 AttachmentDesc (
121 DE_NULL, // const void* pNext
122 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
123 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format
124 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
125 testParams.loadOp, // VkAttachmentLoadOp loadOp
126 testParams.storeOp, // VkAttachmentStoreOp storeOp
127 testParams.stencilLoadOp, // VkAttachmentLoadOp stencilLoadOp
128 testParams.stencilStoreOp, // VkAttachmentStoreOp stencilStoreOp
129 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
130 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
131 ),
132 // Input attachment
133 AttachmentDesc (
134 DE_NULL, // const void* pNext
135 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
136 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format
137 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
138 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
139 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
140 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
141 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
142 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
143 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
144 )
145 };
146
147 // Note: Attachment 1 is not referenced by any subpass.
148 const AttachmentRef resultAttachmentRefSubpass0 (
149 DE_NULL, // const void* pNext
150 2u, // deUint32 attachment
151 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
152 aspectMask // VkImageAspectFlags aspectMask
153 );
154
155 const AttachmentRef resultAttachmentRefSubpass1 (
156 DE_NULL, // const void* pNext
157 0u, // deUint32 attachment
158 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
159 aspectMask // VkImageAspectFlags aspectMask
160 );
161
162 const AttachmentRef inputAttachmentRefSubpass1 (
163 DE_NULL, // const void* pNext
164 2u, // deUint32 attachment
165 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout layout
166 aspectMask // VkImageAspectFlags aspectMask
167 );
168
169 const SubpassDesc subpassDescriptions[] =
170 {
171 SubpassDesc (
172 DE_NULL,
173 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
174 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
175 0u, // deUint32 viewMask
176 0u, // deUint32 inputAttachmentCount
177 DE_NULL, // const VkAttachmentReference* pInputAttachments
178 1u, // deUint32 colorAttachmentCount
179 &resultAttachmentRefSubpass0, // const VkAttachmentReference* pColorAttachments
180 DE_NULL, // const VkAttachmentReference* pResolveAttachments
181 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
182 0u, // deUint32 preserveAttachmentCount
183 DE_NULL // const deUint32* pPreserveAttachments
184 ),
185 SubpassDesc (
186 DE_NULL,
187 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
188 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
189 0u, // deUint32 viewMask
190 1u, // deUint32 inputAttachmentCount
191 &inputAttachmentRefSubpass1, // const VkAttachmentReference* pInputAttachments
192 1u, // deUint32 colorAttachmentCount
193 &resultAttachmentRefSubpass1, // const VkAttachmentReference* pColorAttachments
194 DE_NULL, // const VkAttachmentReference* pResolveAttachments
195 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
196 0u, // deUint32 preserveAttachmentCount
197 DE_NULL // const deUint32* pPreserveAttachments
198 )
199 };
200
201 const SubpassDep subpassDependency (
202 DE_NULL, // const void* pNext
203 0u, // uint32_t srcSubpass
204 1u, // uint32_t dstSubpass
205 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask
206 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask
207 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask
208 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask
209 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags
210 0u // deInt32 viewOffset
211 );
212
213 const RenderPassCreateInfo renderPassInfo (
214 DE_NULL, // const void* pNext
215 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
216 3u, // deUint32 attachmentCount
217 attachmentDescriptions, // const VkAttachmentDescription* pAttachments
218 2u, // deUint32 subpassCount
219 subpassDescriptions, // const VkSubpassDescription* pSubpasses
220 1u, // deUint32 dependencyCount
221 &subpassDependency, // const VkSubpassDependency* pDependencies
222 0u, // deUint32 correlatedViewMaskCount
223 DE_NULL // const deUint32* pCorrelatedViewMasks
224 );
225
226 return renderPassInfo.createRenderPass(vk, vkDevice);
227 }
228
229 class UnusedAttachmentTest : public vkt::TestCase
230 {
231 public:
232 UnusedAttachmentTest (tcu::TestContext& testContext,
233 const std::string& name,
234 const std::string& description,
235 const TestParams& testParams);
236 virtual ~UnusedAttachmentTest (void);
237 virtual void initPrograms (SourceCollections& sourceCollections) const;
238 virtual TestInstance* createInstance (Context& context) const;
239 private:
240 const TestParams m_testParams;
241 };
242
243 class UnusedAttachmentTestInstance : public vkt::TestInstance
244 {
245 public:
246 UnusedAttachmentTestInstance (Context& context,
247 const TestParams& testParams);
248 virtual ~UnusedAttachmentTestInstance (void);
249 virtual tcu::TestStatus iterate (void);
250 template<typename RenderpassSubpass>
251 void createCommandBuffer (const DeviceInterface& vk,
252 VkDevice vkDevice);
253 private:
254 tcu::TestStatus verifyImage (void);
255
256 const tcu::UVec2 m_renderSize;
257
258 Move<VkImage> m_colorImage;
259 de::MovePtr<Allocation> m_colorImageAlloc;
260 Move<VkImageView> m_colorAttachmentView;
261
262 Move<VkImage> m_unusedImage;
263 de::MovePtr<Allocation> m_unusedImageAlloc;
264 Move<VkImageView> m_unusedAttachmentView;
265
266 Move<VkImage> m_inputImage;
267 de::MovePtr<Allocation> m_inputImageAlloc;
268 Move<VkImageView> m_inputAttachmentView;
269
270 Move<VkDescriptorSetLayout> m_descriptorSetLayoutSubpass0;
271 Move<VkDescriptorSetLayout> m_descriptorSetLayoutSubpass1;
272 Move<VkDescriptorPool> m_descriptorPool;
273 Move<VkDescriptorSet> m_descriptorSetSubpass1;
274 Move<VkRenderPass> m_renderPass;
275 Move<VkFramebuffer> m_framebuffer;
276
277 Move<VkShaderModule> m_vertexShaderModule;
278 Move<VkShaderModule> m_fragmentShaderModuleSubpass0;
279 Move<VkShaderModule> m_fragmentShaderModuleSubpass1;
280
281 Move<VkBuffer> m_vertexBuffer;
282 std::vector<Vertex4RGBA> m_vertices;
283 de::MovePtr<Allocation> m_vertexBufferAlloc;
284
285 Move<VkBuffer> m_backingBuffer;
286 de::MovePtr<Allocation> m_backingBufferAlloc;
287
288 Move<VkPipelineLayout> m_pipelineLayoutSubpass0;
289 Move<VkPipelineLayout> m_pipelineLayoutSubpass1;
290 Move<VkPipeline> m_graphicsPipelineSubpass0;
291 Move<VkPipeline> m_graphicsPipelineSubpass1;
292
293 Move<VkCommandPool> m_cmdPool;
294 Move<VkCommandBuffer> m_cmdBuffer;
295 };
296
UnusedAttachmentTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const TestParams & testParams)297 UnusedAttachmentTest::UnusedAttachmentTest (tcu::TestContext& testContext,
298 const std::string& name,
299 const std::string& description,
300 const TestParams& testParams)
301 : vkt::TestCase (testContext, name, description)
302 , m_testParams (testParams)
303 {
304 }
305
~UnusedAttachmentTest(void)306 UnusedAttachmentTest::~UnusedAttachmentTest (void)
307 {
308 }
309
createInstance(Context & context) const310 TestInstance* UnusedAttachmentTest::createInstance (Context& context) const
311 {
312 return new UnusedAttachmentTestInstance(context, m_testParams);
313 }
314
initPrograms(SourceCollections & sourceCollections) const315 void UnusedAttachmentTest::initPrograms (SourceCollections& sourceCollections) const
316 {
317 std::ostringstream fragmentSource;
318
319 sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
320 "#version 450\n"
321 "layout(location = 0) in highp vec4 position;\n"
322 "layout(location = 1) in highp vec4 color;\n"
323 "layout(location = 0) out highp vec4 vtxColor;\n"
324 "void main (void)\n"
325 "{\n"
326 " gl_Position = position;\n"
327 " vtxColor = color;\n"
328 "}\n");
329
330 sourceCollections.glslSources.add("color_frag_sb0") << glu::FragmentSource(
331 "#version 450\n"
332 "layout(location = 0) in highp vec4 vtxColor;\n"
333 "layout(location = 0) out highp vec4 fragColor;\n"
334 "void main (void)\n"
335 "{\n"
336 " fragColor = vtxColor;\n"
337 "}\n");
338
339 sourceCollections.glslSources.add("color_frag_sb1") << glu::FragmentSource(
340 "#version 450\n"
341 "layout(location = 0) in highp vec4 vtxColor;\n"
342 "layout(location = 0) out highp vec4 fragColor;\n"
343 "layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputColor;"
344 "void main (void)\n"
345 "{\n"
346 " fragColor = subpassLoad(inputColor) + vtxColor;\n"
347 "}\n");
348 }
349
UnusedAttachmentTestInstance(Context & context,const TestParams & testParams)350 UnusedAttachmentTestInstance::UnusedAttachmentTestInstance (Context& context,
351 const TestParams& testParams)
352 : vkt::TestInstance (context)
353 , m_renderSize (32u, 32u)
354 , m_vertices (createQuad())
355 {
356 const DeviceInterface& vk = m_context.getDeviceInterface();
357 const VkDevice vkDevice = m_context.getDevice();
358 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
359 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
360 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
361
362 // Check for renderpass2 extension if used
363 if (testParams.renderPassType == RENDERPASS_TYPE_RENDERPASS2)
364 context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
365
366 // Create color image
367 {
368 const VkImageCreateInfo colorImageParams =
369 {
370 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
371 DE_NULL, // const void* pNext;
372 0u, // VkImageCreateFlags flags;
373 VK_IMAGE_TYPE_2D, // VkImageType imageType;
374 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
375 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
376 1u, // deUint32 mipLevels;
377 1u, // deUint32 arrayLayers;
378 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
379 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
380 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
381 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
382 1u, // deUint32 queueFamilyIndexCount;
383 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
384 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
385 };
386
387 m_colorImage = createImage(vk, vkDevice, &colorImageParams);
388
389 // Allocate and bind color image memory
390 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
391 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
392 }
393
394 // Create image which is not used by any subpass
395 {
396 const VkImageCreateInfo unusedImageParams =
397 {
398 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
399 DE_NULL, // const void* pNext;
400 0u, // VkImageCreateFlags flags;
401 VK_IMAGE_TYPE_2D, // VkImageType imageType;
402 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
403 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
404 1u, // deUint32 mipLevels;
405 1u, // deUint32 arrayLayers;
406 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
407 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
408 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
409 | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
410 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
411 1u, // deUint32 queueFamilyIndexCount;
412 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
413 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
414 };
415
416 m_unusedImage = createImage(vk, vkDevice, &unusedImageParams);
417
418 // Allocate and bind unused image memory
419 VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vk, vkDevice, *m_unusedImage);
420
421 m_unusedImageAlloc = memAlloc.allocate(memoryRequirements, MemoryRequirement::Any);
422 VK_CHECK(vk.bindImageMemory(vkDevice, *m_unusedImage, m_unusedImageAlloc->getMemory(), m_unusedImageAlloc->getOffset()));
423
424 // Clear image with specific value to verify the contents don't change
425 {
426 const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
427 Move<VkCommandPool> cmdPool;
428 Move<VkCommandBuffer> cmdBuffer;
429
430 VkClearValue clearValue;
431 clearValue.color.float32[0] = 0.1f;
432 clearValue.color.float32[1] = 0.2f;
433 clearValue.color.float32[2] = 0.3f;
434 clearValue.color.float32[3] = 0.4f;
435
436 // Create command pool and buffer
437 cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
438 cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
439
440 const VkImageMemoryBarrier preImageBarrier =
441 {
442 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
443 DE_NULL, // const void* pNext;
444 0u, // VkAccessFlags srcAccessMask;
445 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
446 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
447 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
448 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
449 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
450 *m_unusedImage, // VkImage image;
451 { // VkImageSubresourceRange subresourceRange;
452 aspectMask, // VkImageAspect aspect;
453 0u, // deUint32 baseMipLevel;
454 1u, // deUint32 mipLevels;
455 0u, // deUint32 baseArraySlice;
456 1u // deUint32 arraySize;
457 }
458 };
459
460 const VkImageMemoryBarrier postImageBarrier =
461 {
462 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
463 DE_NULL, // const void* pNext;
464 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
465 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
466 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
467 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
468 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
469 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
470 *m_unusedImage, // VkImage image;
471 { // VkImageSubresourceRange subresourceRange;
472 aspectMask, // VkImageAspect aspect;
473 0u, // deUint32 baseMipLevel;
474 1u, // deUint32 mipLevels;
475 0u, // deUint32 baseArraySlice;
476 1u // deUint32 arraySize;
477 }
478 };
479
480 const VkImageSubresourceRange clearRange =
481 {
482 aspectMask, // VkImageAspectFlags aspectMask;
483 0u, // deUint32 baseMipLevel;
484 1u, // deUint32 levelCount;
485 0u, // deUint32 baseArrayLayer;
486 1u // deUint32 layerCount;
487 };
488
489 // Clear image
490 beginCommandBuffer(vk, *cmdBuffer);
491 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
492 vk.cmdClearColorImage(*cmdBuffer, *m_unusedImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &clearRange);
493 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
494 endCommandBuffer(vk, *cmdBuffer);
495
496 submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
497 }
498 }
499
500 // Create input image
501 {
502 const VkImageCreateInfo inputImageParams =
503 {
504 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
505 DE_NULL, // const void* pNext;
506 0u, // VkImageCreateFlags flags;
507 VK_IMAGE_TYPE_2D, // VkImageType imageType;
508 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
509 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
510 1u, // deUint32 mipLevels;
511 1u, // deUint32 arrayLayers;
512 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
513 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
514 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, // VkImageUsageFlags usage;
515 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
516 1u, // deUint32 queueFamilyIndexCount;
517 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
518 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
519 };
520
521 m_inputImage = createImage(vk, vkDevice, &inputImageParams);
522
523 // Allocate and bind input image memory
524 m_inputImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_inputImage), MemoryRequirement::Any);
525 VK_CHECK(vk.bindImageMemory(vkDevice, *m_inputImage, m_inputImageAlloc->getMemory(), m_inputImageAlloc->getOffset()));
526 }
527
528 // Create color attachment view
529 {
530 const VkImageViewCreateInfo colorAttachmentViewParams =
531 {
532 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
533 DE_NULL, // const void* pNext;
534 0u, // VkImageViewCreateFlags flags;
535 *m_colorImage, // VkImage image;
536 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
537 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
538 componentMappingRGBA, // VkChannelMapping channels;
539 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
540 };
541
542 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
543 }
544
545 // Create unused attachment view
546 {
547 const VkImageViewCreateInfo unusedAttachmentViewParams =
548 {
549 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
550 DE_NULL, // const void* pNext;
551 0u, // VkImageViewCreateFlags flags;
552 *m_unusedImage, // VkImage image;
553 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
554 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
555 componentMappingRGBA, // VkChannelMapping channels;
556 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
557 };
558
559 m_unusedAttachmentView = createImageView(vk, vkDevice, &unusedAttachmentViewParams);
560 }
561
562 // Create input attachment view
563 {
564 const VkImageViewCreateInfo inputAttachmentViewParams =
565 {
566 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
567 DE_NULL, // const void* pNext;
568 0u, // VkImageViewCreateFlags flags;
569 *m_inputImage, // VkImage image;
570 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
571 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
572 componentMappingRGBA, // VkChannelMapping channels;
573 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
574 };
575
576 m_inputAttachmentView = createImageView(vk, vkDevice, &inputAttachmentViewParams);
577 }
578
579 // Create render pass
580 if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
581 m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice, testParams);
582 else
583 m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice, testParams);
584
585 // Create framebuffer
586 {
587 const VkImageView imageViews[] =
588 {
589 *m_colorAttachmentView,
590 *m_unusedAttachmentView,
591 *m_inputAttachmentView
592 };
593
594 const VkFramebufferCreateInfo framebufferParams =
595 {
596 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
597 DE_NULL, // const void* pNext;
598 0u, // VkFramebufferCreateFlags flags;
599 *m_renderPass, // VkRenderPass renderPass;
600 3u, // deUint32 attachmentCount;
601 imageViews, // const VkImageView* pAttachments;
602 (deUint32)m_renderSize.x(), // deUint32 width;
603 (deUint32)m_renderSize.y(), // deUint32 height;
604 1u // deUint32 layers;
605 };
606
607 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
608 }
609
610 // Create pipeline layout for subpass 0
611 {
612 const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams =
613 {
614 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType
615 DE_NULL, // const void* pNext
616 0u, // VkDescriptorSetLayoutCreateFlags flags
617 0u, // deUint32 bindingCount
618 DE_NULL // const VkDescriptorSetLayoutBinding* pBindings
619 };
620 m_descriptorSetLayoutSubpass0 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
621
622 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
623 {
624 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
625 DE_NULL, // const void* pNext;
626 0u, // VkPipelineLayoutCreateFlags flags;
627 1u, // deUint32 setLayoutCount;
628 &m_descriptorSetLayoutSubpass0.get(), // const VkDescriptorSetLayout* pSetLayouts;
629 0u, // deUint32 pushConstantRangeCount;
630 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
631 };
632
633 m_pipelineLayoutSubpass0 = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
634 }
635
636 // Create pipeline layout for subpass 1
637 {
638 const VkDescriptorSetLayoutBinding layoutBinding =
639 {
640 0u, // deUint32 binding;
641 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType descriptorType;
642 1u, // deUint32 descriptorCount;
643 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
644 DE_NULL // const VkSampler* pImmutableSamplers;
645 };
646
647 const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams =
648 {
649 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType
650 DE_NULL, // const void* pNext
651 0u, // VkDescriptorSetLayoutCreateFlags flags
652 1u, // deUint32 bindingCount
653 &layoutBinding // const VkDescriptorSetLayoutBinding* pBindings
654 };
655 m_descriptorSetLayoutSubpass1 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
656
657 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
658 {
659 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
660 DE_NULL, // const void* pNext;
661 0u, // VkPipelineLayoutCreateFlags flags;
662 1u, // deUint32 setLayoutCount;
663 &m_descriptorSetLayoutSubpass1.get(), // const VkDescriptorSetLayout* pSetLayouts;
664 0u, // deUint32 pushConstantRangeCount;
665 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
666 };
667
668 m_pipelineLayoutSubpass1 = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
669 }
670
671 // Update descriptor set
672 {
673 const VkDescriptorPoolSize descriptorPoolSize =
674 {
675 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType type;
676 1u // deUint32 descriptorCount;
677 };
678
679 const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo =
680 {
681 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType
682 DE_NULL, // const void* pNext
683 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // VkDescriptorPoolCreateFlags flags
684 1u, // deUint32 maxSets
685 1u, // deUint32 poolSizeCount
686 &descriptorPoolSize // const VkDescriptorPoolSize* pPoolSizes
687 };
688
689 m_descriptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo);
690
691 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
692 {
693 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType
694 DE_NULL, // const void* pNext
695 *m_descriptorPool, // VkDescriptorPool descriptorPool
696 1u, // deUint32 descriptorSetCount
697 &m_descriptorSetLayoutSubpass1.get(), // const VkDescriptorSetLayout* pSetLayouts
698 };
699
700 m_descriptorSetSubpass1 = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
701
702 const VkDescriptorImageInfo inputImageInfo =
703 {
704 DE_NULL, // VkSampleri sampler;
705 *m_inputAttachmentView, // VkImageView imageView;
706 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout;
707 };
708
709 const VkWriteDescriptorSet descriptorWrite =
710 {
711 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
712 DE_NULL, // const void* pNext;
713 *m_descriptorSetSubpass1, // VkDescriptorSet dstSet;
714 0u, // deUint32 dstBinding;
715 0u, // deUint32 dstArrayElement;
716 1u, // deUint32 descriptorCount;
717 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType descriptorType;
718 &inputImageInfo, // const VkDescriptorImageInfo* pImageInfo;
719 DE_NULL, // const VkDescriptorBufferInfo* pBufferInfo;
720 DE_NULL // const VkBufferView* pTexelBufferView;
721 };
722
723 vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL);
724 }
725
726 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
727 m_fragmentShaderModuleSubpass0 = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb0"), 0);
728 m_fragmentShaderModuleSubpass1 = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb1"), 0);
729
730 // Create pipelines
731 {
732 const VkVertexInputBindingDescription vertexInputBindingDescription =
733 {
734 0u, // deUint32 binding;
735 sizeof(Vertex4RGBA), // deUint32 strideInBytes;
736 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
737 };
738
739 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
740 {
741 {
742 0u, // deUint32 location;
743 0u, // deUint32 binding;
744 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
745 0u // deUint32 offset;
746 },
747 {
748 1u, // deUint32 location;
749 0u, // deUint32 binding;
750 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
751 (deUint32)(sizeof(float) * 4), // deUint32 offset;
752 }
753 };
754
755 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
756 {
757 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
758 DE_NULL, // const void* pNext;
759 0u, // VkPipelineVertexInputStateCreateFlags flags;
760 1u, // deUint32 vertexBindingDescriptionCount;
761 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
762 2u, // deUint32 vertexAttributeDescriptionCount;
763 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
764 };
765
766 const std::vector<VkViewport> viewports (1, makeViewport(m_renderSize));
767 const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize));
768
769 {
770 m_graphicsPipelineSubpass0 = makeGraphicsPipeline(vk, // const DeviceInterface& vk
771 vkDevice, // const VkDevice device
772 *m_pipelineLayoutSubpass0, // const VkPipelineLayout pipelineLayout
773 *m_vertexShaderModule, // const VkShaderModule vertexShaderModule
774 DE_NULL, // const VkShaderModule tessellationControlModule
775 DE_NULL, // const VkShaderModule tessellationEvalModule
776 DE_NULL, // const VkShaderModule geometryShaderModule
777 *m_fragmentShaderModuleSubpass0, // const VkShaderModule fragmentShaderModule
778 *m_renderPass, // const VkRenderPass renderPass
779 viewports, // const std::vector<VkViewport>& viewports
780 scissors, // const std::vector<VkRect2D>& scissors
781 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
782 0u, // const deUint32 subpass
783 0u, // const deUint32 patchControlPoints
784 &vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
785
786 m_graphicsPipelineSubpass1 = makeGraphicsPipeline(vk, // const DeviceInterface& vk
787 vkDevice, // const VkDevice device
788 *m_pipelineLayoutSubpass1, // const VkPipelineLayout pipelineLayout
789 *m_vertexShaderModule, // const VkShaderModule vertexShaderModule
790 DE_NULL, // const VkShaderModule tessellationControlModule
791 DE_NULL, // const VkShaderModule tessellationEvalModule
792 DE_NULL, // const VkShaderModule geometryShaderModule
793 *m_fragmentShaderModuleSubpass1, // const VkShaderModule fragmentShaderModule
794 *m_renderPass, // const VkRenderPass renderPass
795 viewports, // const std::vector<VkViewport>& viewports
796 scissors, // const std::vector<VkRect2D>& scissors
797 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
798 1u, // const deUint32 subpass
799 0u, // const deUint32 patchControlPoints
800 &vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
801 }
802 }
803
804 // Create vertex buffer
805 {
806 const VkBufferCreateInfo vertexBufferParams =
807 {
808 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
809 DE_NULL, // const void* pNext;
810 0u, // VkBufferCreateFlags flags;
811 (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size;
812 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
813 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
814 1u, // deUint32 queueFamilyIndexCount;
815 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
816 };
817
818 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
819 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
820
821 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
822
823 // Upload vertex data
824 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
825 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
826 }
827
828 // Create command pool
829 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
830
831 // Create command buffer
832 if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
833 createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
834 else
835 createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
836 }
837
~UnusedAttachmentTestInstance(void)838 UnusedAttachmentTestInstance::~UnusedAttachmentTestInstance (void)
839 {
840 }
841
842 template<typename RenderpassSubpass>
createCommandBuffer(const DeviceInterface & vk,VkDevice vkDevice)843 void UnusedAttachmentTestInstance::createCommandBuffer (const DeviceInterface& vk,
844 VkDevice vkDevice)
845 {
846 const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo (DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
847 const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo (DE_NULL);
848
849 const VkClearValue attachmentClearValues[] =
850 {
851 makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f), // color
852 makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f), // unused
853 makeClearValueColorF32(0.5f, 0.2f, 0.1f, 1.0f) // input
854 };
855
856 const VkDeviceSize vertexBufferOffset = 0;
857
858 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
859
860 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
861
862 const VkRenderPassBeginInfo renderPassBeginInfo =
863 {
864 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
865 DE_NULL, // const void* pNext;
866 *m_renderPass, // VkRenderPass renderPass;
867 *m_framebuffer, // VkFramebuffer framebuffer;
868 makeRect2D(m_renderSize), // VkRect2D renderArea;
869 3u, // uint32_t clearValueCount;
870 attachmentClearValues // const VkClearValue* pClearValues;
871 };
872 RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
873
874 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineSubpass0);
875 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
876 vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
877 vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
878 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineSubpass1);
879 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutSubpass1, 0, 1, &m_descriptorSetSubpass1.get(), 0, DE_NULL);
880 vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
881
882 RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
883 endCommandBuffer(vk, *m_cmdBuffer);
884 }
885
iterate(void)886 tcu::TestStatus UnusedAttachmentTestInstance::iterate (void)
887 {
888 const DeviceInterface& vk = m_context.getDeviceInterface();
889 const VkDevice vkDevice = m_context.getDevice();
890 const VkQueue queue = m_context.getUniversalQueue();
891
892 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
893
894 return verifyImage();
895 }
896
verifyImage(void)897 tcu::TestStatus UnusedAttachmentTestInstance::verifyImage (void)
898 {
899 const DeviceInterface& vk = m_context.getDeviceInterface();
900 const VkDevice vkDevice = m_context.getDevice();
901 const VkQueue queue = m_context.getUniversalQueue();
902 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
903 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
904 de::UniquePtr<tcu::TextureLevel> textureLevelResult (pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, VK_FORMAT_R8G8B8A8_UNORM, m_renderSize).release());
905 const tcu::ConstPixelBufferAccess& resultAccess = textureLevelResult->getAccess();
906 de::UniquePtr<tcu::TextureLevel> textureLevelUnused (pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_unusedImage, VK_FORMAT_R8G8B8A8_UNORM, m_renderSize).release());
907 const tcu::ConstPixelBufferAccess& unusedAccess = textureLevelUnused->getAccess();
908 tcu::TestLog& log = m_context.getTestContext().getLog();
909
910 // Log images
911 log << tcu::TestLog::ImageSet("Result", "Result images")
912 << tcu::TestLog::Image("Rendered", "Rendered image", resultAccess)
913 << tcu::TestLog::Image("Unused", "Unused image", unusedAccess)
914 << tcu::TestLog::EndImageSet;
915
916 // Check the unused image data hasn't changed.
917 for (int y = 0; y < unusedAccess.getHeight(); y++)
918 for (int x = 0; x < unusedAccess.getWidth(); x++)
919 {
920 const tcu::Vec4 color = unusedAccess.getPixel(x, y);
921 const tcu::Vec4 refColor = tcu::Vec4(0.1f, 0.2f, 0.3f, 0.4f);
922 for (deUint32 cpnt = 0; cpnt < 4; cpnt++)
923 if (de::abs(color[cpnt] - refColor[cpnt]) > 0.01f)
924 return tcu::TestStatus::fail("Unused image contents has changed.");
925 }
926
927 // Check for rendered result. Just a quick sanity check to see if correct color is found at the center of the quad.
928 const tcu::Vec4 resultColor = resultAccess.getPixel(resultAccess.getWidth() / 2, resultAccess.getHeight() / 2);
929 const tcu::Vec4 refColor = tcu::Vec4(0.4f, 0.6f, 0.2f, 1.0f);
930 for (deUint32 cpnt = 0; cpnt < 4; cpnt++)
931 if (de::abs(resultColor[cpnt] - refColor[cpnt]) > 0.01f)
932 return tcu::TestStatus::fail("Result image mismatch");
933
934 return tcu::TestStatus::pass("Pass");
935 }
936
loadOpToString(VkAttachmentLoadOp loadOp)937 std::string loadOpToString (VkAttachmentLoadOp loadOp)
938 {
939 switch (loadOp)
940 {
941 case VK_ATTACHMENT_LOAD_OP_LOAD:
942 return "load";
943 case VK_ATTACHMENT_LOAD_OP_CLEAR:
944 return "clear";
945 case VK_ATTACHMENT_LOAD_OP_DONT_CARE:
946 return "dontcare";
947 default:
948 DE_FATAL("unexpected attachment load op");
949 return "";
950 };
951 }
952
storeOpToString(VkAttachmentStoreOp storeOp)953 std::string storeOpToString (VkAttachmentStoreOp storeOp)
954 {
955 switch (storeOp)
956 {
957 case VK_ATTACHMENT_STORE_OP_STORE:
958 return "store";
959 case VK_ATTACHMENT_STORE_OP_DONT_CARE:
960 return "dontcare";
961 default:
962 DE_FATAL("unexpected attachment store op");
963 return "";
964 };
965 }
966
967 } // anonymous
968
createRenderPassUnusedAttachmentTests(tcu::TestContext & testCtx,const RenderPassType renderPassType)969 tcu::TestCaseGroup* createRenderPassUnusedAttachmentTests (tcu::TestContext& testCtx, const RenderPassType renderPassType)
970 {
971 de::MovePtr<tcu::TestCaseGroup> unusedAttTests (new tcu::TestCaseGroup(testCtx, "unused_attachment", "Unused attachment tests"));
972
973 const VkAttachmentLoadOp loadOps[] =
974 {
975 VK_ATTACHMENT_LOAD_OP_LOAD,
976 VK_ATTACHMENT_LOAD_OP_CLEAR,
977 VK_ATTACHMENT_LOAD_OP_DONT_CARE
978 };
979
980 const VkAttachmentStoreOp storeOps[] =
981 {
982 VK_ATTACHMENT_STORE_OP_STORE,
983 VK_ATTACHMENT_STORE_OP_DONT_CARE
984 };
985
986 for (deUint32 loadOpIdx = 0; loadOpIdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpIdx++)
987 {
988 de::MovePtr<tcu::TestCaseGroup> loadOpGroup(new tcu::TestCaseGroup(testCtx, (std::string("loadop") + loadOpToString(loadOps[loadOpIdx])).c_str(), ""));
989
990 for (deUint32 storeOpIdx = 0; storeOpIdx < DE_LENGTH_OF_ARRAY(storeOps); storeOpIdx++)
991 {
992 de::MovePtr<tcu::TestCaseGroup> storeOpGroup(new tcu::TestCaseGroup(testCtx, (std::string("storeop") + storeOpToString(storeOps[storeOpIdx])).c_str(), ""));
993
994 for (deUint32 stencilLoadOpIdx = 0; stencilLoadOpIdx < DE_LENGTH_OF_ARRAY(loadOps); stencilLoadOpIdx++)
995 {
996 de::MovePtr<tcu::TestCaseGroup> stencilLoadOpGroup(new tcu::TestCaseGroup(testCtx, (std::string("stencilloadop") + loadOpToString(loadOps[stencilLoadOpIdx])).c_str(), ""));
997
998 for (deUint32 stencilStoreOpIdx = 0; stencilStoreOpIdx < DE_LENGTH_OF_ARRAY(storeOps); stencilStoreOpIdx++)
999 {
1000 TestParams params;
1001 const std::string testName = std::string("stencilstoreop") + storeOpToString(storeOps[stencilStoreOpIdx]);
1002
1003 params.loadOp = loadOps[loadOpIdx];
1004 params.storeOp = storeOps[storeOpIdx];
1005 params.stencilLoadOp = loadOps[stencilLoadOpIdx];
1006 params.stencilStoreOp = storeOps[stencilStoreOpIdx];
1007 params.renderPassType = renderPassType;
1008
1009 stencilLoadOpGroup->addChild(new UnusedAttachmentTest(testCtx, testName, "", params));
1010 }
1011 storeOpGroup->addChild(stencilLoadOpGroup.release());
1012 }
1013 loadOpGroup->addChild(storeOpGroup.release());
1014 }
1015 unusedAttTests->addChild(loadOpGroup.release());
1016 }
1017
1018 return unusedAttTests.release();
1019 }
1020
1021 } // renderpass
1022 } // vkt
1023