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