1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 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 sparse input attachments in VkSubpassDescription::pInputAttachments
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktRenderPassUnusedAttachmentSparseFillingTests.hpp"
27 #include "vktRenderPassTestsUtil.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "tcuTestLog.hpp"
35 #include "deRandom.hpp"
36 #include <sstream>
37 #include <vector>
38 #include <algorithm>
39 #include <numeric>
40 #include <random>
41
42 typedef de::SharedPtr<vk::Unique<vk::VkImage> > VkImageSp;
43 typedef de::SharedPtr<vk::Unique<vk::VkImageView> > VkImageViewSp;
44 typedef de::SharedPtr<vk::Unique<vk::VkBuffer> > VkBufferSp;
45 typedef de::SharedPtr<vk::Allocation> AllocationSp;
46
47 namespace vkt
48 {
49
50 namespace renderpass
51 {
52
53 using namespace vk;
54
55 template<typename T>
safeSharedPtr(T * ptr)56 de::SharedPtr<T> safeSharedPtr(T* ptr)
57 {
58 try
59 {
60 return de::SharedPtr<T>(ptr);
61 }
62 catch (...)
63 {
64 delete ptr;
65 throw;
66 }
67 }
68
69 static const deUint32 RENDER_SIZE = 8u;
70 static const unsigned int DEFAULT_SEED = 31u;
71
72 namespace
73 {
74
75 struct TestParams
76 {
77 RenderingType renderingType;
78 deUint32 activeInputAttachmentCount;
79 };
80
81 struct Vertex
82 {
83 tcu::Vec4 position;
84 tcu::Vec4 uv;
85 };
86
createFullscreenTriangle(void)87 std::vector<Vertex> createFullscreenTriangle (void)
88 {
89 std::vector<Vertex> vertices;
90
91 for (deUint32 i = 0; i < 3; ++i)
92 {
93 float x = static_cast<float>((i << 1) & 2);
94 float y = static_cast<float>(i & 2);
95 vertices.push_back(Vertex{ tcu::Vec4(x * 2.0f - 1.0f, y * 2.0f - 1.0f, 0.0f, 1.0f), tcu::Vec4(x,y,0.0f,0.0f) });
96 }
97 return vertices;
98 }
99
generateInputAttachmentParams(deUint32 activeAttachmentCount,deUint32 allAttachmentCount,std::vector<deUint32> & attachmentIndices,std::vector<deUint32> & descriptorBindings)100 void generateInputAttachmentParams(deUint32 activeAttachmentCount, deUint32 allAttachmentCount, std::vector<deUint32>& attachmentIndices, std::vector<deUint32>& descriptorBindings)
101 {
102 attachmentIndices.resize(allAttachmentCount);
103 std::iota(begin(attachmentIndices), begin(attachmentIndices) + activeAttachmentCount, 0);
104 std::fill(begin(attachmentIndices) + activeAttachmentCount, end(attachmentIndices), VK_ATTACHMENT_UNUSED);
105 de::Random random(DEFAULT_SEED);
106 random.shuffle(begin(attachmentIndices), end(attachmentIndices));
107
108 descriptorBindings.resize(activeAttachmentCount+1);
109 descriptorBindings[0] = VK_ATTACHMENT_UNUSED;
110 for (deUint32 i = 0, lastBinding = 1; i < allAttachmentCount; ++i)
111 {
112 if (attachmentIndices[i] != VK_ATTACHMENT_UNUSED)
113 descriptorBindings[lastBinding++] = i;
114 }
115 }
116
117 class InputAttachmentSparseFillingTest : public vkt::TestCase
118 {
119 public:
120 InputAttachmentSparseFillingTest (tcu::TestContext& testContext,
121 const std::string& name,
122 const TestParams& testParams);
123 virtual ~InputAttachmentSparseFillingTest (void);
124 virtual void initPrograms (SourceCollections& sourceCollections) const;
125 virtual TestInstance* createInstance (Context& context) const;
126 virtual void checkSupport (Context& context) const;
127
128 private:
129 TestParams m_testParams;
130 };
131
132 class InputAttachmentSparseFillingTestInstance : public vkt::TestInstance
133 {
134 public:
135 InputAttachmentSparseFillingTestInstance (Context& context,
136 const TestParams& testParams);
137 virtual ~InputAttachmentSparseFillingTestInstance (void);
138 virtual tcu::TestStatus iterate (void);
139 template<typename RenderpassSubpass>
140 void createCommandBuffer (const DeviceInterface& vk,
141 VkDevice vkDevice);
142
143 template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
144 Move<VkRenderPass> createRenderPass (const DeviceInterface& vk,
145 VkDevice vkDevice);
146 private:
147 tcu::TestStatus verifyImage (void);
148
149 const tcu::UVec2 m_renderSize;
150 std::vector<Vertex> m_vertices;
151 TestParams m_testParams;
152
153 std::vector<VkImageSp> m_inputImages;
154 std::vector<AllocationSp> m_inputImageMemory;
155 std::vector<VkImageViewSp> m_inputImageViews;
156
157 VkImageSp m_outputImage;
158 AllocationSp m_outputImageMemory;
159 VkImageViewSp m_outputImageView;
160
161 VkBufferSp m_outputBuffer;
162 AllocationSp m_outputBufferMemory;
163
164 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
165 Move<VkDescriptorPool> m_descriptorPool;
166 Move<VkDescriptorSet> m_descriptorSet;
167 Move<VkRenderPass> m_renderPass;
168 Move<VkFramebuffer> m_framebuffer;
169
170 Move<VkShaderModule> m_vertexShaderModule;
171 Move<VkShaderModule> m_fragmentShaderModule;
172
173 Move<VkBuffer> m_vertexBuffer;
174 de::MovePtr<Allocation> m_vertexBufferAlloc;
175
176 Move<VkPipelineLayout> m_pipelineLayout;
177 Move<VkPipeline> m_graphicsPipeline;
178
179 Move<VkCommandPool> m_cmdPool;
180 Move<VkCommandBuffer> m_cmdBuffer;
181 };
182
InputAttachmentSparseFillingTest(tcu::TestContext & testContext,const std::string & name,const TestParams & testParams)183 InputAttachmentSparseFillingTest::InputAttachmentSparseFillingTest (tcu::TestContext& testContext,
184 const std::string& name,
185 const TestParams& testParams)
186 : vkt::TestCase (testContext, name), m_testParams(testParams)
187 {
188 }
189
~InputAttachmentSparseFillingTest(void)190 InputAttachmentSparseFillingTest::~InputAttachmentSparseFillingTest (void)
191 {
192 }
193
initPrograms(SourceCollections & sourceCollections) const194 void InputAttachmentSparseFillingTest::initPrograms (SourceCollections& sourceCollections) const
195 {
196 std::ostringstream fragmentSource;
197
198 sourceCollections.glslSources.add("vertex") << glu::VertexSource(
199 "#version 450\n"
200 "layout(location = 0) in vec4 position;\n"
201 "layout(location = 1) in vec4 uv;\n"
202 "layout(location = 0) out vec4 outUV;\n"
203 "void main (void)\n"
204 "{\n"
205 " gl_Position = position;\n"
206 " outUV = uv;\n"
207 "}\n");
208
209 // We read from X input attachments randomly spread in input attachment array of size 2*X
210 std::ostringstream str;
211 str << "#version 450\n"
212 << "layout(location = 0) in vec4 inUV;\n"
213 << "layout(binding = 0, rg32ui) uniform uimage2D resultImage;\n";
214
215 std::vector<deUint32> attachmentIndices, descriptorBindings;
216 generateInputAttachmentParams(m_testParams.activeInputAttachmentCount, 2u * m_testParams.activeInputAttachmentCount, attachmentIndices, descriptorBindings);
217
218 for (std::size_t i = 1; i < descriptorBindings.size(); ++i)
219 str << "layout(binding = " << i << ", input_attachment_index = " << descriptorBindings[i] <<") uniform subpassInput attach" << i <<";\n";
220
221 str << "void main (void)\n"
222 << "{\n"
223 << " uvec4 result = uvec4(0);\n";
224
225 for (std::size_t i = 1; i < descriptorBindings.size(); ++i)
226 {
227 str << " result.x = result.x + 1;\n";
228 str << " if(subpassLoad(attach" << i << ").x > 0.0)\n";
229 str << " result.y = result.y + 1;\n";
230 }
231
232 str << " imageStore(resultImage, ivec2(imageSize(resultImage) * inUV.xy), result);\n"
233 << "}\n";
234
235 sourceCollections.glslSources.add("fragment") << glu::FragmentSource(str.str());
236 }
237
createInstance(Context & context) const238 TestInstance* InputAttachmentSparseFillingTest::createInstance(Context& context) const
239 {
240 return new InputAttachmentSparseFillingTestInstance(context, m_testParams);
241 }
242
checkSupport(Context & context) const243 void InputAttachmentSparseFillingTest::checkSupport(Context& context) const
244 {
245 if (m_testParams.renderingType == RENDERING_TYPE_RENDERPASS2)
246 context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
247
248 const vk::VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits;
249
250 if( 2u * m_testParams.activeInputAttachmentCount > limits.maxPerStageDescriptorInputAttachments )
251 TCU_THROW(NotSupportedError, "Input attachment count including unused elements exceeds maxPerStageDescriptorInputAttachments");
252
253 if ( 2u * m_testParams.activeInputAttachmentCount > limits.maxPerStageResources)
254 TCU_THROW(NotSupportedError, "Input attachment count including unused elements exceeds maxPerStageResources");
255 }
256
InputAttachmentSparseFillingTestInstance(Context & context,const TestParams & testParams)257 InputAttachmentSparseFillingTestInstance::InputAttachmentSparseFillingTestInstance (Context& context, const TestParams& testParams)
258 : vkt::TestInstance (context)
259 , m_renderSize (RENDER_SIZE, RENDER_SIZE)
260 , m_vertices (createFullscreenTriangle())
261 , m_testParams (testParams)
262 {
263 const DeviceInterface& vk = m_context.getDeviceInterface();
264 const VkDevice vkDevice = m_context.getDevice();
265 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
266 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
267 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
268
269 {
270 const VkImageCreateInfo inputImageParams =
271 {
272 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
273 DE_NULL, // const void* pNext;
274 0u, // VkImageCreateFlags flags;
275 VK_IMAGE_TYPE_2D, // VkImageType imageType;
276 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
277 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
278 1u, // deUint32 mipLevels;
279 1u, // deUint32 arrayLayers;
280 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
281 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
282 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
283 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
284 1u, // deUint32 queueFamilyIndexCount;
285 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
286 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
287 };
288
289 VkImageViewCreateInfo inputAttachmentViewParams =
290 {
291 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
292 DE_NULL, // const void* pNext;
293 0u, // VkImageViewCreateFlags flags;
294 0, // VkImage image;
295 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
296 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
297 componentMappingRGBA, // VkChannelMapping channels;
298 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
299 };
300
301 // Create input attachment images with image views
302 for (deUint32 imageNdx = 0; imageNdx < m_testParams.activeInputAttachmentCount; ++imageNdx)
303 {
304 auto inputImage = safeSharedPtr(new Unique<VkImage>(vk::createImage(vk, vkDevice, &inputImageParams)));
305
306 auto inputImageAlloc = safeSharedPtr(memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, **inputImage), MemoryRequirement::Any).release());
307 VK_CHECK(vk.bindImageMemory(vkDevice, **inputImage, inputImageAlloc->getMemory(), inputImageAlloc->getOffset()));
308
309 inputAttachmentViewParams.image = **inputImage;
310 auto inputImageView = safeSharedPtr(new Unique<VkImageView>(createImageView(vk, vkDevice, &inputAttachmentViewParams)));
311
312 m_inputImages.push_back(inputImage);
313 m_inputImageMemory.push_back(inputImageAlloc);
314 m_inputImageViews.push_back(inputImageView);
315 }
316 }
317
318 {
319 const VkImageCreateInfo outputImageParams =
320 {
321 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
322 DE_NULL, // const void* pNext;
323 0u, // VkImageCreateFlags flags;
324 VK_IMAGE_TYPE_2D, // VkImageType imageType;
325 VK_FORMAT_R32G32_UINT, // VkFormat format;
326 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
327 1u, // deUint32 mipLevels;
328 1u, // deUint32 arrayLayers;
329 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
330 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
331 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
332 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
333 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
334 1u, // deUint32 queueFamilyIndexCount;
335 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
336 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
337 };
338
339 m_outputImage = safeSharedPtr(new Unique<VkImage>(vk::createImage(vk, vkDevice, &outputImageParams)));
340 m_outputImageMemory = safeSharedPtr(memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, **m_outputImage), MemoryRequirement::Any).release());
341 VK_CHECK(vk.bindImageMemory(vkDevice, **m_outputImage, m_outputImageMemory->getMemory(), m_outputImageMemory->getOffset()));
342
343 VkImageViewCreateInfo inputAttachmentViewParams =
344 {
345 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
346 DE_NULL, // const void* pNext;
347 0u, // VkImageViewCreateFlags flags;
348 **m_outputImage, // VkImage image;
349 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
350 VK_FORMAT_R32G32_UINT, // VkFormat format;
351 componentMappingRGBA, // VkChannelMapping channels;
352 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
353 };
354 m_outputImageView = safeSharedPtr(new Unique<VkImageView>(createImageView(vk, vkDevice, &inputAttachmentViewParams)));
355 }
356
357 {
358 const VkDeviceSize outputBufferSizeBytes = m_renderSize.x() * m_renderSize.y() * tcu::getPixelSize(mapVkFormat(VK_FORMAT_R32G32_UINT));
359 const VkBufferCreateInfo outputBufferParams =
360 {
361 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
362 DE_NULL, // pNext
363 (VkBufferCreateFlags)0u, // flags
364 outputBufferSizeBytes, // size
365 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
366 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
367 1u, // queueFamilyIndexCount
368 &queueFamilyIndex, // pQueueFamilyIndices
369 };
370 m_outputBuffer = safeSharedPtr(new Unique<VkBuffer>(createBuffer(vk, vkDevice, &outputBufferParams)));
371 m_outputBufferMemory = safeSharedPtr(memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, **m_outputBuffer), MemoryRequirement::HostVisible).release());
372 VK_CHECK(vk.bindBufferMemory(vkDevice, **m_outputBuffer, m_outputBufferMemory->getMemory(), m_outputBufferMemory->getOffset()));
373 }
374
375 // Create render pass
376 if (testParams.renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
377 m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice);
378 else
379 m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice);
380
381 std::vector<VkDescriptorImageInfo> descriptorImageInfos;
382 std::vector<VkImageView> framebufferImageViews;
383 descriptorImageInfos.push_back(
384 VkDescriptorImageInfo{
385 DE_NULL, // VkSampleri sampler;
386 **m_outputImageView, // VkImageView imageView;
387 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout imageLayout;
388 }
389 );
390 for (auto& inputImageView : m_inputImageViews)
391 {
392 framebufferImageViews.push_back(**inputImageView);
393 descriptorImageInfos.push_back(
394 VkDescriptorImageInfo{
395 DE_NULL, // VkSampleri sampler;
396 **inputImageView, // VkImageView imageView;
397 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout;
398 }
399 );
400 }
401
402 // Create framebuffer
403 {
404 const VkFramebufferCreateInfo framebufferParams =
405 {
406 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
407 DE_NULL, // const void* pNext;
408 0u, // VkFramebufferCreateFlags flags;
409 *m_renderPass, // VkRenderPass renderPass;
410 static_cast<deUint32>(framebufferImageViews.size()), // deUint32 attachmentCount;
411 framebufferImageViews.data(), // const VkImageView* pAttachments;
412 static_cast<deUint32>(m_renderSize.x()), // deUint32 width;
413 static_cast<deUint32>(m_renderSize.y()), // deUint32 height;
414 1u // deUint32 layers;
415 };
416
417 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
418 }
419
420 // Create pipeline layout
421 {
422 DescriptorSetLayoutBuilder layoutBuilder;
423 // add output image storage
424 layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
425 // add input attachments
426 for (deUint32 imageNdx = 0; imageNdx < m_testParams.activeInputAttachmentCount; ++imageNdx)
427 layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT);
428 m_descriptorSetLayout = layoutBuilder.build(vk, vkDevice);
429
430 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
431 {
432 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
433 DE_NULL, // const void* pNext;
434 0u, // VkPipelineLayoutCreateFlags flags;
435 1u, // deUint32 setLayoutCount;
436 &m_descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
437 0u, // deUint32 pushConstantRangeCount;
438 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
439 };
440
441 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
442 }
443
444 // Update descriptor set
445 {
446 m_descriptorPool = DescriptorPoolBuilder()
447 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
448 .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, m_testParams.activeInputAttachmentCount)
449 .build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
450
451 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
452 {
453 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType
454 DE_NULL, // const void* pNext
455 *m_descriptorPool, // VkDescriptorPool descriptorPool
456 1u, // deUint32 descriptorSetCount
457 &m_descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts
458 };
459 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
460
461 DescriptorSetUpdateBuilder builder;
462 builder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfos[0]);
463 for( deUint32 i=1; i<static_cast<deUint32>(descriptorImageInfos.size()); ++i)
464 builder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(i), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descriptorImageInfos[i]);
465 builder.update(vk, vkDevice);
466 }
467
468 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vertex"), 0);
469 m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("fragment"), 0);
470
471 // Create pipelines
472 {
473 const VkVertexInputBindingDescription vertexInputBindingDescription =
474 {
475 0u, // deUint32 binding;
476 sizeof(Vertex), // deUint32 strideInBytes;
477 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
478 };
479
480 std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescription =
481 {
482 {
483 0u, // deUint32 location;
484 0u, // deUint32 binding;
485 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
486 0u // deUint32 offset;
487 },
488 {
489 1u, // deUint32 location;
490 0u, // deUint32 binding;
491 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
492 DE_OFFSET_OF(Vertex, uv) // deUint32 offset;
493 }
494 };
495
496 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
497 {
498 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
499 DE_NULL, // const void* pNext;
500 0u, // VkPipelineVertexInputStateCreateFlags flags;
501 1u, // deUint32 vertexBindingDescriptionCount;
502 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
503 static_cast<deUint32>(vertexInputAttributeDescription.size()), // deUint32 vertexAttributeDescriptionCount;
504 vertexInputAttributeDescription.data() // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
505 };
506
507 const std::vector<VkViewport> viewports (1, makeViewport(m_renderSize));
508 const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize));
509
510 {
511 m_graphicsPipeline = makeGraphicsPipeline(vk, // const DeviceInterface& vk
512 vkDevice, // const VkDevice device
513 *m_pipelineLayout, // const VkPipelineLayout pipelineLayout
514 *m_vertexShaderModule, // const VkShaderModule vertexShaderModule
515 DE_NULL, // const VkShaderModule tessellationControlModule
516 DE_NULL, // const VkShaderModule tessellationEvalModule
517 DE_NULL, // const VkShaderModule geometryShaderModule
518 *m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule
519 *m_renderPass, // const VkRenderPass renderPass
520 viewports, // const std::vector<VkViewport>& viewports
521 scissors, // const std::vector<VkRect2D>& scissors
522 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
523 0u, // const deUint32 subpass
524 0u, // const deUint32 patchControlPoints
525 &vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
526 }
527 }
528
529 // Create vertex buffer
530 {
531 const VkBufferCreateInfo vertexBufferParams =
532 {
533 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
534 DE_NULL, // const void* pNext;
535 0u, // VkBufferCreateFlags flags;
536 (VkDeviceSize)(sizeof(Vertex) * m_vertices.size()), // VkDeviceSize size;
537 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
538 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
539 1u, // deUint32 queueFamilyIndexCount;
540 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
541 };
542
543 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
544 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
545 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
546
547 // Upload vertex data
548 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex));
549 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
550 }
551
552 // Create command pool
553 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
554
555 // Create command buffer
556 if (testParams.renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
557 createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
558 else
559 createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
560 }
561
~InputAttachmentSparseFillingTestInstance(void)562 InputAttachmentSparseFillingTestInstance::~InputAttachmentSparseFillingTestInstance (void)
563 {
564 }
565
566 template<typename RenderpassSubpass>
createCommandBuffer(const DeviceInterface & vk,VkDevice vkDevice)567 void InputAttachmentSparseFillingTestInstance::createCommandBuffer (const DeviceInterface& vk,
568 VkDevice vkDevice)
569 {
570 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
571
572 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
573
574 // clear output image (rg16ui) to (0,0), set image layout to VK_IMAGE_LAYOUT_GENERAL
575 VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
576 {
577 const VkImageMemoryBarrier outputImageInitBarrier =
578 {
579 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
580 DE_NULL, // const void* pNext;
581 0u, // VkAccessFlags srcAccessMask;
582 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAcessMask;
583 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
584 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
585 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
586 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
587 **m_outputImage, // VkImage image;
588 range // VkImageSubresourceRange subresourceRange;
589 };
590 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &outputImageInitBarrier);
591 VkClearValue clearColor = makeClearValueColorU32(0, 0, 0, 0);
592 vk.cmdClearColorImage(*m_cmdBuffer, **m_outputImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
593 VkMemoryBarrier memBarrier =
594 {
595 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
596 DE_NULL, // pNext
597 VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
598 VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT // dstAccessMask
599 };
600 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
601 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
602 }
603 // clear all input attachments (rgba8) to (1,1,1,1), set image layout to VK_IMAGE_LAYOUT_GENERAL
604 for (auto& inputImage : m_inputImages)
605 {
606 const VkImageMemoryBarrier inputImageInitBarrier =
607 {
608 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
609 DE_NULL, // const void* pNext;
610 0u, // VkAccessFlags srcAccessMask;
611 VK_ACCESS_MEMORY_WRITE_BIT, // VkAccessFlags dstAcessMask;
612 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
613 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
614 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
615 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
616 **inputImage, // VkImage image;
617 range // VkImageSubresourceRange subresourceRange;
618 };
619 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &inputImageInitBarrier);
620 VkClearValue clearColor = makeClearValueColorF32(1.0f, 1.0f, 1.0f, 1.0f);
621
622 vk.cmdClearColorImage(*m_cmdBuffer, **inputImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
623
624 VkMemoryBarrier memBarrier =
625 {
626 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
627 DE_NULL, // pNext
628 VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
629 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT // dstAccessMask
630 };
631 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
632 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
633 }
634
635 // Render pass does not use clear values - input images were prepared beforehand
636 const VkRenderPassBeginInfo renderPassBeginInfo =
637 {
638 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
639 DE_NULL, // const void* pNext;
640 *m_renderPass, // VkRenderPass renderPass;
641 *m_framebuffer, // VkFramebuffer framebuffer;
642 makeRect2D(m_renderSize), // VkRect2D renderArea;
643 0, // uint32_t clearValueCount;
644 DE_NULL // const VkClearValue* pClearValues;
645 };
646 const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
647 RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
648
649 const VkDeviceSize vertexBufferOffset = 0;
650 vk.cmdBindPipeline (*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
651 vk.cmdBindDescriptorSets (*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
652 vk.cmdBindVertexBuffers (*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
653 vk.cmdDraw (*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
654
655 const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
656 RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
657
658 copyImageToBuffer(vk, *m_cmdBuffer, **m_outputImage, **m_outputBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
659
660 endCommandBuffer(vk, *m_cmdBuffer);
661 }
662
663 template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vk,VkDevice vkDevice)664 Move<VkRenderPass> InputAttachmentSparseFillingTestInstance::createRenderPass (const DeviceInterface& vk,
665 VkDevice vkDevice)
666 {
667 const VkImageAspectFlags aspectMask = m_testParams.renderingType == RENDERING_TYPE_RENDERPASS_LEGACY ? 0 : VK_IMAGE_ASPECT_COLOR_BIT;
668 std::vector<AttachmentDesc> attachmentDescriptions;
669 std::vector<AttachmentRef> attachmentRefs;
670
671 std::vector<deUint32> attachmentIndices;
672 std::vector<deUint32> descriptorBindings;
673 generateInputAttachmentParams(m_testParams.activeInputAttachmentCount, 2u * m_testParams.activeInputAttachmentCount, attachmentIndices, descriptorBindings);
674
675 for (deUint32 i = 0; i < m_testParams.activeInputAttachmentCount; ++i)
676 {
677 attachmentDescriptions.push_back(
678 AttachmentDesc(
679 DE_NULL, // const void* pNext
680 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
681 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format
682 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
683 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp
684 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
685 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
686 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
687 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout
688 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout
689 )
690 );
691 }
692 for (std::size_t i = 0; i < attachmentIndices.size(); ++i)
693 attachmentRefs.push_back(
694 AttachmentRef(
695 DE_NULL, // const void* pNext
696 attachmentIndices[i], // deUint32 attachment
697 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout layout
698 aspectMask // VkImageAspectFlags aspectMask
699 )
700 );
701
702 std::vector<SubpassDesc> subpassDescriptions =
703 {
704 SubpassDesc (
705 DE_NULL,
706 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
707 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
708 0u, // deUint32 viewMask
709 static_cast<deUint32>(attachmentRefs.size()), // deUint32 inputAttachmentCount
710 attachmentRefs.data(), // const VkAttachmentReference* pInputAttachments
711 0u, // deUint32 colorAttachmentCount
712 DE_NULL, // const VkAttachmentReference* pColorAttachments
713 DE_NULL, // const VkAttachmentReference* pResolveAttachments
714 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
715 0u, // deUint32 preserveAttachmentCount
716 DE_NULL // const deUint32* pPreserveAttachments
717 ),
718 };
719 std::vector<SubpassDep> subpassDependencies =
720 {
721 SubpassDep (
722 DE_NULL,
723 0u, // deUint32 srcPass
724 VK_SUBPASS_EXTERNAL, // deUint32 dstPass
725 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags srcStageMask
726 VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, // VkPipelineStageFlags dstStageMask
727 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask
728 VK_ACCESS_INDIRECT_COMMAND_READ_BIT, // VkAccessFlags dstAccessMask
729 0, // VkDependencyFlags flags
730 0 // deInt32 viewOffset
731 ),
732 };
733
734 const RenderPassCreateInfo renderPassInfo (
735 DE_NULL, // const void* pNext
736 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
737 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount
738 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments
739 static_cast<deUint32>(subpassDescriptions.size()), // deUint32 subpassCount
740 subpassDescriptions.data(), // const VkSubpassDescription* pSubpasses
741 static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount
742 subpassDependencies.data(), // const VkSubpassDependency* pDependencies
743 0u, // deUint32 correlatedViewMaskCount
744 DE_NULL // const deUint32* pCorrelatedViewMasks
745 );
746
747 return renderPassInfo.createRenderPass(vk, vkDevice);
748 }
749
iterate(void)750 tcu::TestStatus InputAttachmentSparseFillingTestInstance::iterate (void)
751 {
752 const DeviceInterface& vk = m_context.getDeviceInterface();
753 const VkDevice vkDevice = m_context.getDevice();
754 const VkQueue queue = m_context.getUniversalQueue();
755
756 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
757
758 return verifyImage();
759 }
760
verifyImage(void)761 tcu::TestStatus InputAttachmentSparseFillingTestInstance::verifyImage (void)
762 {
763 const DeviceInterface& vk = m_context.getDeviceInterface();
764 const VkDevice vkDevice = m_context.getDevice();
765
766 invalidateAlloc(vk, vkDevice, *m_outputBufferMemory);
767 const tcu::ConstPixelBufferAccess resultAccess(mapVkFormat(VK_FORMAT_R32G32_UINT), m_renderSize.x(), m_renderSize.y(), 1u, m_outputBufferMemory->getHostPtr());
768
769 // Log result image
770 m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Result", "Result images")
771 << tcu::TestLog::Image("Rendered", "Rendered image", resultAccess)
772 << tcu::TestLog::EndImageSet;
773
774 // Check the unused image data hasn't changed.
775 for (int y = 0; y < resultAccess.getHeight(); y++)
776 for (int x = 0; x < resultAccess.getWidth(); x++)
777 {
778 tcu::UVec4 color = resultAccess.getPixelUint(x, y);
779 if( color.x() != m_testParams.activeInputAttachmentCount)
780 return tcu::TestStatus::fail("Wrong attachment count");
781 if( color.y() != m_testParams.activeInputAttachmentCount )
782 return tcu::TestStatus::fail("Wrong active attachment count");
783 }
784
785 return tcu::TestStatus::pass("Pass");
786 }
787
788 } // anonymous
789
createRenderPassUnusedAttachmentSparseFillingTests(tcu::TestContext & testCtx,const RenderingType renderingType)790 tcu::TestCaseGroup* createRenderPassUnusedAttachmentSparseFillingTests (tcu::TestContext& testCtx, const RenderingType renderingType)
791 {
792 // Unused attachment tests
793 de::MovePtr<tcu::TestCaseGroup> unusedAttTests (new tcu::TestCaseGroup(testCtx, "attachment_sparse_filling"));
794
795 const std::vector<deUint32> activeInputAttachmentCount
796 {
797 1u,
798 3u,
799 7u,
800 15u,
801 31u,
802 63u,
803 127u
804 };
805
806 for (std::size_t attachmentNdx = 0; attachmentNdx < activeInputAttachmentCount.size(); ++attachmentNdx)
807 {
808 TestParams testParams{ renderingType, activeInputAttachmentCount[attachmentNdx] };
809 unusedAttTests->addChild(new InputAttachmentSparseFillingTest(testCtx, std::string("input_attachment_") + de::toString(activeInputAttachmentCount[attachmentNdx]), testParams));
810 }
811
812 return unusedAttTests.release();
813 }
814
815 } // renderpass
816
817 } // vkt
818