1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Tests for mutable images
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktImageMutableTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26 #include "vktImageTexture.hpp"
27
28 #include "vkBuilderUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkImageUtil.hpp"
31
32 #include "deUniquePtr.hpp"
33 #include "deSharedPtr.hpp"
34
35 #include "tcuImageCompare.hpp"
36 #include "tcuTestLog.hpp"
37 #include "tcuTextureUtil.hpp"
38
39 #include <string>
40 #include <vector>
41
42 using namespace vk;
43 using namespace tcu;
44
45 using de::UniquePtr;
46 using de::MovePtr;
47 using de::SharedPtr;
48 using std::vector;
49
50 namespace vkt
51 {
52 namespace image
53 {
54
55 typedef SharedPtr<Unique<VkPipeline> > SharedPtrVkPipeline;
56 typedef SharedPtr<Unique<VkImageView> > SharedPtrVkImageView;
57
58 template<typename T>
makeSharedPtr(Move<T> move)59 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
60 {
61 return SharedPtr<Unique<T> >(new Unique<T>(move));
62 }
63
64 enum Upload {
65 UPLOAD_CLEAR = 0,
66 UPLOAD_COPY,
67 UPLOAD_STORE,
68 UPLOAD_DRAW,
69 UPLOAD_LAST
70 };
71
72 enum Download {
73 DOWNLOAD_COPY = 0,
74 DOWNLOAD_LOAD,
75 DOWNLOAD_TEXTURE,
76 DOWNLOAD_LAST
77 };
78
getUploadString(const int upload)79 std::string getUploadString (const int upload)
80 {
81 const char* strs[] = { "clear", "copy", "store", "draw" };
82 return strs[upload];
83 }
84
getDownloadString(const int download)85 std::string getDownloadString (const int download)
86 {
87 const char* strs[] = { "copy", "load", "texture" };
88 return strs[download];
89 }
90
91 struct CaseDef
92 {
93 ImageType imageType;
94 IVec3 size;
95 deUint32 numLayers;
96 VkFormat imageFormat;
97 VkFormat viewFormat;
98 enum Upload upload;
99 enum Download download;
100 bool isFormatListTest;
101 };
102
103 static const deUint32 COLOR_TABLE_SIZE = 4;
104
105 // Reference color values for float color rendering. Values have been chosen
106 // so that when the bit patterns are reinterpreted as a 16-bit float, we do not
107 // run into NaN / inf / denorm values.
108 static const Vec4 COLOR_TABLE_FLOAT[COLOR_TABLE_SIZE] =
109 {
110 Vec4(0.00f, 0.40f, 0.80f, 0.10f),
111 Vec4(0.10f, 0.50f, 0.90f, 0.20f),
112 Vec4(0.20f, 0.60f, 1.00f, 0.30f),
113 Vec4(0.30f, 0.70f, 0.00f, 0.40f),
114 };
115
116 // Reference color values for integer color rendering. We avoid negative
117 // values (even for SINT formats) to avoid the situation where sign extension
118 // leads to NaN / inf values when they are reinterpreted with a float
119 // format.
120 static const IVec4 COLOR_TABLE_INT[COLOR_TABLE_SIZE] =
121 {
122 IVec4(112, 60, 101, 41),
123 IVec4( 60, 101, 41, 112),
124 IVec4( 41, 112, 60, 101),
125 IVec4(101, 41, 112, 60),
126 };
127
128 // Reference clear colors created from the color table values
129 static const VkClearValue REFERENCE_CLEAR_COLOR_FLOAT[COLOR_TABLE_SIZE] =
130 {
131 makeClearValueColorF32(COLOR_TABLE_FLOAT[0].x(), COLOR_TABLE_FLOAT[0].y(), COLOR_TABLE_FLOAT[0].z(), COLOR_TABLE_FLOAT[0].w()),
132 makeClearValueColorF32(COLOR_TABLE_FLOAT[1].x(), COLOR_TABLE_FLOAT[1].y(), COLOR_TABLE_FLOAT[1].z(), COLOR_TABLE_FLOAT[1].w()),
133 makeClearValueColorF32(COLOR_TABLE_FLOAT[2].x(), COLOR_TABLE_FLOAT[2].y(), COLOR_TABLE_FLOAT[2].z(), COLOR_TABLE_FLOAT[2].w()),
134 makeClearValueColorF32(COLOR_TABLE_FLOAT[3].x(), COLOR_TABLE_FLOAT[3].y(), COLOR_TABLE_FLOAT[3].z(), COLOR_TABLE_FLOAT[3].w()),
135 };
136
137 static const VkClearValue REFERENCE_CLEAR_COLOR_INT[COLOR_TABLE_SIZE] =
138 {
139 makeClearValueColorI32(COLOR_TABLE_INT[0].x(), COLOR_TABLE_INT[0].y(), COLOR_TABLE_INT[0].z(), COLOR_TABLE_INT[0].w()),
140 makeClearValueColorI32(COLOR_TABLE_INT[1].x(), COLOR_TABLE_INT[1].y(), COLOR_TABLE_INT[1].z(), COLOR_TABLE_INT[1].w()),
141 makeClearValueColorI32(COLOR_TABLE_INT[2].x(), COLOR_TABLE_INT[2].y(), COLOR_TABLE_INT[2].z(), COLOR_TABLE_INT[2].w()),
142 makeClearValueColorI32(COLOR_TABLE_INT[3].x(), COLOR_TABLE_INT[3].y(), COLOR_TABLE_INT[3].z(), COLOR_TABLE_INT[3].w()),
143 };
144
145 static const Texture s_textures[] =
146 {
147 Texture(IMAGE_TYPE_2D, tcu::IVec3(32, 32, 1), 1),
148 Texture(IMAGE_TYPE_2D_ARRAY, tcu::IVec3(32, 32, 1), 4),
149 };
150
getImageType(const ImageType textureImageType)151 VkImageType getImageType (const ImageType textureImageType)
152 {
153 switch (textureImageType)
154 {
155 case IMAGE_TYPE_2D:
156 case IMAGE_TYPE_2D_ARRAY:
157 return VK_IMAGE_TYPE_2D;
158
159 default:
160 DE_ASSERT(0);
161 return VK_IMAGE_TYPE_LAST;
162 }
163 }
164
getImageViewType(const ImageType textureImageType)165 VkImageViewType getImageViewType (const ImageType textureImageType)
166 {
167 switch (textureImageType)
168 {
169 case IMAGE_TYPE_2D:
170 return VK_IMAGE_VIEW_TYPE_2D;
171 case IMAGE_TYPE_2D_ARRAY:
172 return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
173
174 default:
175 DE_ASSERT(0);
176 return VK_IMAGE_VIEW_TYPE_LAST;
177 }
178 }
179
180 static const VkFormat s_formats[] =
181 {
182 VK_FORMAT_R32G32B32A32_SFLOAT,
183 VK_FORMAT_R16G16B16A16_SFLOAT,
184 VK_FORMAT_R32G32_SFLOAT,
185 VK_FORMAT_R16G16_SFLOAT,
186 VK_FORMAT_R32_SFLOAT,
187
188 VK_FORMAT_R32G32B32A32_UINT,
189 VK_FORMAT_R16G16B16A16_UINT,
190 VK_FORMAT_R8G8B8A8_UINT,
191 VK_FORMAT_R32G32_UINT,
192 VK_FORMAT_R16G16_UINT,
193 VK_FORMAT_R32_UINT,
194
195 VK_FORMAT_R32G32B32A32_SINT,
196 VK_FORMAT_R16G16B16A16_SINT,
197 VK_FORMAT_R8G8B8A8_SINT,
198 VK_FORMAT_R32G32_SINT,
199 VK_FORMAT_R16G16_SINT,
200 VK_FORMAT_R32_SINT,
201
202 VK_FORMAT_R8G8B8A8_UNORM,
203
204 VK_FORMAT_R8G8B8A8_SNORM,
205 };
206
formatsAreCompatible(const VkFormat format0,const VkFormat format1)207 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
208 {
209 return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
210 }
211
getColorFormatStr(const int numComponents,const bool isUint,const bool isSint)212 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
213 {
214 std::ostringstream str;
215 if (numComponents == 1)
216 str << (isUint ? "uint" : isSint ? "int" : "float");
217 else
218 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
219
220 return str.str();
221 }
222
getShaderSamplerType(const tcu::TextureFormat & format,VkImageViewType type)223 std::string getShaderSamplerType (const tcu::TextureFormat& format, VkImageViewType type)
224 {
225 std::ostringstream samplerType;
226
227 if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
228 samplerType << "u";
229 else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
230 samplerType << "i";
231
232 switch (type)
233 {
234 case VK_IMAGE_VIEW_TYPE_2D:
235 samplerType << "sampler2D";
236 break;
237
238 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
239 samplerType << "sampler2DArray";
240 break;
241
242 default:
243 DE_FATAL("Ivalid image view type");
244 break;
245 }
246
247 return samplerType.str();
248 }
249
initPrograms(SourceCollections & programCollection,const CaseDef caseDef)250 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
251 {
252 if (caseDef.upload == UPLOAD_DRAW)
253 {
254 {
255 std::ostringstream src;
256 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
257 << "\n"
258 << "layout(location = 0) in vec4 in_position;\n"
259 << "layout(location = 1) in vec4 in_color;\n"
260 << "layout(location = 0) out vec4 out_color;\n"
261 << "\n"
262 << "out gl_PerVertex {\n"
263 << " vec4 gl_Position;\n"
264 << "};\n"
265 << "\n"
266 << "void main(void)\n"
267 << "{\n"
268 << " gl_Position = in_position;\n"
269 << " out_color = in_color;\n"
270 << "}\n";
271
272 programCollection.glslSources.add("uploadDrawVert") << glu::VertexSource(src.str());
273 }
274
275 {
276 const int numComponents = getNumUsedChannels(mapVkFormat(caseDef.viewFormat).order);
277 const bool isUint = isUintFormat(caseDef.viewFormat);
278 const bool isSint = isIntFormat(caseDef.viewFormat);
279 const std::string colorFormat = getColorFormatStr(numComponents, isUint, isSint);
280
281 std::ostringstream src;
282 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
283 << "\n"
284 << "layout(location = 0) in vec4 in_color;\n"
285 << "layout(location = 0) out " << colorFormat << " out_color;\n"
286 << "\n"
287 << "void main(void)\n"
288 << "{\n"
289 << " out_color = " << colorFormat << "("
290 << (numComponents == 1 ? "in_color.r" :
291 numComponents == 2 ? "in_color.rg" :
292 numComponents == 3 ? "in_color.rgb" : "in_color")
293 << ");\n"
294 << "}\n";
295
296 programCollection.glslSources.add("uploadDrawFrag") << glu::FragmentSource(src.str());
297 }
298 }
299
300 if (caseDef.upload == UPLOAD_STORE)
301 {
302 const TextureFormat tcuFormat = mapVkFormat(caseDef.viewFormat);
303 const std::string imageFormatStr = getShaderImageFormatQualifier(tcuFormat);
304 const std::string imageTypeStr = getShaderImageType(tcuFormat, caseDef.imageType);
305 const std::string colorTypeStr = isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
306 const bool isIntegerFormat = isUintFormat(caseDef.viewFormat) || isIntFormat(caseDef.viewFormat);
307
308 std::ostringstream src;
309 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
310 << "\n"
311 << "layout (local_size_x = 1) in;\n"
312 << "\n"
313 << "layout(binding=0, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " u_image;\n"
314 << "\n"
315 << "const " << colorTypeStr << " colorTable[] = " << colorTypeStr << "[](\n";
316 for (deUint32 idx = 0; idx < COLOR_TABLE_SIZE; idx++)
317 {
318 if (isIntegerFormat)
319 src << " " << colorTypeStr << "(" << COLOR_TABLE_INT[idx].x() << ", " << COLOR_TABLE_INT[idx].y() << ", " << COLOR_TABLE_INT[idx].z() << ", " << COLOR_TABLE_INT[idx].w() << ")";
320 else
321 src << " " << colorTypeStr << "(" << COLOR_TABLE_FLOAT[idx].x() << ", " << COLOR_TABLE_FLOAT[idx].y() << ", " << COLOR_TABLE_FLOAT[idx].z() << ", " << COLOR_TABLE_FLOAT[idx].w() << ")";
322 if (idx < COLOR_TABLE_SIZE - 1)
323 src << ",";
324 src << "\n";
325 }
326 src << ");\n"
327 << "\n"
328 << "void main(void)\n"
329 << "{\n";
330 if (caseDef.imageType == IMAGE_TYPE_2D)
331 {
332 src << " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
333 }
334 else
335 {
336 DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
337 src << " ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
338 }
339 src << " " << colorTypeStr << " color = colorTable[gl_GlobalInvocationID.z];\n"
340 << " imageStore(u_image, pos, color);\n"
341 << "}\n";
342
343 programCollection.glslSources.add("uploadStoreComp") << glu::ComputeSource(src.str());
344 }
345
346 if (caseDef.download == DOWNLOAD_LOAD)
347 {
348 const TextureFormat tcuFormat = mapVkFormat(caseDef.viewFormat);
349 const std::string imageFormatStr = getShaderImageFormatQualifier(tcuFormat);
350 const std::string imageTypeStr = getShaderImageType(tcuFormat, caseDef.imageType);
351 const std::string colorTypeStr = isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
352
353 std::ostringstream src;
354 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
355 << "\n"
356 << "layout (local_size_x = 1) in;\n"
357 << "\n"
358 << "layout(binding=0, " << imageFormatStr << ") readonly uniform " << imageTypeStr << " in_image;\n"
359 << "layout(binding=1, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " out_image;\n"
360 << "\n"
361 << "void main(void)\n"
362 << "{\n";
363 if (caseDef.imageType == IMAGE_TYPE_2D)
364 {
365 src << " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
366 }
367 else
368 {
369 DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
370 src << " ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
371 }
372 src << " imageStore(out_image, pos, imageLoad(in_image, pos));\n"
373 << "}\n";
374
375 programCollection.glslSources.add("downloadLoadComp") << glu::ComputeSource(src.str());
376 }
377
378 if (caseDef.download == DOWNLOAD_TEXTURE)
379 {
380 const TextureFormat tcuFormat = mapVkFormat(caseDef.viewFormat);
381 const VkImageViewType viewType = getImageViewType(caseDef.imageType);
382 const std::string samplerTypeStr = getShaderSamplerType(tcuFormat, viewType);
383 const std::string imageFormatStr = getShaderImageFormatQualifier(tcuFormat);
384 const std::string imageTypeStr = getShaderImageType(tcuFormat, caseDef.imageType);
385 const std::string colorTypeStr = isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
386
387 std::ostringstream src;
388 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
389 << "\n"
390 << "layout (local_size_x = 1) in;\n"
391 << "\n"
392 << "layout(binding=0) uniform " << samplerTypeStr << " u_tex;\n"
393 << "layout(binding=1, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " out_image;\n"
394 << "\n"
395 << "void main(void)\n"
396 << "{\n";
397 if (caseDef.imageType == IMAGE_TYPE_2D)
398 {
399 src << " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
400 }
401 else
402 {
403 DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
404 src << " ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
405 }
406 src << " imageStore(out_image, pos, texelFetch(u_tex, pos, 0));\n"
407 << "}\n";
408
409 programCollection.glslSources.add("downloadTextureComp") << glu::ComputeSource(src.str());
410 }
411 }
412
makeImage(const DeviceInterface & vk,const VkDevice device,VkImageCreateFlags flags,VkImageType imageType,const VkFormat format,const VkFormat viewFormat,const bool useImageFormatList,const IVec3 & size,const deUint32 numMipLevels,const deUint32 numLayers,const VkImageUsageFlags usage)413 Move<VkImage> makeImage (const DeviceInterface& vk,
414 const VkDevice device,
415 VkImageCreateFlags flags,
416 VkImageType imageType,
417 const VkFormat format,
418 const VkFormat viewFormat,
419 const bool useImageFormatList,
420 const IVec3& size,
421 const deUint32 numMipLevels,
422 const deUint32 numLayers,
423 const VkImageUsageFlags usage)
424 {
425 const VkFormat formatList[2] =
426 {
427 format,
428 viewFormat
429 };
430
431 const VkImageFormatListCreateInfoKHR formatListInfo =
432 {
433 VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR, // VkStructureType sType;
434 DE_NULL, // const void* pNext;
435 2u, // deUint32 viewFormatCount
436 formatList // const VkFormat* pViewFormats
437 };
438
439 const VkImageCreateInfo imageParams =
440 {
441 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
442 useImageFormatList ? &formatListInfo : DE_NULL, // const void* pNext;
443 flags, // VkImageCreateFlags flags;
444 imageType, // VkImageType imageType;
445 format, // VkFormat format;
446 makeExtent3D(size), // VkExtent3D extent;
447 numMipLevels, // deUint32 mipLevels;
448 numLayers, // deUint32 arrayLayers;
449 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
450 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
451 usage, // VkImageUsageFlags usage;
452 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
453 0u, // deUint32 queueFamilyIndexCount;
454 DE_NULL, // const deUint32* pQueueFamilyIndices;
455 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
456 };
457 return createImage(vk, device, &imageParams);
458 }
459
makeBuffer(const DeviceInterface & vk,const VkDevice device,const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)460 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
461 {
462 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
463 return createBuffer(vk, device, &bufferCreateInfo);
464 }
465
makeColorSubresourceRange(const int baseArrayLayer,const int layerCount)466 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
467 {
468 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
469 }
470
makeSampler(const DeviceInterface & vk,const VkDevice device)471 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
472 {
473 const VkSamplerCreateInfo samplerParams =
474 {
475 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
476 DE_NULL, // const void* pNext;
477 (VkSamplerCreateFlags)0, // VkSamplerCreateFlags flags;
478 VK_FILTER_NEAREST, // VkFilter magFilter;
479 VK_FILTER_NEAREST, // VkFilter minFilter;
480 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
481 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
482 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
483 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
484 0.0f, // float mipLodBias;
485 VK_FALSE, // VkBool32 anisotropyEnable;
486 1.0f, // float maxAnisotropy;
487 VK_FALSE, // VkBool32 compareEnable;
488 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
489 0.0f, // float minLod;
490 0.0f, // float maxLod;
491 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
492 VK_FALSE, // VkBool32 unnormalizedCoordinates;
493 };
494
495 return createSampler(vk, device, &samplerParams);
496 }
497
498
makePipelineLayout(const DeviceInterface & vk,const VkDevice device)499 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface& vk,
500 const VkDevice device)
501 {
502 const VkPipelineLayoutCreateInfo info =
503 {
504 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
505 DE_NULL,
506 (VkPipelineLayoutCreateFlags)0,
507 0u,
508 DE_NULL,
509 0u,
510 DE_NULL,
511 };
512 return createPipelineLayout(vk, device, &info);
513 }
514
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const IVec2 & renderSize,const VkPrimitiveTopology topology,const deUint32 subpass)515 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
516 const VkDevice device,
517 const VkPipelineLayout pipelineLayout,
518 const VkRenderPass renderPass,
519 const VkShaderModule vertexModule,
520 const VkShaderModule fragmentModule,
521 const IVec2& renderSize,
522 const VkPrimitiveTopology topology,
523 const deUint32 subpass)
524 {
525 const VkVertexInputBindingDescription vertexInputBindingDescription =
526 {
527 0u, // deUint32 binding;
528 (deUint32)(2 * sizeof(Vec4)), // deUint32 stride;
529 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
530 };
531
532 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
533 {
534 {
535 0u, // deUint32 location;
536 0u, // deUint32 binding;
537 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
538 0u, // deUint32 offset;
539 },
540 {
541 1u, // deUint32 location;
542 0u, // deUint32 binding;
543 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
544 (deUint32)sizeof(Vec4), // deUint32 offset;
545 }
546 };
547
548 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
549 {
550 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
551 DE_NULL, // const void* pNext;
552 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
553 1u, // deUint32 vertexBindingDescriptionCount;
554 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
555 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // deUint32 vertexAttributeDescriptionCount;
556 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
557 };
558
559 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
560 {
561 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
562 DE_NULL, // const void* pNext;
563 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
564 topology, // VkPrimitiveTopology topology;
565 VK_FALSE, // VkBool32 primitiveRestartEnable;
566 };
567
568 const VkViewport viewport = makeViewport(
569 0.0f, 0.0f,
570 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
571 0.0f, 1.0f);
572
573 const VkRect2D scissor =
574 {
575 makeOffset2D(0, 0),
576 makeExtent2D(renderSize.x(), renderSize.y()),
577 };
578
579 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
580 {
581 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
582 DE_NULL, // const void* pNext;
583 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
584 1u, // deUint32 viewportCount;
585 &viewport, // const VkViewport* pViewports;
586 1u, // deUint32 scissorCount;
587 &scissor, // const VkRect2D* pScissors;
588 };
589
590 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
591 {
592 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
593 DE_NULL, // const void* pNext;
594 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
595 VK_FALSE, // VkBool32 depthClampEnable;
596 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
597 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
598 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
599 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
600 VK_FALSE, // VkBool32 depthBiasEnable;
601 0.0f, // float depthBiasConstantFactor;
602 0.0f, // float depthBiasClamp;
603 0.0f, // float depthBiasSlopeFactor;
604 1.0f, // float lineWidth;
605 };
606
607 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
608 {
609 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
610 DE_NULL, // const void* pNext;
611 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
612 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
613 VK_FALSE, // VkBool32 sampleShadingEnable;
614 0.0f, // float minSampleShading;
615 DE_NULL, // const VkSampleMask* pSampleMask;
616 VK_FALSE, // VkBool32 alphaToCoverageEnable;
617 VK_FALSE // VkBool32 alphaToOneEnable;
618 };
619
620 const VkStencilOpState stencilOpState = makeStencilOpState(
621 VK_STENCIL_OP_KEEP, // stencil fail
622 VK_STENCIL_OP_ZERO, // depth & stencil pass
623 VK_STENCIL_OP_KEEP, // depth only fail
624 VK_COMPARE_OP_EQUAL, // compare op
625 ~0u, // compare mask
626 ~0u, // write mask
627 0u); // reference
628
629 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
630 {
631 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
632 DE_NULL, // const void* pNext;
633 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
634 VK_FALSE, // VkBool32 depthTestEnable;
635 VK_FALSE, // VkBool32 depthWriteEnable;
636 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
637 VK_FALSE, // VkBool32 depthBoundsTestEnable;
638 VK_FALSE, // VkBool32 stencilTestEnable;
639 stencilOpState, // VkStencilOpState front;
640 stencilOpState, // VkStencilOpState back;
641 0.0f, // float minDepthBounds;
642 1.0f, // float maxDepthBounds;
643 };
644
645 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
646 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
647 {
648 VK_FALSE, // VkBool32 blendEnable;
649 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
650 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
651 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
652 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
653 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
654 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
655 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
656 };
657
658 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
659 {
660 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
661 DE_NULL, // const void* pNext;
662 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
663 VK_FALSE, // VkBool32 logicOpEnable;
664 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
665 1u, // deUint32 attachmentCount;
666 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
667 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
668 };
669
670 const VkPipelineShaderStageCreateInfo pShaderStages[] =
671 {
672 {
673 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
674 DE_NULL, // const void* pNext;
675 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
676 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
677 vertexModule, // VkShaderModule module;
678 "main", // const char* pName;
679 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
680 },
681 {
682 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
683 DE_NULL, // const void* pNext;
684 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
685 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
686 fragmentModule, // VkShaderModule module;
687 "main", // const char* pName;
688 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
689 }
690 };
691
692 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
693 {
694 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
695 DE_NULL, // const void* pNext;
696 0u, // VkPipelineCreateFlags flags;
697 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
698 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
699 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
700 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
701 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
702 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
703 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
704 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
705 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
706 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
707 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
708 pipelineLayout, // VkPipelineLayout layout;
709 renderPass, // VkRenderPass renderPass;
710 subpass, // deUint32 subpass;
711 DE_NULL, // VkPipeline basePipelineHandle;
712 0, // deInt32 basePipelineIndex;
713 };
714
715 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
716 }
717
makeComputePipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkShaderModule shaderModule,const VkSpecializationInfo * specInfo)718 Move<VkPipeline> makeComputePipeline (const DeviceInterface& vk,
719 const VkDevice device,
720 const VkPipelineLayout pipelineLayout,
721 const VkShaderModule shaderModule,
722 const VkSpecializationInfo* specInfo)
723 {
724 const VkPipelineShaderStageCreateInfo shaderStageInfo =
725 {
726 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
727 DE_NULL, // const void* pNext;
728 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
729 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
730 shaderModule, // VkShaderModule module;
731 "main", // const char* pName;
732 specInfo, // const VkSpecializationInfo* pSpecializationInfo;
733 };
734 const VkComputePipelineCreateInfo pipelineInfo =
735 {
736 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
737 DE_NULL, // const void* pNext;
738 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
739 shaderStageInfo, // VkPipelineShaderStageCreateInfo stage;
740 pipelineLayout, // VkPipelineLayout layout;
741 DE_NULL, // VkPipeline basePipelineHandle;
742 0, // deInt32 basePipelineIndex;
743 };
744 return createComputePipeline(vk, device, DE_NULL , &pipelineInfo);
745 }
746
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const deUint32 numLayers)747 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
748 const VkDevice device,
749 const VkFormat colorFormat,
750 const deUint32 numLayers)
751 {
752 const VkAttachmentDescription colorAttachmentDescription =
753 {
754 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
755 colorFormat, // VkFormat format;
756 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
757 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
758 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
759 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
760 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
761 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
762 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
763 };
764 vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
765
766 // Create a subpass for each attachment (each attachement is a layer of an arrayed image).
767 vector<VkAttachmentReference> colorAttachmentReferences (numLayers);
768 vector<VkSubpassDescription> subpasses;
769
770 // Ordering here must match the framebuffer attachments
771 for (deUint32 i = 0; i < numLayers; ++i)
772 {
773 const VkAttachmentReference attachmentRef =
774 {
775 i, // deUint32 attachment;
776 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
777 };
778
779 colorAttachmentReferences[i] = attachmentRef;
780
781 const VkSubpassDescription subpassDescription =
782 {
783 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
784 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
785 0u, // deUint32 inputAttachmentCount;
786 DE_NULL, // const VkAttachmentReference* pInputAttachments;
787 1u, // deUint32 colorAttachmentCount;
788 &colorAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments;
789 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
790 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
791 0u, // deUint32 preserveAttachmentCount;
792 DE_NULL // const deUint32* pPreserveAttachments;
793 };
794 subpasses.push_back(subpassDescription);
795 }
796
797 const VkRenderPassCreateInfo renderPassInfo =
798 {
799 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
800 DE_NULL, // const void* pNext;
801 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
802 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount;
803 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
804 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
805 &subpasses[0], // const VkSubpassDescription* pSubpasses;
806 0u, // deUint32 dependencyCount;
807 DE_NULL // const VkSubpassDependency* pDependencies;
808 };
809
810 return createRenderPass(vk, device, &renderPassInfo);
811 }
812
makeFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass,const deUint32 attachmentCount,const VkImageView * pAttachments,const IVec2 size)813 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface& vk,
814 const VkDevice device,
815 const VkRenderPass renderPass,
816 const deUint32 attachmentCount,
817 const VkImageView* pAttachments,
818 const IVec2 size)
819 {
820 const VkFramebufferCreateInfo framebufferInfo =
821 {
822 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
823 DE_NULL,
824 (VkFramebufferCreateFlags)0,
825 renderPass,
826 attachmentCount,
827 pAttachments,
828 static_cast<deUint32>(size.x()),
829 static_cast<deUint32>(size.y()),
830 1u,
831 };
832
833 return createFramebuffer(vk, device, &framebufferInfo);
834 }
835
makeCommandBuffer(const DeviceInterface & vk,const VkDevice device,const VkCommandPool commandPool)836 Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
837 {
838 return allocateCommandBuffer(vk, device, commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
839 }
840
bindImage(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const VkImage image,const MemoryRequirement requirement)841 MovePtr<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement)
842 {
843 MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement);
844 VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset()));
845 return alloc;
846 }
847
bindBuffer(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const VkBuffer buffer,const MemoryRequirement requirement)848 MovePtr<Allocation> bindBuffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBuffer buffer, const MemoryRequirement requirement)
849 {
850 MovePtr<Allocation> alloc(allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), requirement));
851 VK_CHECK(vk.bindBufferMemory(device, buffer, alloc->getMemory(), alloc->getOffset()));
852 return alloc;
853 }
854
genVertexData(const CaseDef & caseDef)855 vector<Vec4> genVertexData (const CaseDef& caseDef)
856 {
857 vector<Vec4> vectorData;
858 const bool isIntegerFormat = isUintFormat(caseDef.viewFormat) || isIntFormat(caseDef.viewFormat);
859
860 for (deUint32 z = 0; z < caseDef.numLayers; z++)
861 {
862 const deUint32 colorIdx = z % COLOR_TABLE_SIZE;
863 const Vec4 color = isIntegerFormat ? COLOR_TABLE_INT[colorIdx].cast<float>() : COLOR_TABLE_FLOAT[colorIdx];
864
865 vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
866 vectorData.push_back(color);
867 vectorData.push_back(Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
868 vectorData.push_back(color);
869 vectorData.push_back(Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
870 vectorData.push_back(color);
871 vectorData.push_back(Vec4( 1.0f, 1.0f, 0.0f, 1.0f));
872 vectorData.push_back(color);
873 }
874
875 return vectorData;
876 }
877
generateExpectedImage(const tcu::PixelBufferAccess & image,const CaseDef & caseDef)878 void generateExpectedImage(const tcu::PixelBufferAccess& image, const CaseDef& caseDef)
879 {
880 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(image.getFormat().type);
881 const bool isIntegerFormat = channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
882 const IVec2 size = caseDef.size.swizzle(0, 1);
883
884 for (int z = 0; z < static_cast<int>(caseDef.numLayers); z++)
885 {
886 const deUint32 colorIdx = z % COLOR_TABLE_SIZE;
887 for (int y = 0; y < size.y(); y++)
888 for (int x = 0; x < size.x(); x++)
889 {
890 if (isIntegerFormat)
891 image.setPixel(COLOR_TABLE_INT[colorIdx], x, y, z);
892 else
893 image.setPixel(COLOR_TABLE_FLOAT[colorIdx], x, y, z);
894 }
895 }
896 }
897
getImageUsageForTestCase(const CaseDef & caseDef)898 VkImageUsageFlags getImageUsageForTestCase (const CaseDef& caseDef)
899 {
900 VkImageUsageFlags flags = 0u;
901
902 switch (caseDef.upload)
903 {
904 case UPLOAD_CLEAR:
905 flags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
906 break;
907 case UPLOAD_DRAW:
908 flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
909 break;
910 case UPLOAD_STORE:
911 flags |= VK_IMAGE_USAGE_STORAGE_BIT;
912 break;
913 case UPLOAD_COPY:
914 flags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
915 break;
916 default:
917 DE_ASSERT("Invalid upload method");
918 break;
919 }
920
921 switch (caseDef.download)
922 {
923 case DOWNLOAD_TEXTURE:
924 flags |= VK_IMAGE_USAGE_SAMPLED_BIT;
925 break;
926 case DOWNLOAD_LOAD:
927 flags |= VK_IMAGE_USAGE_STORAGE_BIT;
928 break;
929 case DOWNLOAD_COPY:
930 flags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
931 break;
932 default:
933 DE_ASSERT("Invalid download method");
934 break;
935 }
936
937 // We can only create a view for the image if it is going to be used for any of these usages,
938 // so let's make sure that we have at least one of them.
939 VkImageUsageFlags viewRequiredFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
940 if (!(flags & viewRequiredFlags))
941 flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
942
943 return flags;
944 }
945
946 // Executes a combination of upload/download methods
947 class UploadDownloadExecutor
948 {
949 public:
UploadDownloadExecutor(Context & context,const CaseDef & caseSpec)950 UploadDownloadExecutor(Context &context, const CaseDef& caseSpec) :
951 m_caseDef(caseSpec),
952 m_haveMaintenance2(de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance2")),
953 m_vk(context.getDeviceInterface()),
954 m_device(context.getDevice()),
955 m_queue(context.getUniversalQueue()),
956 m_queueFamilyIndex(context.getUniversalQueueFamilyIndex()),
957 m_allocator(context.getDefaultAllocator())
958 {
959 }
960
961 void run(Context& context, VkBuffer buffer);
962
963 private:
964 void uploadClear(Context& context);
965 void uploadStore(Context& context);
966 void uploadCopy(Context& context);
967 void uploadDraw(Context& context);
968 void downloadCopy(Context& context, VkBuffer buffer);
969 void downloadTexture(Context& context, VkBuffer buffer);
970 void downloadLoad(Context& context, VkBuffer buffer);
971
972 void copyImageToBuffer(VkImage image,
973 VkBuffer buffer,
974 const IVec3 size,
975 const VkAccessFlags srcAccessMask,
976 const VkImageLayout oldLayout,
977 const deUint32 numLayers);
978
979 const CaseDef& m_caseDef;
980
981 bool m_haveMaintenance2;
982
983 const DeviceInterface& m_vk;
984 const VkDevice m_device;
985 const VkQueue m_queue;
986 const deUint32 m_queueFamilyIndex;
987 Allocator& m_allocator;
988
989 Move<VkCommandPool> m_cmdPool;
990 Move<VkCommandBuffer> m_cmdBuffer;
991
992 bool m_imageIsIntegerFormat;
993 bool m_viewIsIntegerFormat;
994
995 // Target image for upload paths
996 Move<VkImage> m_image;
997 MovePtr<Allocation> m_imageAlloc;
998
999 // Upload copy
1000 struct
1001 {
1002 Move<VkBuffer> colorBuffer;
1003 VkDeviceSize colorBufferSize;
1004 MovePtr<Allocation> colorBufferAlloc;
1005 } m_uCopy;
1006
1007 // Upload draw
1008 struct
1009 {
1010 Move<VkBuffer> vertexBuffer;
1011 MovePtr<Allocation> vertexBufferAlloc;
1012 Move<VkPipelineLayout> pipelineLayout;
1013 Move<VkRenderPass> renderPass;
1014 Move<VkShaderModule> vertexModule;
1015 Move<VkShaderModule> fragmentModule;
1016 vector<SharedPtrVkImageView> attachments;
1017 vector<VkImageView> attachmentHandles;
1018 vector<SharedPtrVkPipeline> pipelines;
1019 Move<VkFramebuffer> framebuffer;
1020 } m_uDraw;
1021
1022 // Upload store
1023 struct
1024 {
1025 Move<VkDescriptorPool> descriptorPool;
1026 Move<VkPipelineLayout> pipelineLayout;
1027 Move<VkDescriptorSetLayout> descriptorSetLayout;
1028 Move<VkDescriptorSet> descriptorSet;
1029 VkDescriptorImageInfo imageDescriptorInfo;
1030 Move<VkShaderModule> computeModule;
1031 Move<VkPipeline> computePipeline;
1032 Move<VkImageView> imageView;
1033 } m_uStore;
1034
1035 // Download load
1036 struct
1037 {
1038 Move<VkDescriptorPool> descriptorPool;
1039 Move<VkPipelineLayout> pipelineLayout;
1040 Move<VkDescriptorSetLayout> descriptorSetLayout;
1041 Move<VkDescriptorSet> descriptorSet;
1042 Move<VkShaderModule> computeModule;
1043 Move<VkPipeline> computePipeline;
1044 Move<VkImageView> inImageView;
1045 VkDescriptorImageInfo inImageDescriptorInfo;
1046 Move<VkImage> outImage;
1047 Move<VkImageView> outImageView;
1048 MovePtr<Allocation> outImageAlloc;
1049 VkDescriptorImageInfo outImageDescriptorInfo;
1050 } m_dLoad;
1051
1052 // Download texture
1053 struct
1054 {
1055 Move<VkDescriptorPool> descriptorPool;
1056 Move<VkPipelineLayout> pipelineLayout;
1057 Move<VkDescriptorSetLayout> descriptorSetLayout;
1058 Move<VkDescriptorSet> descriptorSet;
1059 Move<VkShaderModule> computeModule;
1060 Move<VkPipeline> computePipeline;
1061 Move<VkImageView> inImageView;
1062 VkDescriptorImageInfo inImageDescriptorInfo;
1063 Move<VkSampler> sampler;
1064 Move<VkImage> outImage;
1065 Move<VkImageView> outImageView;
1066 MovePtr<Allocation> outImageAlloc;
1067 VkDescriptorImageInfo outImageDescriptorInfo;
1068 } m_dTex;
1069
1070 VkImageLayout m_imageLayoutAfterUpload;
1071 VkAccessFlagBits m_imageUploadAccessMask;
1072 };
1073
run(Context & context,VkBuffer buffer)1074 void UploadDownloadExecutor::run(Context& context, VkBuffer buffer)
1075 {
1076 m_imageIsIntegerFormat = isUintFormat(m_caseDef.imageFormat) || isIntFormat(m_caseDef.imageFormat);
1077 m_viewIsIntegerFormat = isUintFormat(m_caseDef.viewFormat) || isIntFormat(m_caseDef.viewFormat);
1078
1079 m_cmdPool = createCommandPool(m_vk, m_device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_queueFamilyIndex);
1080 m_cmdBuffer = makeCommandBuffer(m_vk, m_device, *m_cmdPool);
1081 beginCommandBuffer(m_vk, *m_cmdBuffer);
1082
1083 const VkImageUsageFlags imageUsage = getImageUsageForTestCase(m_caseDef);
1084 const VkImageCreateFlags imageFlags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | (m_haveMaintenance2 ? VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR : 0);
1085 m_image = makeImage(m_vk, m_device, imageFlags, getImageType(m_caseDef.imageType), m_caseDef.imageFormat, m_caseDef.viewFormat,
1086 m_caseDef.isFormatListTest, m_caseDef.size, 1u, m_caseDef.numLayers, imageUsage);
1087 m_imageAlloc = bindImage(m_vk, m_device, m_allocator, *m_image, MemoryRequirement::Any);
1088
1089 switch (m_caseDef.upload)
1090 {
1091 case UPLOAD_DRAW:
1092 uploadDraw(context);
1093 break;
1094 case UPLOAD_STORE:
1095 uploadStore(context);
1096 break;
1097 case UPLOAD_CLEAR:
1098 uploadClear(context);
1099 break;
1100 case UPLOAD_COPY:
1101 uploadCopy(context);
1102 break;
1103 default:
1104 DE_ASSERT("Unsupported upload method");
1105 }
1106
1107 switch (m_caseDef.download)
1108 {
1109 case DOWNLOAD_COPY:
1110 downloadCopy(context, buffer);
1111 break;
1112 case DOWNLOAD_LOAD:
1113 downloadLoad(context, buffer);
1114 break;
1115 case DOWNLOAD_TEXTURE:
1116 downloadTexture(context, buffer);
1117 break;
1118 default:
1119 DE_ASSERT("Unsupported download method");
1120 }
1121
1122 VK_CHECK(m_vk.endCommandBuffer(*m_cmdBuffer));
1123 submitCommandsAndWait(m_vk, m_device, m_queue, *m_cmdBuffer);
1124 }
1125
uploadClear(Context & context)1126 void UploadDownloadExecutor::uploadClear(Context& context)
1127 {
1128 (void) context;
1129
1130 VkImageLayout requiredImageLayout = VK_IMAGE_LAYOUT_GENERAL;
1131
1132 const VkImageSubresourceRange subresourceRange = makeColorSubresourceRange(0, m_caseDef.numLayers);
1133 const VkImageMemoryBarrier imageInitBarrier =
1134 {
1135 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1136 DE_NULL, // const void* pNext;
1137 0u, // VkAccessFlags srcAccessMask;
1138 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAcessMask;
1139 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1140 requiredImageLayout, // VkImageLayout newLayout;
1141 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1142 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1143 *m_image, // VkImage image;
1144 subresourceRange // VkImageSubresourceRange subresourceRange;
1145 };
1146
1147 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1148 0u, DE_NULL, 0u, DE_NULL, 1u, &imageInitBarrier);
1149
1150 for (deUint32 layer = 0; layer < m_caseDef.numLayers; layer++)
1151 {
1152 const VkImageSubresourceRange layerSubresourceRange = makeColorSubresourceRange(layer, 1u);
1153 const deUint32 colorIdx = layer % COLOR_TABLE_SIZE;
1154 const VkClearColorValue clearColor = m_imageIsIntegerFormat ? REFERENCE_CLEAR_COLOR_INT[colorIdx].color : REFERENCE_CLEAR_COLOR_FLOAT[colorIdx].color;
1155 m_vk.cmdClearColorImage(*m_cmdBuffer, *m_image, requiredImageLayout, &clearColor, 1u, &layerSubresourceRange);
1156 }
1157
1158 m_imageLayoutAfterUpload = requiredImageLayout;
1159 m_imageUploadAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1160 }
1161
uploadStore(Context & context)1162 void UploadDownloadExecutor::uploadStore(Context& context)
1163 {
1164 const vk::VkImageViewUsageCreateInfoKHR viewUsageCreateInfo = {
1165 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR, // VkStructureType sType
1166 DE_NULL, // const void* pNext
1167 VK_IMAGE_USAGE_STORAGE_BIT, // VkImageUsageFlags usage;
1168 };
1169 m_uStore.imageView = makeImageView(m_vk, m_device, *m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1170 makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1171
1172 // Setup compute pipeline
1173 m_uStore.descriptorPool = DescriptorPoolBuilder()
1174 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1175 .build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1176
1177 m_uStore.descriptorSetLayout = DescriptorSetLayoutBuilder()
1178 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1179 .build(m_vk, m_device);
1180
1181 m_uStore.pipelineLayout = makePipelineLayout(m_vk, m_device, *m_uStore.descriptorSetLayout);
1182 m_uStore.descriptorSet = makeDescriptorSet(m_vk, m_device, *m_uStore.descriptorPool, *m_uStore.descriptorSetLayout);
1183 m_uStore.imageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *m_uStore.imageView, VK_IMAGE_LAYOUT_GENERAL);
1184 m_uStore.computeModule = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadStoreComp"), 0);
1185 m_uStore.computePipeline = makeComputePipeline(m_vk, m_device, *m_uStore.pipelineLayout, *m_uStore.computeModule, DE_NULL);
1186
1187 DescriptorSetUpdateBuilder()
1188 .writeSingle(*m_uStore.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_uStore.imageDescriptorInfo)
1189 .update(m_vk, m_device);
1190
1191 // Transition storage image for shader access (imageStore)
1192 VkImageLayout requiredImageLayout = VK_IMAGE_LAYOUT_GENERAL;
1193 const VkImageMemoryBarrier imageBarrier =
1194 {
1195 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1196 DE_NULL, // const void* pNext;
1197 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1198 (VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1199 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1200 requiredImageLayout, // VkImageLayout newLayout;
1201 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1202 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1203 *m_image, // VkImage image;
1204 makeColorSubresourceRange(0, m_caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1205 };
1206
1207 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1208 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1209
1210 // Dispatch
1211 m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_uStore.computePipeline);
1212 m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_uStore.pipelineLayout, 0u, 1u, &m_uStore.descriptorSet.get(), 0u, DE_NULL);
1213 m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1214
1215 m_imageLayoutAfterUpload = requiredImageLayout;
1216 m_imageUploadAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1217 }
1218
uploadCopy(Context & context)1219 void UploadDownloadExecutor::uploadCopy(Context& context)
1220 {
1221 (void) context;
1222
1223 // Create a host-mappable buffer with the color data to upload
1224 const VkDeviceSize pixelSize = tcu::getPixelSize(mapVkFormat(m_caseDef.imageFormat));
1225 const VkDeviceSize layerSize = m_caseDef.size.x() * m_caseDef.size.y() * m_caseDef.size.z() * pixelSize;
1226
1227 m_uCopy.colorBufferSize = layerSize * m_caseDef.numLayers;
1228 m_uCopy.colorBuffer = makeBuffer(m_vk, m_device, m_uCopy.colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
1229 m_uCopy.colorBufferAlloc = bindBuffer(m_vk, m_device, m_allocator, *m_uCopy.colorBuffer, MemoryRequirement::HostVisible);
1230
1231 // Fill color buffer
1232 const tcu::TextureFormat tcuFormat = mapVkFormat(m_caseDef.imageFormat);
1233 VkDeviceSize layerOffset = 0ull;
1234 for (deUint32 layer = 0; layer < m_caseDef.numLayers; layer++)
1235 {
1236 tcu::PixelBufferAccess imageAccess = tcu::PixelBufferAccess(tcuFormat, m_caseDef.size.x(), m_caseDef.size.y(), 1u, (deUint8*) m_uCopy.colorBufferAlloc->getHostPtr() + layerOffset);
1237 const deUint32 colorIdx = layer % COLOR_TABLE_SIZE;
1238 if (m_imageIsIntegerFormat)
1239 tcu::clear(imageAccess, COLOR_TABLE_INT[colorIdx]);
1240 else
1241 tcu::clear(imageAccess, COLOR_TABLE_FLOAT[colorIdx]);
1242 layerOffset += layerSize;
1243 }
1244
1245 flushMappedMemoryRange(m_vk, m_device, m_uCopy.colorBufferAlloc->getMemory(), m_uCopy.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1246
1247 // Prepare buffer and image for copy
1248 const VkBufferMemoryBarrier bufferInitBarrier =
1249 {
1250 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1251 DE_NULL, // const void* pNext;
1252 VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask;
1253 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1254 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1255 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1256 *m_uCopy.colorBuffer, // VkBuffer buffer;
1257 0ull, // VkDeviceSize offset;
1258 VK_WHOLE_SIZE, // VkDeviceSize size;
1259 };
1260
1261 const VkImageMemoryBarrier imageInitBarrier =
1262 {
1263 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1264 DE_NULL, // const void* pNext;
1265 0u, // VkAccessFlags outputMask;
1266 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags inputMask;
1267 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1268 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
1269 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1270 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1271 *m_image, // VkImage image;
1272 makeColorSubresourceRange(0, m_caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
1273 };
1274
1275 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1276 0u, DE_NULL, 1u, &bufferInitBarrier, 1u, &imageInitBarrier);
1277
1278 // Copy buffer to image
1279 const VkImageSubresourceLayers subresource =
1280 {
1281 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1282 0u, // deUint32 mipLevel;
1283 0u, // deUint32 baseArrayLayer;
1284 m_caseDef.numLayers, // deUint32 layerCount;
1285 };
1286
1287 const VkBufferImageCopy region =
1288 {
1289 0ull, // VkDeviceSize bufferOffset;
1290 0u, // deUint32 bufferRowLength;
1291 0u, // deUint32 bufferImageHeight;
1292 subresource, // VkImageSubresourceLayers imageSubresource;
1293 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1294 makeExtent3D(m_caseDef.size), // VkExtent3D imageExtent;
1295 };
1296
1297 m_vk.cmdCopyBufferToImage(*m_cmdBuffer, *m_uCopy.colorBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ®ion);
1298
1299 const VkImageMemoryBarrier imagePostInitBarrier =
1300 {
1301 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1302 DE_NULL, // const void* pNext;
1303 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags outputMask;
1304 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
1305 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
1306 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
1307 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1308 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1309 *m_image, // VkImage image;
1310 makeColorSubresourceRange(0, m_caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
1311 };
1312
1313 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1314 0u, DE_NULL, 0u, DE_NULL, 1u, &imagePostInitBarrier);
1315
1316 m_imageLayoutAfterUpload = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
1317 m_imageUploadAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1318 }
1319
uploadDraw(Context & context)1320 void UploadDownloadExecutor::uploadDraw(Context& context)
1321 {
1322 // Create vertex buffer
1323 {
1324 const vector<Vec4> vertices = genVertexData(m_caseDef);
1325 const VkDeviceSize vertexBufferSize = vertices.size() * sizeof(Vec4);
1326
1327 m_uDraw.vertexBuffer = makeBuffer(m_vk, m_device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1328 m_uDraw.vertexBufferAlloc = bindBuffer(m_vk, m_device, m_allocator, *m_uDraw.vertexBuffer, MemoryRequirement::HostVisible);
1329 deMemcpy(m_uDraw.vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1330 flushMappedMemoryRange(m_vk, m_device, m_uDraw.vertexBufferAlloc->getMemory(), m_uDraw.vertexBufferAlloc->getOffset(), vertexBufferSize);
1331 }
1332
1333 // Create attachments and pipelines for each image layer
1334 m_uDraw.pipelineLayout = makePipelineLayout(m_vk, m_device);
1335 m_uDraw.renderPass = makeRenderPass(m_vk, m_device, m_caseDef.viewFormat, m_caseDef.numLayers);
1336 m_uDraw.vertexModule = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadDrawVert"), 0u);
1337 m_uDraw.fragmentModule = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadDrawFrag"), 0u);
1338
1339 for (deUint32 subpassNdx = 0; subpassNdx < m_caseDef.numLayers; ++subpassNdx)
1340 {
1341 const vk::VkImageViewUsageCreateInfoKHR viewUsageCreateInfo = {
1342 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR, // VkStructureType sType
1343 DE_NULL, // const void* pNext
1344 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags usage;
1345 };
1346 Move<VkImageView> imageView = makeImageView(m_vk, m_device, *m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1347 makeColorSubresourceRange(subpassNdx, 1), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1348 m_uDraw.attachmentHandles.push_back(*imageView);
1349 m_uDraw.attachments.push_back(makeSharedPtr(imageView));
1350 m_uDraw.pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(m_vk, m_device, *m_uDraw.pipelineLayout, *m_uDraw.renderPass, *m_uDraw.vertexModule, *m_uDraw.fragmentModule,
1351 m_caseDef.size.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, subpassNdx)));
1352 }
1353
1354 // Create framebuffer
1355 m_uDraw.framebuffer = makeFramebuffer(m_vk, m_device, *m_uDraw.renderPass, static_cast<deUint32>(m_uDraw.attachmentHandles.size()), &m_uDraw.attachmentHandles[0], m_caseDef.size.swizzle(0, 1));
1356
1357 // Create command buffer
1358 {
1359 {
1360 vector<VkClearValue> clearValues (m_caseDef.numLayers, m_viewIsIntegerFormat ? REFERENCE_CLEAR_COLOR_INT[0] : REFERENCE_CLEAR_COLOR_FLOAT[0]);
1361
1362 const VkRect2D renderArea =
1363 {
1364 makeOffset2D(0, 0),
1365 makeExtent2D(m_caseDef.size.x(), m_caseDef.size.y()),
1366 };
1367
1368 const VkRenderPassBeginInfo renderPassBeginInfo =
1369 {
1370 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1371 DE_NULL, // const void* pNext;
1372 *m_uDraw.renderPass, // VkRenderPass renderPass;
1373 *m_uDraw.framebuffer, // VkFramebuffer framebuffer;
1374 renderArea, // VkRect2D renderArea;
1375 static_cast<deUint32>(clearValues.size()), // deUint32 clearValueCount;
1376 &clearValues[0], // const VkClearValue* pClearValues;
1377 };
1378
1379 m_vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1380 }
1381
1382 // Render
1383 const VkDeviceSize vertexDataPerDraw = 4 * 2 * sizeof(Vec4);
1384 VkDeviceSize vertexBufferOffset = 0ull;
1385 for (deUint32 subpassNdx = 0; subpassNdx < m_caseDef.numLayers; ++subpassNdx)
1386 {
1387 if (subpassNdx != 0)
1388 m_vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1389
1390 m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_uDraw.pipelines[subpassNdx]);
1391
1392 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_uDraw.vertexBuffer.get(), &vertexBufferOffset);
1393 m_vk.cmdDraw(*m_cmdBuffer, 4u, 1u, 0u, 0u);
1394 vertexBufferOffset += vertexDataPerDraw;
1395 }
1396
1397 m_vk.cmdEndRenderPass(*m_cmdBuffer);
1398 }
1399
1400 m_imageLayoutAfterUpload = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1401 m_imageUploadAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1402 }
1403
downloadCopy(Context & context,VkBuffer buffer)1404 void UploadDownloadExecutor::downloadCopy(Context& context, VkBuffer buffer)
1405 {
1406 (void) context;
1407
1408 copyImageToBuffer(*m_image, buffer, m_caseDef.size, m_imageUploadAccessMask, m_imageLayoutAfterUpload, m_caseDef.numLayers);
1409 }
1410
downloadTexture(Context & context,VkBuffer buffer)1411 void UploadDownloadExecutor::downloadTexture(Context& context, VkBuffer buffer)
1412 {
1413 // Create output image with download result
1414 const VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1415 m_dTex.outImage = makeImage(m_vk, m_device, 0u, VK_IMAGE_TYPE_2D, m_caseDef.viewFormat, m_caseDef.viewFormat, false, m_caseDef.size, 1u, m_caseDef.numLayers, usageFlags);
1416 m_dTex.outImageAlloc = bindImage(m_vk, m_device, m_allocator, *m_dTex.outImage, MemoryRequirement::Any);
1417 m_dTex.outImageView = makeImageView(m_vk, m_device, *m_dTex.outImage, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat, makeColorSubresourceRange(0, m_caseDef.numLayers));
1418
1419 const vk::VkImageViewUsageCreateInfoKHR viewUsageCreateInfo = {
1420 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR, // VkStructureType sType
1421 DE_NULL, // const void* pNext
1422 VK_IMAGE_USAGE_SAMPLED_BIT, // VkImageUsageFlags usage;
1423 };
1424 m_dTex.inImageView = makeImageView(m_vk, m_device, *m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1425 makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1426 m_dTex.sampler = makeSampler(m_vk, m_device);
1427
1428 // Setup compute pipeline
1429 m_dTex.descriptorPool = DescriptorPoolBuilder()
1430 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1431 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1432 .build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1433
1434 m_dTex.descriptorSetLayout = DescriptorSetLayoutBuilder()
1435 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT, &m_dTex.sampler.get())
1436 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1437 .build(m_vk, m_device);
1438
1439 m_dTex.pipelineLayout = makePipelineLayout(m_vk, m_device, *m_dTex.descriptorSetLayout);
1440 m_dTex.descriptorSet = makeDescriptorSet(m_vk, m_device, *m_dTex.descriptorPool, *m_dTex.descriptorSetLayout);
1441 m_dTex.inImageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *m_dTex.inImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1442 m_dTex.outImageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *m_dTex.outImageView, VK_IMAGE_LAYOUT_GENERAL);
1443 m_dTex.computeModule = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("downloadTextureComp"), 0);
1444 m_dTex.computePipeline = makeComputePipeline(m_vk, m_device, *m_dTex.pipelineLayout, *m_dTex.computeModule, DE_NULL);
1445
1446 DescriptorSetUpdateBuilder()
1447 .writeSingle(*m_dTex.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &m_dTex.inImageDescriptorInfo)
1448 .writeSingle(*m_dTex.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dTex.outImageDescriptorInfo)
1449 .update(m_vk, m_device);
1450
1451 // Transition images for shader access (texture / imageStore)
1452 const VkImageMemoryBarrier imageBarriers[] =
1453 {
1454 {
1455 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1456 DE_NULL, // const void* pNext;
1457 (VkAccessFlags)m_imageUploadAccessMask, // VkAccessFlags srcAccessMask;
1458 (VkAccessFlags)VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
1459 m_imageLayoutAfterUpload, // VkImageLayout oldLayout;
1460 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout;
1461 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1462 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1463 *m_image, // VkImage image;
1464 makeColorSubresourceRange(0, m_caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1465 },
1466 {
1467 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1468 DE_NULL, // const void* pNext;
1469 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1470 (VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1471 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1472 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
1473 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1474 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1475 *m_dTex.outImage, // VkImage image;
1476 makeColorSubresourceRange(0, m_caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1477 }
1478 };
1479
1480 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1481 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1482
1483 // Dispatch
1484 m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dTex.computePipeline);
1485 m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dTex.pipelineLayout, 0u, 1u, &m_dTex.descriptorSet.get(), 0u, DE_NULL);
1486 m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1487
1488 // Copy output image to color buffer
1489 copyImageToBuffer(*m_dTex.outImage, buffer, m_caseDef.size, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, m_caseDef.numLayers);
1490 }
1491
downloadLoad(Context & context,VkBuffer buffer)1492 void UploadDownloadExecutor::downloadLoad(Context& context, VkBuffer buffer)
1493 {
1494 // Create output image with download result
1495 const VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1496 m_dLoad.outImage = makeImage(m_vk, m_device, 0u, VK_IMAGE_TYPE_2D, m_caseDef.viewFormat, m_caseDef.viewFormat, false, m_caseDef.size, 1u, m_caseDef.numLayers, usageFlags);
1497 m_dLoad.outImageAlloc = bindImage(m_vk, m_device, m_allocator, *m_dLoad.outImage, MemoryRequirement::Any);
1498 m_dLoad.outImageView = makeImageView(m_vk, m_device, *m_dLoad.outImage, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat, makeColorSubresourceRange(0, m_caseDef.numLayers));
1499
1500 const vk::VkImageViewUsageCreateInfoKHR viewUsageCreateInfo = {
1501 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR, // VkStructureType sType
1502 DE_NULL, // const void* pNext
1503 VK_IMAGE_USAGE_STORAGE_BIT, // VkImageUsageFlags usage;
1504 };
1505 m_dLoad.inImageView = makeImageView(m_vk, m_device, *m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1506 makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1507
1508 // Setup compute pipeline
1509 m_dLoad.descriptorPool = DescriptorPoolBuilder()
1510 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u)
1511 .build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1512
1513 m_dLoad.descriptorSetLayout = DescriptorSetLayoutBuilder()
1514 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1515 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1516 .build(m_vk, m_device);
1517
1518 m_dLoad.pipelineLayout = makePipelineLayout(m_vk, m_device, *m_dLoad.descriptorSetLayout);
1519 m_dLoad.descriptorSet = makeDescriptorSet(m_vk, m_device, *m_dLoad.descriptorPool, *m_dLoad.descriptorSetLayout);
1520 m_dLoad.inImageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *m_dLoad.inImageView, VK_IMAGE_LAYOUT_GENERAL);
1521 m_dLoad.outImageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *m_dLoad.outImageView, VK_IMAGE_LAYOUT_GENERAL);
1522 m_dLoad.computeModule = createShaderModule(m_vk, m_device, context.getBinaryCollection().get("downloadLoadComp"), 0);
1523 m_dLoad.computePipeline = makeComputePipeline(m_vk, m_device, *m_dLoad.pipelineLayout, *m_dLoad.computeModule, DE_NULL);
1524
1525 DescriptorSetUpdateBuilder()
1526 .writeSingle(*m_dLoad.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dLoad.inImageDescriptorInfo)
1527 .writeSingle(*m_dLoad.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dLoad.outImageDescriptorInfo)
1528 .update(m_vk, m_device);
1529
1530 // Transition storage images for shader access (imageLoad/Store)
1531 VkImageLayout requiredImageLayout = VK_IMAGE_LAYOUT_GENERAL;
1532 const VkImageMemoryBarrier imageBarriers[] =
1533 {
1534 {
1535 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1536 DE_NULL, // const void* pNext;
1537 (VkAccessFlags)m_imageUploadAccessMask, // VkAccessFlags srcAccessMask;
1538 (VkAccessFlags)VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
1539 m_imageLayoutAfterUpload, // VkImageLayout oldLayout;
1540 requiredImageLayout, // VkImageLayout newLayout;
1541 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1542 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1543 *m_image, // VkImage image;
1544 makeColorSubresourceRange(0, m_caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1545 },
1546 {
1547 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1548 DE_NULL, // const void* pNext;
1549 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1550 (VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1551 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1552 requiredImageLayout, // VkImageLayout newLayout;
1553 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1554 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1555 *m_dLoad.outImage, // VkImage image;
1556 makeColorSubresourceRange(0, m_caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1557 }
1558 };
1559
1560 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1561 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1562
1563 // Dispatch
1564 m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dLoad.computePipeline);
1565 m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dLoad.pipelineLayout, 0u, 1u, &m_dLoad.descriptorSet.get(), 0u, DE_NULL);
1566 m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1567
1568 // Copy output image to color buffer
1569 copyImageToBuffer(*m_dLoad.outImage, buffer, m_caseDef.size, VK_ACCESS_SHADER_WRITE_BIT, requiredImageLayout, m_caseDef.numLayers);
1570 }
1571
copyImageToBuffer(VkImage sourceImage,VkBuffer buffer,const IVec3 size,const VkAccessFlags srcAccessMask,const VkImageLayout oldLayout,const deUint32 numLayers)1572 void UploadDownloadExecutor::copyImageToBuffer(VkImage sourceImage,
1573 VkBuffer buffer,
1574 const IVec3 size,
1575 const VkAccessFlags srcAccessMask,
1576 const VkImageLayout oldLayout,
1577 const deUint32 numLayers)
1578 {
1579 // Copy result to host visible buffer for inspection
1580 const VkImageMemoryBarrier imageBarrier =
1581 {
1582 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1583 DE_NULL, // const void* pNext;
1584 srcAccessMask, // VkAccessFlags outputMask;
1585 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
1586 oldLayout, // VkImageLayout oldLayout;
1587 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1588 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1589 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1590 sourceImage, // VkImage image;
1591 makeColorSubresourceRange(0, numLayers) // VkImageSubresourceRange subresourceRange;
1592 };
1593
1594 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1595 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1596
1597 const VkImageSubresourceLayers subresource =
1598 {
1599 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1600 0u, // deUint32 mipLevel;
1601 0u, // deUint32 baseArrayLayer;
1602 numLayers, // deUint32 layerCount;
1603 };
1604
1605 const VkBufferImageCopy region =
1606 {
1607 0ull, // VkDeviceSize bufferOffset;
1608 0u, // deUint32 bufferRowLength;
1609 0u, // deUint32 bufferImageHeight;
1610 subresource, // VkImageSubresourceLayers imageSubresource;
1611 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1612 makeExtent3D(size), // VkExtent3D imageExtent;
1613 };
1614
1615 m_vk.cmdCopyImageToBuffer(*m_cmdBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, ®ion);
1616
1617 const VkBufferMemoryBarrier bufferBarrier =
1618 {
1619 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1620 DE_NULL, // const void* pNext;
1621 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1622 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1623 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1624 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1625 buffer, // VkBuffer buffer;
1626 0ull, // VkDeviceSize offset;
1627 VK_WHOLE_SIZE, // VkDeviceSize size;
1628 };
1629
1630 m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1631 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1632 }
1633
isStorageImageExtendedFormat(const VkFormat format)1634 bool isStorageImageExtendedFormat (const VkFormat format)
1635 {
1636 switch (format)
1637 {
1638 case VK_FORMAT_R32G32_SFLOAT:
1639 case VK_FORMAT_R32G32_SINT:
1640 case VK_FORMAT_R32G32_UINT:
1641 case VK_FORMAT_R16G16B16A16_UNORM:
1642 case VK_FORMAT_R16G16B16A16_SNORM:
1643 case VK_FORMAT_R16G16_SFLOAT:
1644 case VK_FORMAT_R16G16_UNORM:
1645 case VK_FORMAT_R16G16_SNORM:
1646 case VK_FORMAT_R16G16_SINT:
1647 case VK_FORMAT_R16G16_UINT:
1648 case VK_FORMAT_R16_SFLOAT:
1649 case VK_FORMAT_R16_UNORM:
1650 case VK_FORMAT_R16_SNORM:
1651 case VK_FORMAT_R16_SINT:
1652 case VK_FORMAT_R16_UINT:
1653 case VK_FORMAT_R8G8_UNORM:
1654 case VK_FORMAT_R8G8_SNORM:
1655 case VK_FORMAT_R8G8_SINT:
1656 case VK_FORMAT_R8G8_UINT:
1657 case VK_FORMAT_R8_UNORM:
1658 case VK_FORMAT_R8_SNORM:
1659 case VK_FORMAT_R8_SINT:
1660 case VK_FORMAT_R8_UINT:
1661 return true;
1662
1663 default:
1664 return false;
1665 }
1666 }
1667
testMutable(Context & context,const CaseDef caseDef)1668 tcu::TestStatus testMutable (Context& context, const CaseDef caseDef)
1669 {
1670 const DeviceInterface& vk = context.getDeviceInterface();
1671 const InstanceInterface& vki = context.getInstanceInterface();
1672 const VkDevice device = context.getDevice();
1673 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1674 Allocator& allocator = context.getDefaultAllocator();
1675
1676 // If this is a VK_KHR_image_format_list test, check that the extension is supported
1677 if (caseDef.isFormatListTest && !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_image_format_list"))
1678 TCU_THROW(NotSupportedError, "VK_KHR_image_format_list not supported");
1679
1680 // Check required features on the format for the required upload/download methods
1681 VkFormatProperties imageFormatProps, viewFormatProps;
1682 vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.imageFormat, &imageFormatProps);
1683 vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.viewFormat, &viewFormatProps);
1684
1685 VkFormatFeatureFlags viewFormatFeatureFlags = 0u;
1686 switch (caseDef.upload)
1687 {
1688 case UPLOAD_DRAW:
1689 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
1690 break;
1691 case UPLOAD_STORE:
1692 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1693 break;
1694 default:
1695 DE_ASSERT("Invalid upload method");
1696 break;
1697 }
1698 switch (caseDef.download)
1699 {
1700 case DOWNLOAD_TEXTURE:
1701 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
1702 // For the texture case we write the samples read to a separate output image with the same view format
1703 // so we need to check that we can also use the view format for storage
1704 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1705 break;
1706 case DOWNLOAD_LOAD:
1707 viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1708 break;
1709 default:
1710 DE_ASSERT("Invalid download method");
1711 break;
1712 }
1713
1714 if ((viewFormatFeatureFlags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) &&
1715 isStorageImageExtendedFormat(caseDef.viewFormat) &&
1716 !getPhysicalDeviceFeatures(vki, physDevice).shaderStorageImageExtendedFormats)
1717 {
1718 TCU_THROW(NotSupportedError, "View format requires shaderStorageImageExtended");
1719 }
1720
1721 if ((viewFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags)
1722 TCU_THROW(NotSupportedError, "View format doesn't support upload/download method");
1723
1724 // We don't use the base image for anything other than transfer
1725 // operations so there are no features to check. However, The Vulkan
1726 // 1.0 spec does not allow us to create an image view with usage that
1727 // is not supported by the main format. With VK_KHR_maintenance2, we
1728 // can do this via VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR.
1729 if ((imageFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags &&
1730 !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance2"))
1731 {
1732 TCU_THROW(NotSupportedError, "Image format doesn't support upload/download method");
1733 }
1734
1735 // Create a color buffer for host-inspection of results
1736 // For the Copy download method, this is the target of the download, for other
1737 // download methods, pixel data will be copied to this buffer from the download
1738 // target
1739 const VkDeviceSize colorBufferSize = caseDef.size.x() * caseDef.size.y() * caseDef.size.z() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.imageFormat));
1740 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1741 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1742 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1743 flushMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1744
1745 // Execute the test
1746 UploadDownloadExecutor executor(context, caseDef);
1747 executor.run(context, *colorBuffer);
1748
1749 // Verify results
1750 {
1751 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1752
1753 // For verification purposes, we use the format of the upload to generate the expected image
1754 const VkFormat format = caseDef.upload == UPLOAD_CLEAR || caseDef.upload == UPLOAD_COPY ? caseDef.imageFormat : caseDef.viewFormat;
1755 const tcu::TextureFormat tcuFormat = mapVkFormat(format);
1756 const bool isIntegerFormat = isUintFormat(format) || isIntFormat(format);
1757 const tcu::ConstPixelBufferAccess resultImage (tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers, colorBufferAlloc->getHostPtr());
1758 tcu::TextureLevel textureLevel (tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers);
1759 const tcu::PixelBufferAccess expectedImage = textureLevel.getAccess();
1760 generateExpectedImage(expectedImage, caseDef);
1761
1762 bool ok;
1763 if (isIntegerFormat)
1764 ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1765 else
1766 ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1767 return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1768 }
1769 }
1770
createImageMutableTests(TestContext & testCtx)1771 tcu::TestCaseGroup* createImageMutableTests (TestContext& testCtx)
1772 {
1773 de::MovePtr<TestCaseGroup> testGroup (new TestCaseGroup(testCtx, "mutable", "Cases with mutable images"));
1774 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1775 {
1776 const Texture& texture = s_textures[textureNdx];
1777 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1778
1779 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
1780 for (int viewFormatNdx = 0; viewFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++viewFormatNdx)
1781 {
1782 if (imageFormatNdx != viewFormatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[viewFormatNdx]))
1783 {
1784 for (int upload = 0; upload < UPLOAD_LAST; upload++)
1785 for (int download = 0; download < DOWNLOAD_LAST; download++)
1786 {
1787 CaseDef caseDef =
1788 {
1789 texture.type(),
1790 texture.layerSize(),
1791 static_cast<deUint32>(texture.numLayers()),
1792 s_formats[imageFormatNdx],
1793 s_formats[viewFormatNdx],
1794 static_cast<enum Upload>(upload),
1795 static_cast<enum Download>(download),
1796 false
1797 };
1798
1799 std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[viewFormatNdx]) +
1800 "_" + getUploadString(upload) + "_" + getDownloadString(download);
1801 addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", initPrograms, testMutable, caseDef);
1802
1803 caseDef.isFormatListTest = true;
1804 caseName += "_format_list";
1805 addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", initPrograms, testMutable, caseDef);
1806 }
1807 }
1808 }
1809
1810 testGroup->addChild(groupByImageViewType.release());
1811 }
1812
1813 return testGroup.release();
1814 }
1815
1816 } // image
1817 } // vkt
1818