1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2014 The Android Open Source Project
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Geometry shader layered rendering tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktGeometryLayeredRenderingTests.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktGeometryTestsUtil.hpp"
29
30 #include "vkPrograms.hpp"
31 #include "vkStrUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkImageUtil.hpp"
37
38 #include "deStringUtil.hpp"
39 #include "deUniquePtr.hpp"
40
41 #include "tcuTextureUtil.hpp"
42 #include "tcuVectorUtil.hpp"
43
44 namespace vkt
45 {
46 namespace geometry
47 {
48 namespace
49 {
50 using namespace vk;
51 using de::MovePtr;
52 using de::UniquePtr;
53 using tcu::Vec4;
54 using tcu::IVec3;
55
56 enum TestType
57 {
58 TEST_TYPE_DEFAULT_LAYER, // !< draw to default layer
59 TEST_TYPE_SINGLE_LAYER, // !< draw to single layer
60 TEST_TYPE_ALL_LAYERS, // !< draw all layers
61 TEST_TYPE_DIFFERENT_CONTENT, // !< draw different content to different layers
62 TEST_TYPE_LAYER_ID, // !< draw to all layers, verify gl_Layer fragment input
63 TEST_TYPE_INVOCATION_PER_LAYER, // !< draw to all layers, one invocation per layer
64 TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION, // !< draw to all layers, multiple invocations write to multiple layers
65 };
66
67 struct ImageParams
68 {
69 VkImageViewType viewType;
70 VkExtent3D size;
71 deUint32 numLayers;
72 };
73
74 struct TestParams
75 {
76 TestType testType;
77 ImageParams image;
78 };
79
80 static const float s_colors[][4] =
81 {
82 { 1.0f, 1.0f, 1.0f, 1.0f }, // white
83 { 1.0f, 0.0f, 0.0f, 1.0f }, // red
84 { 0.0f, 1.0f, 0.0f, 1.0f }, // green
85 { 0.0f, 0.0f, 1.0f, 1.0f }, // blue
86 { 1.0f, 1.0f, 0.0f, 1.0f }, // yellow
87 { 1.0f, 0.0f, 1.0f, 1.0f }, // magenta
88 };
89
getTargetLayer(const ImageParams & imageParams)90 deUint32 getTargetLayer (const ImageParams& imageParams)
91 {
92 if (imageParams.viewType == VK_IMAGE_VIEW_TYPE_3D)
93 return imageParams.size.depth / 2;
94 else
95 return imageParams.numLayers / 2;
96 }
97
getShortImageViewTypeName(const VkImageViewType imageViewType)98 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
99 {
100 std::string s(getImageViewTypeName(imageViewType));
101 return de::toLower(s.substr(19));
102 }
103
getImageType(const VkImageViewType viewType)104 VkImageType getImageType (const VkImageViewType viewType)
105 {
106 switch (viewType)
107 {
108 case VK_IMAGE_VIEW_TYPE_1D:
109 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
110 return VK_IMAGE_TYPE_1D;
111
112 case VK_IMAGE_VIEW_TYPE_2D:
113 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
114 case VK_IMAGE_VIEW_TYPE_CUBE:
115 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
116 return VK_IMAGE_TYPE_2D;
117
118 case VK_IMAGE_VIEW_TYPE_3D:
119 return VK_IMAGE_TYPE_3D;
120
121 default:
122 DE_ASSERT(0);
123 return VK_IMAGE_TYPE_LAST;
124 }
125 }
126
isCubeImageViewType(const VkImageViewType viewType)127 inline bool isCubeImageViewType (const VkImageViewType viewType)
128 {
129 return viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
130 }
131
makeImageCreateInfo(const VkImageCreateFlags flags,const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const VkImageUsageFlags usage)132 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const VkImageUsageFlags usage)
133 {
134 const VkImageCreateInfo imageParams =
135 {
136 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
137 DE_NULL, // const void* pNext;
138 flags, // VkImageCreateFlags flags;
139 type, // VkImageType imageType;
140 format, // VkFormat format;
141 size, // VkExtent3D extent;
142 1u, // deUint32 mipLevels;
143 numLayers, // deUint32 arrayLayers;
144 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
145 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
146 usage, // VkImageUsageFlags usage;
147 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
148 0u, // deUint32 queueFamilyIndexCount;
149 DE_NULL, // const deUint32* pQueueFamilyIndices;
150 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
151 };
152 return imageParams;
153 }
154
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)155 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
156 const VkDevice device,
157 const VkFormat colorFormat)
158 {
159 const VkAttachmentDescription colorAttachmentDescription =
160 {
161 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
162 colorFormat, // VkFormat format;
163 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
164 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
165 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
166 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
167 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
168 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
169 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
170 };
171
172 const VkAttachmentReference colorAttachmentRef =
173 {
174 0u, // deUint32 attachment;
175 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
176 };
177
178 const VkSubpassDescription subpassDescription =
179 {
180 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
181 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
182 0u, // deUint32 inputAttachmentCount;
183 DE_NULL, // const VkAttachmentReference* pInputAttachments;
184 1u, // deUint32 colorAttachmentCount;
185 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments;
186 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
187 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
188 0u, // deUint32 preserveAttachmentCount;
189 DE_NULL // const deUint32* pPreserveAttachments;
190 };
191
192 const VkRenderPassCreateInfo renderPassInfo =
193 {
194 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
195 DE_NULL, // const void* pNext;
196 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
197 1u, // deUint32 attachmentCount;
198 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments;
199 1u, // deUint32 subpassCount;
200 &subpassDescription, // const VkSubpassDescription* pSubpasses;
201 0u, // deUint32 dependencyCount;
202 DE_NULL // const VkSubpassDependency* pDependencies;
203 };
204
205 return createRenderPass(vk, device, &renderPassInfo);
206 }
207
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule geometryModule,const VkShaderModule fragmentModule,const VkExtent2D renderSize)208 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
209 const VkDevice device,
210 const VkPipelineLayout pipelineLayout,
211 const VkRenderPass renderPass,
212 const VkShaderModule vertexModule,
213 const VkShaderModule geometryModule,
214 const VkShaderModule fragmentModule,
215 const VkExtent2D renderSize)
216 {
217 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
218 {
219 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
220 DE_NULL, // const void* pNext;
221 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
222 0u, // uint32_t vertexBindingDescriptionCount;
223 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
224 0u, // uint32_t vertexAttributeDescriptionCount;
225 DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
226 };
227
228 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
229 {
230 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
231 DE_NULL, // const void* pNext;
232 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
233 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // VkPrimitiveTopology topology;
234 VK_FALSE, // VkBool32 primitiveRestartEnable;
235 };
236
237 const VkViewport viewport = makeViewport(
238 0.0f, 0.0f,
239 static_cast<float>(renderSize.width), static_cast<float>(renderSize.height),
240 0.0f, 1.0f);
241 const VkRect2D scissor =
242 {
243 makeOffset2D(0, 0),
244 makeExtent2D(renderSize.width, renderSize.height),
245 };
246
247 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
248 {
249 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
250 DE_NULL, // const void* pNext;
251 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
252 1u, // uint32_t viewportCount;
253 &viewport, // const VkViewport* pViewports;
254 1u, // uint32_t scissorCount;
255 &scissor, // const VkRect2D* pScissors;
256 };
257
258 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
259 {
260 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
261 DE_NULL, // const void* pNext;
262 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
263 VK_FALSE, // VkBool32 depthClampEnable;
264 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
265 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
266 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
267 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
268 VK_FALSE, // VkBool32 depthBiasEnable;
269 0.0f, // float depthBiasConstantFactor;
270 0.0f, // float depthBiasClamp;
271 0.0f, // float depthBiasSlopeFactor;
272 1.0f, // float lineWidth;
273 };
274
275 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
276 {
277 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
278 DE_NULL, // const void* pNext;
279 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
280 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
281 VK_FALSE, // VkBool32 sampleShadingEnable;
282 0.0f, // float minSampleShading;
283 DE_NULL, // const VkSampleMask* pSampleMask;
284 VK_FALSE, // VkBool32 alphaToCoverageEnable;
285 VK_FALSE // VkBool32 alphaToOneEnable;
286 };
287
288 const VkStencilOpState stencilOpState = makeStencilOpState(
289 VK_STENCIL_OP_KEEP, // stencil fail
290 VK_STENCIL_OP_KEEP, // depth & stencil pass
291 VK_STENCIL_OP_KEEP, // depth only fail
292 VK_COMPARE_OP_ALWAYS, // compare op
293 0u, // compare mask
294 0u, // write mask
295 0u); // reference
296
297 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
298 {
299 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
300 DE_NULL, // const void* pNext;
301 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
302 VK_FALSE, // VkBool32 depthTestEnable;
303 VK_FALSE, // VkBool32 depthWriteEnable;
304 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
305 VK_FALSE, // VkBool32 depthBoundsTestEnable;
306 VK_FALSE, // VkBool32 stencilTestEnable;
307 stencilOpState, // VkStencilOpState front;
308 stencilOpState, // VkStencilOpState back;
309 0.0f, // float minDepthBounds;
310 1.0f, // float maxDepthBounds;
311 };
312
313 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
314 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
315 {
316 VK_FALSE, // VkBool32 blendEnable;
317 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
318 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
319 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
320 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
321 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
322 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
323 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
324 };
325
326 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
327 {
328 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
329 DE_NULL, // const void* pNext;
330 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
331 VK_FALSE, // VkBool32 logicOpEnable;
332 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
333 1u, // deUint32 attachmentCount;
334 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
335 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
336 };
337
338 const VkPipelineShaderStageCreateInfo pShaderStages[] =
339 {
340 {
341 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
342 DE_NULL, // const void* pNext;
343 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
344 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
345 vertexModule, // VkShaderModule module;
346 "main", // const char* pName;
347 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
348 },
349 {
350 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
351 DE_NULL, // const void* pNext;
352 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
353 VK_SHADER_STAGE_GEOMETRY_BIT, // VkShaderStageFlagBits stage;
354 geometryModule, // VkShaderModule module;
355 "main", // const char* pName;
356 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
357 },
358 {
359 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
360 DE_NULL, // const void* pNext;
361 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
362 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
363 fragmentModule, // VkShaderModule module;
364 "main", // const char* pName;
365 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
366 },
367 };
368
369 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
370 {
371 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
372 DE_NULL, // const void* pNext;
373 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
374 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
375 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
376 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
377 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
378 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
379 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
380 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
381 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
382 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
383 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
384 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
385 pipelineLayout, // VkPipelineLayout layout;
386 renderPass, // VkRenderPass renderPass;
387 0u, // deUint32 subpass;
388 DE_NULL, // VkPipeline basePipelineHandle;
389 0, // deInt32 basePipelineIndex;
390 };
391
392 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
393 }
394
395 //! Convenience wrapper to access 1D, 2D, and 3D image layers/slices in a uniform way.
396 class LayeredImageAccess
397 {
398 public:
create(const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const void * pData)399 static LayeredImageAccess create (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
400 {
401 if (type == VK_IMAGE_TYPE_1D)
402 return LayeredImageAccess(format, size.width, numLayers, pData);
403 else
404 return LayeredImageAccess(type, format, size, numLayers, pData);
405 }
406
getLayer(const int layer) const407 inline tcu::ConstPixelBufferAccess getLayer (const int layer) const
408 {
409 return tcu::getSubregion(m_wholeImage, 0, (m_1dModifier * layer), ((~m_1dModifier & 1) * layer), m_width, m_height, 1);
410 }
411
getNumLayersOrSlices(void) const412 inline int getNumLayersOrSlices (void) const
413 {
414 return m_layers;
415 }
416
417 private:
418 // Specialized for 1D images.
LayeredImageAccess(const VkFormat format,const deUint32 width,const deUint32 numLayers,const void * pData)419 LayeredImageAccess (const VkFormat format, const deUint32 width, const deUint32 numLayers, const void* pData)
420 : m_width (static_cast<int>(width))
421 , m_height (1)
422 , m_1dModifier (1)
423 , m_layers (numLayers)
424 , m_wholeImage (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_layers, 1, pData))
425 {
426 }
427
LayeredImageAccess(const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const void * pData)428 LayeredImageAccess (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
429 : m_width (static_cast<int>(size.width))
430 , m_height (static_cast<int>(size.height))
431 , m_1dModifier (0)
432 , m_layers (static_cast<int>(type == VK_IMAGE_TYPE_3D ? size.depth : numLayers))
433 , m_wholeImage (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_height, m_layers, pData))
434 {
435 }
436
437 const int m_width;
438 const int m_height;
439 const int m_1dModifier;
440 const int m_layers;
441 const tcu::ConstPixelBufferAccess m_wholeImage;
442 };
443
compareColors(const Vec4 & colorA,const Vec4 & colorB,const Vec4 & threshold)444 inline bool compareColors (const Vec4& colorA, const Vec4& colorB, const Vec4& threshold)
445 {
446 return tcu::allEqual(
447 tcu::lessThan(tcu::abs(colorA - colorB), threshold),
448 tcu::BVec4(true, true, true, true));
449 }
450
verifyImageSingleColoredRow(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image,const float rowWidthRatio,const tcu::Vec4 & barColor)451 bool verifyImageSingleColoredRow (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const float rowWidthRatio, const tcu::Vec4& barColor)
452 {
453 DE_ASSERT(rowWidthRatio > 0.0f);
454
455 const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
456 const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
457 const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
458 const Vec4 threshold (0.02f);
459 const int barLength = static_cast<int>(rowWidthRatio * static_cast<float>(image.getWidth()));
460 const int barLengthThreshold = 1;
461 tcu::TextureLevel errorMask (image.getFormat(), image.getWidth(), image.getHeight());
462 tcu::PixelBufferAccess errorMaskAccess = errorMask.getAccess();
463
464 tcu::clear(errorMask.getAccess(), green);
465
466 log << tcu::TestLog::Message
467 << "Expecting all pixels with distance less or equal to (about) " << barLength
468 << " pixels from left border to be of color " << barColor.swizzle(0, 1, 2) << "."
469 << tcu::TestLog::EndMessage;
470
471 bool allPixelsOk = true;
472
473 for (int y = 0; y < image.getHeight(); ++y)
474 for (int x = 0; x < image.getWidth(); ++x)
475 {
476 const Vec4 color = image.getPixel(x, y);
477 const bool isBlack = compareColors(color, black, threshold);
478 const bool isColor = compareColors(color, barColor, threshold);
479
480 bool isOk;
481
482 if (x <= barLength - barLengthThreshold)
483 isOk = isColor;
484 else if (x >= barLength + barLengthThreshold)
485 isOk = isBlack;
486 else
487 isOk = isColor || isBlack;
488
489 allPixelsOk &= isOk;
490
491 if (!isOk)
492 errorMaskAccess.setPixel(red, x, y);
493 }
494
495 if (allPixelsOk)
496 {
497 log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
498 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
499 << tcu::TestLog::Image("Layer", "Layer", image)
500 << tcu::TestLog::EndImageSet;
501 return true;
502 }
503 else
504 {
505 log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
506 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
507 << tcu::TestLog::Image("Layer", "Layer", image)
508 << tcu::TestLog::Image("ErrorMask", "Errors", errorMask)
509 << tcu::TestLog::EndImageSet;
510 return false;
511 }
512
513 log << tcu::TestLog::Image("LayerContent", "Layer content", image);
514
515 return allPixelsOk;
516 }
517
verifyEmptyImage(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image)518 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
519 {
520 log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
521
522 const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
523 const Vec4 threshold (0.02f);
524
525 for (int y = 0; y < image.getHeight(); ++y)
526 for (int x = 0; x < image.getWidth(); ++x)
527 {
528 const Vec4 color = image.getPixel(x, y);
529
530 if (!compareColors(color, black, threshold))
531 {
532 log << tcu::TestLog::Message
533 << "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
534 << tcu::TestLog::EndMessage
535 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
536 << tcu::TestLog::Image("Layer", "Layer", image)
537 << tcu::TestLog::EndImageSet;
538 return false;
539 }
540 }
541
542 log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
543
544 return true;
545 }
546
verifyLayerContent(tcu::TestLog & log,const TestType testType,const tcu::ConstPixelBufferAccess image,const int layerNdx,const int numLayers)547 bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers)
548 {
549 const Vec4 white (1.0f, 1.0f, 1.0f, 1.0f);
550 const int targetLayer = numLayers / 2;
551 const float variableBarRatio = static_cast<float>(layerNdx) / static_cast<float>(numLayers);
552
553 switch (testType)
554 {
555 case TEST_TYPE_DEFAULT_LAYER:
556 if (layerNdx == 0)
557 return verifyImageSingleColoredRow(log, image, 0.5f, white);
558 else
559 return verifyEmptyImage(log, image);
560
561 case TEST_TYPE_SINGLE_LAYER:
562 if (layerNdx == targetLayer)
563 return verifyImageSingleColoredRow(log, image, 0.5f, white);
564 else
565 return verifyEmptyImage(log, image);
566
567 case TEST_TYPE_ALL_LAYERS:
568 case TEST_TYPE_INVOCATION_PER_LAYER:
569 return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
570
571 case TEST_TYPE_DIFFERENT_CONTENT:
572 case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION:
573 if (layerNdx == 0)
574 return verifyEmptyImage(log, image);
575 else
576 return verifyImageSingleColoredRow(log, image, variableBarRatio, white);
577
578 case TEST_TYPE_LAYER_ID:
579 {
580 // This code must be in sync with the fragment shader.
581 const tcu::Vec4 layerColor( (layerNdx % 2) == 1 ? 1.0f : 0.5f,
582 ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f,
583 layerNdx == 0 ? 1.0f : 0.0f,
584 1.0f);
585 return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
586 }
587
588 default:
589 DE_ASSERT(0);
590 return false;
591 };
592 }
593
getLayerDescription(const VkImageViewType viewType,const int layer)594 std::string getLayerDescription (const VkImageViewType viewType, const int layer)
595 {
596 std::ostringstream str;
597 const int numCubeFaces = 6;
598
599 if (isCubeImageViewType(viewType))
600 str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces);
601 else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
602 str << "slice z = " << layer;
603 else
604 str << "layer " << layer;
605
606 return str.str();
607 }
608
verifyResults(tcu::TestLog & log,const TestParams & params,const VkFormat colorFormat,const void * resultData)609 bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat colorFormat, const void* resultData)
610 {
611 const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), colorFormat, params.image.size, params.image.numLayers, resultData);
612
613 int numGoodLayers = 0;
614
615 for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx)
616 {
617 const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx);
618
619 log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
620
621 if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices()))
622 ++numGoodLayers;
623 }
624
625 return numGoodLayers == image.getNumLayersOrSlices();
626 }
627
toGlsl(const Vec4 & v)628 std::string toGlsl (const Vec4& v)
629 {
630 std::ostringstream str;
631 str << "vec4(";
632 for (int i = 0; i < 4; ++i)
633 str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1);
634 str << ")";
635 return str.str();
636 }
637
initPrograms(SourceCollections & programCollection,const TestParams params)638 void initPrograms (SourceCollections& programCollection, const TestParams params)
639 {
640 const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER);
641
642 // Vertex shader
643 {
644 std::ostringstream src;
645 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
646 << "\n"
647 << "void main(void)\n"
648 << "{\n"
649 << "}\n";
650
651 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
652 }
653
654 // Geometry shader
655 {
656 const int numLayers = static_cast<int>(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D ? params.image.size.depth : params.image.numLayers);
657
658 const int maxVertices = (params.testType == TEST_TYPE_DIFFERENT_CONTENT) ? (numLayers + 1) * numLayers :
659 (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_LAYER_ID) ? numLayers * 4 :
660 (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION) ? 6 : 4;
661
662 std::ostringstream src;
663 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
664 << "\n";
665
666 if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
667 src << "layout(points, invocations = " << numLayers << ") in;\n";
668 else
669 src << "layout(points) in;\n";
670
671 src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
672 << "\n"
673 << (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "")
674 << "out gl_PerVertex {\n"
675 << " vec4 gl_Position;\n"
676 << "};\n"
677 << "\n"
678 << "void main(void)\n"
679 << "{\n";
680
681 std::ostringstream colorTable;
682 {
683 const int numColors = DE_LENGTH_OF_ARRAY(s_colors);
684
685 colorTable << " const vec4 colors[" << numColors << "] = vec4[" << numColors << "](";
686
687 const std::string padding(colorTable.str().length(), ' ');
688
689 for (int i = 0; i < numColors; ++i)
690 colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]);
691
692 colorTable << ");\n";
693 }
694
695 if (params.testType == TEST_TYPE_DEFAULT_LAYER)
696 {
697 src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
698 << " EmitVertex();\n"
699 << "\n"
700 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
701 << " EmitVertex();\n"
702 << "\n"
703 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
704 << " EmitVertex();\n"
705 << "\n"
706 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
707 << " EmitVertex();\n";
708 }
709 else if (params.testType == TEST_TYPE_SINGLE_LAYER)
710 {
711 const deUint32 targetLayer = getTargetLayer(params.image);
712
713 src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
714 << " gl_Layer = " << targetLayer << ";\n"
715 << " EmitVertex();\n"
716 << "\n"
717 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
718 << " gl_Layer = " << targetLayer << ";\n"
719 << " EmitVertex();\n"
720 << "\n"
721 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
722 << " gl_Layer = " << targetLayer << ";\n"
723 << " EmitVertex();\n"
724 << "\n"
725 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
726 << " gl_Layer = " << targetLayer << ";\n"
727 << " EmitVertex();\n";
728 }
729 else if (params.testType == TEST_TYPE_ALL_LAYERS)
730 {
731 src << colorTable.str()
732 << "\n"
733 << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
734 << " const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
735 << "\n"
736 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
737 << " gl_Layer = layerNdx;\n"
738 << " vert_color = colors[colorNdx];\n"
739 << " EmitVertex();\n"
740 << "\n"
741 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
742 << " gl_Layer = layerNdx;\n"
743 << " vert_color = colors[colorNdx];\n"
744 << " EmitVertex();\n"
745 << "\n"
746 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
747 << " gl_Layer = layerNdx;\n"
748 << " vert_color = colors[colorNdx];\n"
749 << " EmitVertex();\n"
750 << "\n"
751 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
752 << " gl_Layer = layerNdx;\n"
753 << " vert_color = colors[colorNdx];\n"
754 << " EmitVertex();\n"
755 << " EndPrimitive();\n"
756 << " };\n";
757 }
758 else if (params.testType == TEST_TYPE_LAYER_ID)
759 {
760 src << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
761 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
762 << " gl_Layer = layerNdx;\n"
763 << " EmitVertex();\n"
764 << "\n"
765 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
766 << " gl_Layer = layerNdx;\n"
767 << " EmitVertex();\n"
768 << "\n"
769 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
770 << " gl_Layer = layerNdx;\n"
771 << " EmitVertex();\n"
772 << "\n"
773 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
774 << " gl_Layer = layerNdx;\n"
775 << " EmitVertex();\n"
776 << " EndPrimitive();\n"
777 << " };\n";
778 }
779 else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT)
780 {
781 src << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
782 << " for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n"
783 << " const float posX = float(colNdx) / float(" << numLayers << ") * 2.0 - 1.0;\n"
784 << "\n"
785 << " gl_Position = vec4(posX, 1.0, 0.0, 1.0);\n"
786 << " gl_Layer = layerNdx;\n"
787 << " EmitVertex();\n"
788 << "\n"
789 << " gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
790 << " gl_Layer = layerNdx;\n"
791 << " EmitVertex();\n"
792 << " }\n"
793 << " EndPrimitive();\n"
794 << " }\n";
795 }
796 else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER)
797 {
798 src << colorTable.str()
799 << " const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
800 << "\n"
801 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
802 << " gl_Layer = gl_InvocationID;\n"
803 << " vert_color = colors[colorNdx];\n"
804 << " EmitVertex();\n"
805 << "\n"
806 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
807 << " gl_Layer = gl_InvocationID;\n"
808 << " vert_color = colors[colorNdx];\n"
809 << " EmitVertex();\n"
810 << "\n"
811 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
812 << " gl_Layer = gl_InvocationID;\n"
813 << " vert_color = colors[colorNdx];\n"
814 << " EmitVertex();\n"
815 << "\n"
816 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
817 << " gl_Layer = gl_InvocationID;\n"
818 << " vert_color = colors[colorNdx];\n"
819 << " EmitVertex();\n"
820 << " EndPrimitive();\n";
821 }
822 else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
823 {
824 src << " const int layerA = gl_InvocationID;\n"
825 << " const int layerB = (gl_InvocationID + 1) % " << numLayers << ";\n"
826 << " const float aEnd = float(layerA) / float(" << numLayers << ") * 2.0 - 1.0;\n"
827 << " const float bEnd = float(layerB) / float(" << numLayers << ") * 2.0 - 1.0;\n"
828 << "\n"
829 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
830 << " gl_Layer = layerA;\n"
831 << " EmitVertex();\n"
832 << "\n"
833 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
834 << " gl_Layer = layerA;\n"
835 << " EmitVertex();\n"
836 << "\n"
837 << " gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
838 << " gl_Layer = layerA;\n"
839 << " EmitVertex();\n"
840 << " EndPrimitive();\n"
841 << "\n"
842 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
843 << " gl_Layer = layerB;\n"
844 << " EmitVertex();\n"
845 << "\n"
846 << " gl_Position = vec4(bEnd, 1.0, 0.0, 1.0);\n"
847 << " gl_Layer = layerB;\n"
848 << " EmitVertex();\n"
849 << "\n"
850 << " gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
851 << " gl_Layer = layerB;\n"
852 << " EmitVertex();\n"
853 << " EndPrimitive();\n";
854 }
855 else
856 DE_ASSERT(0);
857
858 src << "}\n"; // end main
859
860 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
861 }
862
863 // Fragment shader
864 {
865 std::ostringstream src;
866 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
867 << "\n"
868 << "layout(location = 0) out vec4 o_color;\n"
869 << (geomOutputColor ? "layout(location = 0) in vec4 vert_color;\n" : "")
870 << "\n"
871 << "void main(void)\n"
872 << "{\n";
873
874 if (params.testType == TEST_TYPE_LAYER_ID)
875 {
876 // This code must be in sync with verifyLayerContent()
877 src << " o_color = vec4( (gl_Layer % 2) == 1 ? 1.0 : 0.5,\n"
878 << " ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n"
879 << " gl_Layer == 0 ? 1.0 : 0.0,\n"
880 << " 1.0);\n";
881 }
882 else if (geomOutputColor)
883 src << " o_color = vert_color;\n";
884 else
885 src << " o_color = vec4(1.0);\n";
886
887 src << "}\n";
888
889 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
890 }
891 }
892
test(Context & context,const TestParams params)893 tcu::TestStatus test (Context& context, const TestParams params)
894 {
895 if (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType &&
896 (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance1")))
897 TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
898
899 const DeviceInterface& vk = context.getDeviceInterface();
900 const InstanceInterface& vki = context.getInstanceInterface();
901 const VkDevice device = context.getDevice();
902 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
903 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
904 const VkQueue queue = context.getUniversalQueue();
905 Allocator& allocator = context.getDefaultAllocator();
906
907 checkGeometryShaderSupport(vki, physDevice);
908
909 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
910 const deUint32 numLayers = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
911 const Vec4 clearColor = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
912 const VkDeviceSize colorBufferSize = params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * tcu::getPixelSize(mapVkFormat(colorFormat));
913 const VkImageCreateFlags imageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
914 (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
915 const VkImageViewType viewType = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
916
917 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
918 params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
919 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
920 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
921
922 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
923 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
924
925 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
926 const Unique<VkShaderModule> geometryModule (createShaderModule (vk, device, context.getBinaryCollection().get("geom"), 0u));
927 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
928
929 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, colorFormat));
930 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, params.image.size.width, params.image.size.height, numLayers));
931 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
932 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
933 makeExtent2D(params.image.size.width, params.image.size.height)));
934 const Unique<VkCommandPool> cmdPool (makeCommandPool (vk, device, queueFamilyIndex));
935 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer (vk, device, *cmdPool));
936
937 zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
938
939 beginCommandBuffer(vk, *cmdBuffer);
940
941 const VkClearValue clearValue = makeClearValueColor(clearColor);
942 const VkRect2D renderArea =
943 {
944 makeOffset2D(0, 0),
945 makeExtent2D(params.image.size.width, params.image.size.height),
946 };
947 const VkRenderPassBeginInfo renderPassBeginInfo =
948 {
949 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
950 DE_NULL, // const void* pNext;
951 *renderPass, // VkRenderPass renderPass;
952 *framebuffer, // VkFramebuffer framebuffer;
953 renderArea, // VkRect2D renderArea;
954 1u, // uint32_t clearValueCount;
955 &clearValue, // const VkClearValue* pClearValues;
956 };
957 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
958
959 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
960 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
961 vk.cmdEndRenderPass(*cmdBuffer);
962
963 // Prepare color image for copy
964 {
965 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
966 const VkImageMemoryBarrier barriers[] =
967 {
968 {
969 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
970 DE_NULL, // const void* pNext;
971 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
972 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
973 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
974 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
975 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
976 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
977 *colorImage, // VkImage image;
978 colorSubresourceRange, // VkImageSubresourceRange subresourceRange;
979 },
980 };
981
982 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
983 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
984 }
985 // Color image -> host buffer
986 {
987 const VkBufferImageCopy region =
988 {
989 0ull, // VkDeviceSize bufferOffset;
990 0u, // uint32_t bufferRowLength;
991 0u, // uint32_t bufferImageHeight;
992 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers), // VkImageSubresourceLayers imageSubresource;
993 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
994 params.image.size, // VkExtent3D imageExtent;
995 };
996
997 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
998 }
999 // Buffer write barrier
1000 {
1001 const VkBufferMemoryBarrier barriers[] =
1002 {
1003 {
1004 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1005 DE_NULL, // const void* pNext;
1006 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1007 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1008 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1009 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1010 *colorBuffer, // VkBuffer buffer;
1011 0ull, // VkDeviceSize offset;
1012 VK_WHOLE_SIZE, // VkDeviceSize size;
1013 },
1014 };
1015
1016 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1017 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
1018 }
1019
1020 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1021 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1022
1023 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
1024
1025 if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1026 return tcu::TestStatus::fail("Rendered images are incorrect");
1027 else
1028 return tcu::TestStatus::pass("OK");
1029 }
1030
1031 } // anonymous
1032
createLayeredRenderingTests(tcu::TestContext & testCtx)1033 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
1034 {
1035 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests."));
1036
1037 const struct
1038 {
1039 TestType test;
1040 const char* name;
1041 const char* description;
1042 } testTypes[] =
1043 {
1044 { TEST_TYPE_DEFAULT_LAYER, "render_to_default_layer", "Render to the default layer" },
1045 { TEST_TYPE_SINGLE_LAYER, "render_to_one", "Render to one layer" },
1046 { TEST_TYPE_ALL_LAYERS, "render_to_all", "Render to all layers" },
1047 { TEST_TYPE_DIFFERENT_CONTENT, "render_different_content", "Render different data to different layers" },
1048 { TEST_TYPE_LAYER_ID, "fragment_layer", "Read gl_Layer in fragment shader" },
1049 { TEST_TYPE_INVOCATION_PER_LAYER, "invocation_per_layer", "Render to multiple layers with multiple invocations, one invocation per layer" },
1050 { TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION, "multiple_layers_per_invocation", "Render to multiple layers with multiple invocations, multiple layers per invocation", },
1051 };
1052
1053 const ImageParams imageParams[] =
1054 {
1055 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, { 64, 1, 1 }, 4 },
1056 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, { 64, 64, 1 }, 4 },
1057 { VK_IMAGE_VIEW_TYPE_CUBE, { 64, 64, 1 }, 6 },
1058 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, { 64, 64, 1 }, 2*6 },
1059 { VK_IMAGE_VIEW_TYPE_3D, { 64, 64, 8 }, 1 }
1060 };
1061
1062 for (int imageParamNdx = 0; imageParamNdx < DE_LENGTH_OF_ARRAY(imageParams); ++imageParamNdx)
1063 {
1064 MovePtr<tcu::TestCaseGroup> viewTypeGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParams[imageParamNdx].viewType).c_str(), ""));
1065
1066 for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1067 {
1068 const TestParams params =
1069 {
1070 testTypes[testTypeNdx].test,
1071 imageParams[imageParamNdx],
1072 };
1073 addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, test, params);
1074 }
1075
1076 group->addChild(viewTypeGroup.release());
1077 }
1078
1079 return group.release();
1080 }
1081
1082 } // geometry
1083 } // vkt
1084