1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Imagination Technologies Ltd.
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Image sampling case
25 *//*--------------------------------------------------------------------*/
26
27 #include "vktPipelineImageSamplingInstance.hpp"
28 #include "vktPipelineClearUtil.hpp"
29 #include "vktPipelineReferenceRenderer.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkObjUtil.hpp"
39 #include "tcuTexLookupVerifier.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include "tcuTestLog.hpp"
42 #include "deSTLUtil.hpp"
43
44 namespace vkt
45 {
46 namespace pipeline
47 {
48
49 using namespace vk;
50 using de::MovePtr;
51 using de::UniquePtr;
52
53 namespace
54 {
allocateBuffer(const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice & physDevice,const VkDevice device,const VkBuffer & buffer,const MemoryRequirement requirement,Allocator & allocator,AllocationKind allocationKind)55 de::MovePtr<Allocation> allocateBuffer(const InstanceInterface &vki, const DeviceInterface &vkd,
56 const VkPhysicalDevice &physDevice, const VkDevice device,
57 const VkBuffer &buffer, const MemoryRequirement requirement,
58 Allocator &allocator, AllocationKind allocationKind)
59 {
60 switch (allocationKind)
61 {
62 case ALLOCATION_KIND_SUBALLOCATED:
63 {
64 const VkMemoryRequirements memoryRequirements = getBufferMemoryRequirements(vkd, device, buffer);
65
66 return allocator.allocate(memoryRequirements, requirement);
67 }
68
69 case ALLOCATION_KIND_DEDICATED:
70 {
71 return allocateDedicated(vki, vkd, physDevice, device, buffer, requirement);
72 }
73
74 default:
75 {
76 TCU_THROW(InternalError, "Invalid allocation kind");
77 }
78 }
79 }
80
allocateImage(const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice & physDevice,const VkDevice device,const VkImage & image,const MemoryRequirement requirement,Allocator & allocator,AllocationKind allocationKind)81 de::MovePtr<Allocation> allocateImage(const InstanceInterface &vki, const DeviceInterface &vkd,
82 const VkPhysicalDevice &physDevice, const VkDevice device, const VkImage &image,
83 const MemoryRequirement requirement, Allocator &allocator,
84 AllocationKind allocationKind)
85 {
86 switch (allocationKind)
87 {
88 case ALLOCATION_KIND_SUBALLOCATED:
89 {
90 const VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vkd, device, image);
91
92 return allocator.allocate(memoryRequirements, requirement);
93 }
94
95 case ALLOCATION_KIND_DEDICATED:
96 {
97 return allocateDedicated(vki, vkd, physDevice, device, image, requirement);
98 }
99
100 default:
101 {
102 TCU_THROW(InternalError, "Invalid allocation kind");
103 }
104 }
105 }
106
getCompatibleImageType(VkImageViewType viewType)107 static VkImageType getCompatibleImageType(VkImageViewType viewType)
108 {
109 switch (viewType)
110 {
111 case VK_IMAGE_VIEW_TYPE_1D:
112 return VK_IMAGE_TYPE_1D;
113 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
114 return VK_IMAGE_TYPE_1D;
115 case VK_IMAGE_VIEW_TYPE_2D:
116 return VK_IMAGE_TYPE_2D;
117 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
118 return VK_IMAGE_TYPE_2D;
119 case VK_IMAGE_VIEW_TYPE_3D:
120 return VK_IMAGE_TYPE_3D;
121 case VK_IMAGE_VIEW_TYPE_CUBE:
122 return VK_IMAGE_TYPE_2D;
123 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
124 return VK_IMAGE_TYPE_2D;
125 default:
126 break;
127 }
128
129 DE_ASSERT(false);
130 return VK_IMAGE_TYPE_1D;
131 }
132
133 template <typename TcuFormatType>
createTestTexture(const TcuFormatType format,VkImageViewType viewType,const tcu::IVec3 & size,int layerCount)134 static MovePtr<TestTexture> createTestTexture(const TcuFormatType format, VkImageViewType viewType,
135 const tcu::IVec3 &size, int layerCount)
136 {
137 MovePtr<TestTexture> texture;
138 const VkImageType imageType = getCompatibleImageType(viewType);
139
140 switch (imageType)
141 {
142 case VK_IMAGE_TYPE_1D:
143 if (layerCount == 1)
144 texture = MovePtr<TestTexture>(new TestTexture1D(format, size.x()));
145 else
146 texture = MovePtr<TestTexture>(new TestTexture1DArray(format, size.x(), layerCount));
147
148 break;
149
150 case VK_IMAGE_TYPE_2D:
151 if (layerCount == 1)
152 {
153 texture = MovePtr<TestTexture>(new TestTexture2D(format, size.x(), size.y()));
154 }
155 else
156 {
157 if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
158 {
159 if (layerCount == tcu::CUBEFACE_LAST && viewType == VK_IMAGE_VIEW_TYPE_CUBE)
160 {
161 texture = MovePtr<TestTexture>(new TestTextureCube(format, size.x()));
162 }
163 else
164 {
165 DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0);
166
167 texture = MovePtr<TestTexture>(new TestTextureCubeArray(format, size.x(), layerCount));
168 }
169 }
170 else
171 {
172 texture = MovePtr<TestTexture>(new TestTexture2DArray(format, size.x(), size.y(), layerCount));
173 }
174 }
175
176 break;
177
178 case VK_IMAGE_TYPE_3D:
179 texture = MovePtr<TestTexture>(new TestTexture3D(format, size.x(), size.y(), size.z()));
180 break;
181
182 default:
183 DE_ASSERT(false);
184 }
185
186 return texture;
187 }
188
189 } // namespace
190
checkSupportImageSamplingInstance(Context & context,ImageSamplingInstanceParams params)191 void checkSupportImageSamplingInstance(Context &context, ImageSamplingInstanceParams params)
192 {
193
194 const VkSamplerReductionModeCreateInfo *reductionModeInfo = NULL;
195 const VkSamplerYcbcrConversionInfo *ycbcrInfo = NULL;
196 const VkSamplerCustomBorderColorCreateInfoEXT *borderColorInfo = NULL;
197
198 for (const VkBaseInStructure *pNext = static_cast<const VkBaseInStructure *>(params.samplerParams.pNext);
199 pNext != NULL; pNext = pNext->pNext)
200 {
201 switch (pNext->sType)
202 {
203 case VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO:
204 reductionModeInfo = reinterpret_cast<const VkSamplerReductionModeCreateInfo *>(pNext);
205 break;
206 case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO:
207 ycbcrInfo = reinterpret_cast<const VkSamplerYcbcrConversionInfo *>(pNext);
208 break;
209 case VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT:
210 borderColorInfo = reinterpret_cast<const VkSamplerCustomBorderColorCreateInfoEXT *>(pNext);
211 break;
212 default:
213 TCU_FAIL("Unrecognized sType in chained sampler create info");
214 }
215 }
216
217 if (de::abs(params.samplerParams.mipLodBias) > context.getDeviceProperties().limits.maxSamplerLodBias)
218 TCU_THROW(NotSupportedError, "Unsupported sampler Lod bias value");
219
220 if (!isSupportedSamplableFormat(context.getInstanceInterface(), context.getPhysicalDevice(), params.imageFormat))
221 throw tcu::NotSupportedError(std::string("Unsupported format for sampling: ") +
222 getFormatName(params.imageFormat));
223
224 if ((uint32_t)params.imageCount > context.getDeviceProperties().limits.maxColorAttachments)
225 throw tcu::NotSupportedError(std::string("Unsupported render target count: ") +
226 de::toString(params.imageCount));
227
228 if (params.samplerParams.minFilter == VK_FILTER_LINEAR || params.samplerParams.magFilter == VK_FILTER_LINEAR ||
229 params.samplerParams.mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR)
230 {
231 if (reductionModeInfo == NULL || reductionModeInfo->reductionMode == VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE)
232 {
233 if (!isLinearFilteringSupported(context.getInstanceInterface(), context.getPhysicalDevice(),
234 params.imageFormat, VK_IMAGE_TILING_OPTIMAL))
235 throw tcu::NotSupportedError(std::string("Unsupported format for linear filtering: ") +
236 getFormatName(params.imageFormat));
237 }
238 else
239 {
240 if (!isMinMaxFilteringSupported(context.getInstanceInterface(), context.getPhysicalDevice(),
241 params.imageFormat, VK_IMAGE_TILING_OPTIMAL))
242 throw tcu::NotSupportedError(std::string("Unsupported format for min/max filtering: ") +
243 getFormatName(params.imageFormat));
244 }
245 }
246
247 if (params.separateStencilUsage)
248 {
249 context.requireDeviceFunctionality("VK_EXT_separate_stencil_usage");
250 context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
251
252 const VkImageStencilUsageCreateInfo stencilUsage = {VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO, nullptr,
253 VK_IMAGE_USAGE_TRANSFER_DST_BIT};
254
255 const VkPhysicalDeviceImageFormatInfo2 formatInfo2 = {
256 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // VkStructureType sType
257 params.separateStencilUsage ? &stencilUsage : nullptr, // const void* pNext
258 params.imageFormat, // VkFormat format
259 getCompatibleImageType(params.imageViewType), // VkImageType type
260 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
261 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage
262 (VkImageCreateFlags)0u // VkImageCreateFlags flags
263 };
264
265 VkImageFormatProperties2 extProperties = {
266 VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
267 nullptr,
268 {
269 {
270 0, // width
271 0, // height
272 0, // depth
273 },
274 0u, // maxMipLevels
275 0u, // maxArrayLayers
276 0, // sampleCounts
277 0u, // maxResourceSize
278 },
279 };
280
281 if ((context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(
282 context.getPhysicalDevice(), &formatInfo2, &extProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED) ||
283 extProperties.imageFormatProperties.maxExtent.width < (uint32_t)params.imageSize.x() ||
284 extProperties.imageFormatProperties.maxExtent.height < (uint32_t)params.imageSize.y())
285 {
286 TCU_THROW(NotSupportedError, "Image format not supported");
287 }
288 }
289
290 if (reductionModeInfo != NULL)
291 context.requireDeviceFunctionality("VK_EXT_sampler_filter_minmax");
292
293 if (ycbcrInfo != NULL)
294 context.requireDeviceFunctionality("VK_KHR_sampler_ycbcr_conversion");
295
296 if (borderColorInfo != NULL)
297 if (!context.getCustomBorderColorFeaturesEXT().customBorderColors)
298 throw tcu::NotSupportedError("customBorderColors feature is not supported");
299
300 if (params.samplerParams.addressModeU == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE ||
301 params.samplerParams.addressModeV == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE ||
302 params.samplerParams.addressModeW == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE)
303 {
304 context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
305 }
306
307 if ((isCompressedFormat(params.imageFormat) || isDepthStencilFormat(params.imageFormat)) &&
308 params.imageViewType == VK_IMAGE_VIEW_TYPE_3D)
309 {
310 // \todo [2016-01-22 pyry] Mandate VK_ERROR_FORMAT_NOT_SUPPORTED
311 try
312 {
313 const VkImageFormatProperties formatProperties = getPhysicalDeviceImageFormatProperties(
314 context.getInstanceInterface(), context.getPhysicalDevice(), params.imageFormat, VK_IMAGE_TYPE_3D,
315 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT, (VkImageCreateFlags)0);
316
317 if (formatProperties.maxExtent.width == 0 && formatProperties.maxExtent.height == 0 &&
318 formatProperties.maxExtent.depth == 0)
319 TCU_THROW(NotSupportedError, "3D compressed or depth format not supported");
320 }
321 catch (const Error &)
322 {
323 TCU_THROW(NotSupportedError, "3D compressed or depth format not supported");
324 }
325 }
326
327 if (params.imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
328 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
329
330 if (params.allocationKind == ALLOCATION_KIND_DEDICATED)
331 context.requireDeviceFunctionality("VK_KHR_dedicated_allocation");
332
333 #ifndef CTS_USES_VULKANSC
334 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset"))
335 {
336 const auto portabilitySubsetFeatures = context.getPortabilitySubsetFeatures();
337 const auto componentMapping = params.componentMapping;
338 if (!portabilitySubsetFeatures.imageViewFormatSwizzle &&
339 ((componentMapping.r != VK_COMPONENT_SWIZZLE_IDENTITY) ||
340 (componentMapping.g != VK_COMPONENT_SWIZZLE_IDENTITY) ||
341 (componentMapping.b != VK_COMPONENT_SWIZZLE_IDENTITY) ||
342 (componentMapping.a != VK_COMPONENT_SWIZZLE_IDENTITY)))
343 {
344 TCU_THROW(NotSupportedError,
345 "VK_KHR_portability_subset: Implementation does not support remapping format components");
346 }
347 }
348
349 bool formatRgba10x6WithoutYCbCrSampler = context.getRGBA10X6FormatsFeaturesEXT().formatRgba10x6WithoutYCbCrSampler;
350 #else
351 bool formatRgba10x6WithoutYCbCrSampler = VK_FALSE;
352 #endif // CTS_USES_VULKANSC
353
354 if ((params.imageFormat == VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16) &&
355 (params.subresourceRange.levelCount > 1) && (formatRgba10x6WithoutYCbCrSampler == VK_FALSE))
356 {
357 TCU_THROW(NotSupportedError, "formatRgba10x6WithoutYCbCrSampler not supported");
358 }
359 }
360
ImageSamplingInstance(Context & context,ImageSamplingInstanceParams params)361 ImageSamplingInstance::ImageSamplingInstance(Context &context, ImageSamplingInstanceParams params)
362 : vkt::TestInstance(context)
363 , m_allocationKind(params.allocationKind)
364 , m_samplingType(params.samplingType)
365 , m_imageViewType(params.imageViewType)
366 , m_imageFormat(params.imageFormat)
367 , m_imageSize(params.imageSize)
368 , m_layerCount(params.layerCount)
369 , m_imageCount(params.imageCount)
370 , m_componentMapping(params.componentMapping)
371 , m_componentMask(true)
372 , m_subresourceRange(params.subresourceRange)
373 , m_samplerParams(params.samplerParams)
374 , m_samplerLod(params.samplerLod)
375 , m_renderSize(params.renderSize)
376 , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
377 , m_vertices(params.vertices)
378 , m_graphicsPipeline(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
379 context.getDevice(), m_context.getDeviceExtensions(), params.pipelineConstructionType,
380 params.pipelineCreateFlags)
381 , m_pipelineConstructionType(params.pipelineConstructionType)
382 , m_imageLayout(params.imageLayout)
383 {
384 }
385
setup()386 void ImageSamplingInstance::setup()
387 {
388 const InstanceInterface &vki = m_context.getInstanceInterface();
389 const DeviceInterface &vk = m_context.getDeviceInterface();
390 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
391 const VkDevice vkDevice = m_context.getDevice();
392 const VkQueue queue = m_context.getUniversalQueue();
393 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
394 SimpleAllocator memAlloc(
395 vk, vkDevice,
396 getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
397 const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
398 VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
399
400 void const *pNext = m_samplerParams.pNext;
401 while (pNext != nullptr)
402 {
403 const VkStructureType nextType = *reinterpret_cast<const VkStructureType *>(pNext);
404 switch (nextType)
405 {
406 case VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO:
407 {
408 VkPhysicalDeviceSamplerFilterMinmaxProperties physicalDeviceSamplerMinMaxProperties = {
409 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES, nullptr, false, false};
410 VkPhysicalDeviceProperties2 physicalDeviceProperties;
411 physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
412 physicalDeviceProperties.pNext = &physicalDeviceSamplerMinMaxProperties;
413
414 vki.getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &physicalDeviceProperties);
415
416 if (physicalDeviceSamplerMinMaxProperties.filterMinmaxImageComponentMapping != VK_TRUE)
417 {
418 // If filterMinmaxImageComponentMapping is VK_FALSE the component mapping of the image
419 // view used with min/max filtering must have been created with the r component set to
420 // VK_COMPONENT_SWIZZLE_IDENTITY. Only the r component of the sampled image value is
421 // defined and the other component values are undefined
422
423 m_componentMask = tcu::BVec4(true, false, false, false);
424
425 if (m_componentMapping.r != VK_COMPONENT_SWIZZLE_IDENTITY &&
426 m_componentMapping.r != VK_COMPONENT_SWIZZLE_R)
427 {
428 TCU_THROW(NotSupportedError,
429 "filterMinmaxImageComponentMapping is not supported (R mapping is not IDENTITY)");
430 }
431 }
432 pNext = reinterpret_cast<const VkSamplerReductionModeCreateInfo *>(pNext)->pNext;
433 }
434 break;
435 case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO:
436 pNext = reinterpret_cast<const VkSamplerYcbcrConversionInfo *>(pNext)->pNext;
437 break;
438 case VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT:
439 {
440 const VkSamplerCustomBorderColorCreateInfoEXT customBorderColorCreateInfo =
441 *reinterpret_cast<const VkSamplerCustomBorderColorCreateInfoEXT *>(pNext);
442
443 VkPhysicalDeviceCustomBorderColorFeaturesEXT physicalDeviceCustomBorderColorFeatures = {
444 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT, nullptr, false, false};
445 VkPhysicalDeviceFeatures2 physicalDeviceFeatures;
446 physicalDeviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
447 physicalDeviceFeatures.pNext = &physicalDeviceCustomBorderColorFeatures;
448
449 vki.getPhysicalDeviceFeatures2(m_context.getPhysicalDevice(), &physicalDeviceFeatures);
450
451 if (physicalDeviceCustomBorderColorFeatures.customBorderColors != VK_TRUE)
452 {
453 TCU_THROW(NotSupportedError, "customBorderColors are not supported");
454 }
455
456 if (physicalDeviceCustomBorderColorFeatures.customBorderColorWithoutFormat != VK_TRUE &&
457 customBorderColorCreateInfo.format == VK_FORMAT_UNDEFINED)
458 {
459 TCU_THROW(NotSupportedError, "customBorderColorWithoutFormat is not supported");
460 }
461
462 pNext = reinterpret_cast<const VkSamplerCustomBorderColorCreateInfoEXT *>(pNext)->pNext;
463 }
464 break;
465 default:
466 TCU_FAIL("Unrecognized sType in chained sampler create info");
467 }
468 }
469
470 // Create texture images, views and samplers
471 {
472 VkImageCreateFlags imageFlags = 0u;
473
474 if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
475 imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
476
477 // Initialize texture data
478 if (isCompressedFormat(m_imageFormat))
479 m_texture =
480 createTestTexture(mapVkCompressedFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
481 else
482 m_texture = createTestTexture(mapVkFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
483
484 const VkImageCreateInfo imageParams = {
485 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
486 nullptr, // const void* pNext;
487 imageFlags, // VkImageCreateFlags flags;
488 getCompatibleImageType(m_imageViewType), // VkImageType imageType;
489 m_imageFormat, // VkFormat format;
490 { // VkExtent3D extent;
491 (uint32_t)m_imageSize.x(), (uint32_t)m_imageSize.y(), (uint32_t)m_imageSize.z()},
492 (uint32_t)m_texture->getNumLevels(), // uint32_t mipLevels;
493 (uint32_t)m_layerCount, // uint32_t arrayLayers;
494 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
495 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
496 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
497 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
498 1u, // uint32_t queueFamilyIndexCount;
499 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
500 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
501 };
502
503 m_images.resize(m_imageCount);
504 m_imageAllocs.resize(m_imageCount);
505 m_imageViews.resize(m_imageCount);
506
507 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
508 {
509 m_images[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &imageParams)));
510 m_imageAllocs[imgNdx] =
511 SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_images[imgNdx],
512 MemoryRequirement::Any, memAlloc, m_allocationKind)));
513 VK_CHECK(vk.bindImageMemory(vkDevice, **m_images[imgNdx], (*m_imageAllocs[imgNdx])->getMemory(),
514 (*m_imageAllocs[imgNdx])->getOffset()));
515
516 // Upload texture data
517 uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, **m_images[imgNdx]);
518
519 // Create image view and sampler
520 const VkImageViewCreateInfo imageViewParams = {
521 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
522 nullptr, // const void* pNext;
523 0u, // VkImageViewCreateFlags flags;
524 **m_images[imgNdx], // VkImage image;
525 m_imageViewType, // VkImageViewType viewType;
526 m_imageFormat, // VkFormat format;
527 m_componentMapping, // VkComponentMapping components;
528 m_subresourceRange, // VkImageSubresourceRange subresourceRange;
529 };
530
531 m_imageViews[imgNdx] =
532 SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &imageViewParams)));
533 }
534
535 m_sampler = createSampler(vk, vkDevice, &m_samplerParams);
536 }
537
538 // Create descriptor set for image and sampler
539 {
540 DescriptorPoolBuilder descriptorPoolBuilder;
541 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
542 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 1u);
543 descriptorPoolBuilder.addType(m_samplingType, m_imageCount);
544 m_descriptorPool = descriptorPoolBuilder.build(
545 vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
546 m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? m_imageCount + 1u : m_imageCount);
547
548 DescriptorSetLayoutBuilder setLayoutBuilder;
549 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
550 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
551 setLayoutBuilder.addArrayBinding(m_samplingType, m_imageCount, VK_SHADER_STAGE_FRAGMENT_BIT);
552 m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice);
553
554 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {
555 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
556 nullptr, // const void* pNext;
557 *m_descriptorPool, // VkDescriptorPool descriptorPool;
558 1u, // uint32_t setLayoutCount;
559 &m_descriptorSetLayout.get() // const VkDescriptorSetLayout* pSetLayouts;
560 };
561
562 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
563
564 const VkSampler sampler = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? VK_NULL_HANDLE : *m_sampler;
565 std::vector<VkDescriptorImageInfo> descriptorImageInfo(m_imageCount);
566 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
567 {
568 descriptorImageInfo[imgNdx].sampler = sampler; // VkSampler sampler;
569 descriptorImageInfo[imgNdx].imageView = **m_imageViews[imgNdx]; // VkImageView imageView;
570 descriptorImageInfo[imgNdx].imageLayout =
571 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; // VkImageLayout imageLayout;
572 }
573
574 DescriptorSetUpdateBuilder setUpdateBuilder;
575 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
576 {
577 const VkDescriptorImageInfo descriptorSamplerInfo = {
578 *m_sampler, // VkSampler sampler;
579 VK_NULL_HANDLE, // VkImageView imageView;
580 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout;
581 };
582 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0),
583 VK_DESCRIPTOR_TYPE_SAMPLER, &descriptorSamplerInfo);
584 }
585
586 const uint32_t binding = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? 1u : 0u;
587 setUpdateBuilder.writeArray(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(binding),
588 m_samplingType, m_imageCount, descriptorImageInfo.data());
589 setUpdateBuilder.update(vk, vkDevice);
590 }
591
592 // Create color images and views
593 {
594 const VkImageCreateInfo colorImageParams = {
595 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
596 nullptr, // const void* pNext;
597 0u, // VkImageCreateFlags flags;
598 VK_IMAGE_TYPE_2D, // VkImageType imageType;
599 m_colorFormat, // VkFormat format;
600 {(uint32_t)m_renderSize.x(), (uint32_t)m_renderSize.y(), 1u}, // VkExtent3D extent;
601 1u, // uint32_t mipLevels;
602 1u, // uint32_t arrayLayers;
603 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
604 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
605 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
606 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
607 1u, // uint32_t queueFamilyIndexCount;
608 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
609 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
610 };
611
612 m_colorImages.resize(m_imageCount);
613 m_colorImageAllocs.resize(m_imageCount);
614 m_colorAttachmentViews.resize(m_imageCount);
615
616 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
617 {
618 m_colorImages[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &colorImageParams)));
619 m_colorImageAllocs[imgNdx] =
620 SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_colorImages[imgNdx],
621 MemoryRequirement::Any, memAlloc, m_allocationKind)));
622 VK_CHECK(vk.bindImageMemory(vkDevice, **m_colorImages[imgNdx], (*m_colorImageAllocs[imgNdx])->getMemory(),
623 (*m_colorImageAllocs[imgNdx])->getOffset()));
624
625 const VkImageViewCreateInfo colorAttachmentViewParams = {
626 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
627 nullptr, // const void* pNext;
628 0u, // VkImageViewCreateFlags flags;
629 **m_colorImages[imgNdx], // VkImage image;
630 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
631 m_colorFormat, // VkFormat format;
632 componentMappingRGBA, // VkComponentMapping components;
633 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
634 };
635
636 m_colorAttachmentViews[imgNdx] =
637 SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &colorAttachmentViewParams)));
638 }
639 }
640
641 // Create render pass
642 {
643 std::vector<VkAttachmentDescription> colorAttachmentDescriptions(m_imageCount);
644 std::vector<VkAttachmentReference> colorAttachmentReferences(m_imageCount);
645
646 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
647 {
648 colorAttachmentDescriptions[imgNdx].flags = 0u; // VkAttachmentDescriptionFlags flags;
649 colorAttachmentDescriptions[imgNdx].format = m_colorFormat; // VkFormat format;
650 colorAttachmentDescriptions[imgNdx].samples = VK_SAMPLE_COUNT_1_BIT; // VkSampleCountFlagBits samples;
651 colorAttachmentDescriptions[imgNdx].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // VkAttachmentLoadOp loadOp;
652 colorAttachmentDescriptions[imgNdx].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // VkAttachmentStoreOp storeOp;
653 colorAttachmentDescriptions[imgNdx].stencilLoadOp =
654 VK_ATTACHMENT_LOAD_OP_DONT_CARE; // VkAttachmentLoadOp stencilLoadOp;
655 colorAttachmentDescriptions[imgNdx].stencilStoreOp =
656 VK_ATTACHMENT_STORE_OP_DONT_CARE; // VkAttachmentStoreOp stencilStoreOp;
657 colorAttachmentDescriptions[imgNdx].initialLayout =
658 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout initialLayout;
659 colorAttachmentDescriptions[imgNdx].finalLayout =
660 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout finalLayout;
661
662 colorAttachmentReferences[imgNdx].attachment = (uint32_t)imgNdx; // uint32_t attachment;
663 colorAttachmentReferences[imgNdx].layout =
664 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout layout;
665 }
666
667 const VkSubpassDescription subpassDescription = {
668 0u, // VkSubpassDescriptionFlags flags;
669 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
670 0u, // uint32_t inputAttachmentCount;
671 nullptr, // const VkAttachmentReference* pInputAttachments;
672 (uint32_t)m_imageCount, // uint32_t colorAttachmentCount;
673 &colorAttachmentReferences[0], // const VkAttachmentReference* pColorAttachments;
674 nullptr, // const VkAttachmentReference* pResolveAttachments;
675 nullptr, // const VkAttachmentReference* pDepthStencilAttachment;
676 0u, // uint32_t preserveAttachmentCount;
677 nullptr // const VkAttachmentReference* pPreserveAttachments;
678 };
679
680 const VkRenderPassCreateInfo renderPassParams = {
681 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
682 nullptr, // const void* pNext;
683 0u, // VkRenderPassCreateFlags flags;
684 (uint32_t)m_imageCount, // uint32_t attachmentCount;
685 &colorAttachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
686 1u, // uint32_t subpassCount;
687 &subpassDescription, // const VkSubpassDescription* pSubpasses;
688 0u, // uint32_t dependencyCount;
689 nullptr // const VkSubpassDependency* pDependencies;
690 };
691
692 m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, &renderPassParams);
693 }
694
695 // Create framebuffer
696 {
697 std::vector<VkImage> images(m_imageCount);
698 std::vector<VkImageView> pAttachments(m_imageCount);
699 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
700 {
701 images[imgNdx] = m_colorImages[imgNdx]->get();
702 pAttachments[imgNdx] = m_colorAttachmentViews[imgNdx]->get();
703 }
704
705 const VkFramebufferCreateInfo framebufferParams = {
706 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
707 nullptr, // const void* pNext;
708 0u, // VkFramebufferCreateFlags flags;
709 *m_renderPass, // VkRenderPass renderPass;
710 (uint32_t)m_imageCount, // uint32_t attachmentCount;
711 &pAttachments[0], // const VkImageView* pAttachments;
712 (uint32_t)m_renderSize.x(), // uint32_t width;
713 (uint32_t)m_renderSize.y(), // uint32_t height;
714 1u // uint32_t layers;
715 };
716
717 m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
718 }
719
720 // Create pipeline layout
721 {
722 #ifndef CTS_USES_VULKANSC
723 VkPipelineLayoutCreateFlags pipelineLayoutFlags =
724 (!isConstructionTypeLibrary(m_pipelineConstructionType)) ?
725 0u :
726 uint32_t(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
727 #else
728 VkPipelineLayoutCreateFlags pipelineLayoutFlags = 0u;
729 #endif // CTS_USES_VULKANSC
730 VkPipelineLayoutCreateInfo pipelineLayoutParams{
731 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
732 nullptr, // const void* pNext;
733 pipelineLayoutFlags, // VkPipelineLayoutCreateFlags flags;
734 0u, // uint32_t setLayoutCount;
735 nullptr, // const VkDescriptorSetLayout* pSetLayouts;
736 0u, // uint32_t pushConstantRangeCount;
737 nullptr // const VkPushConstantRange* pPushConstantRanges;
738 };
739
740 m_preRasterizationStatePipelineLayout =
741 PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
742 pipelineLayoutParams.setLayoutCount = 1u;
743 pipelineLayoutParams.pSetLayouts = &m_descriptorSetLayout.get();
744 m_fragmentStatePipelineLayout =
745 PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
746 }
747
748 m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0);
749 m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0);
750
751 // Create pipeline
752 {
753 const VkVertexInputBindingDescription vertexInputBindingDescription = {
754 0u, // uint32_t binding;
755 sizeof(Vertex4Tex4), // uint32_t strideInBytes;
756 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
757 };
758
759 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
760 {
761 0u, // uint32_t location;
762 0u, // uint32_t binding;
763 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
764 0u // uint32_t offset;
765 },
766 {
767 1u, // uint32_t location;
768 0u, // uint32_t binding;
769 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
770 offsetof(Vertex4Tex4, texCoord), // uint32_t offset;
771 }};
772
773 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
774 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
775 nullptr, // const void* pNext;
776 0u, // VkPipelineVertexInputStateCreateFlags flags;
777 1u, // uint32_t vertexBindingDescriptionCount;
778 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
779 2u, // uint32_t vertexAttributeDescriptionCount;
780 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
781 };
782
783 const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
784 const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
785
786 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates(m_imageCount);
787
788 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
789 {
790 colorBlendAttachmentStates[imgNdx].blendEnable = false; // VkBool32 blendEnable;
791 colorBlendAttachmentStates[imgNdx].srcColorBlendFactor =
792 VK_BLEND_FACTOR_ONE; // VkBlendFactor srcColorBlendFactor;
793 colorBlendAttachmentStates[imgNdx].dstColorBlendFactor =
794 VK_BLEND_FACTOR_ZERO; // VkBlendFactor dstColorBlendFactor;
795 colorBlendAttachmentStates[imgNdx].colorBlendOp = VK_BLEND_OP_ADD; // VkBlendOp colorBlendOp;
796 colorBlendAttachmentStates[imgNdx].srcAlphaBlendFactor =
797 VK_BLEND_FACTOR_ONE; // VkBlendFactor srcAlphaBlendFactor;
798 colorBlendAttachmentStates[imgNdx].dstAlphaBlendFactor =
799 VK_BLEND_FACTOR_ZERO; // VkBlendFactor dstAlphaBlendFactor;
800 colorBlendAttachmentStates[imgNdx].alphaBlendOp = VK_BLEND_OP_ADD; // VkBlendOp alphaBlendOp;
801 colorBlendAttachmentStates[imgNdx].colorWriteMask =
802 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
803 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
804 }
805
806 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = {
807 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
808 nullptr, // const void* pNext;
809 0u, // VkPipelineColorBlendStateCreateFlags flags;
810 false, // VkBool32 logicOpEnable;
811 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
812 (uint32_t)m_imageCount, // uint32_t attachmentCount;
813 &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState* pAttachments;
814 {0.0f, 0.0f, 0.0f, 0.0f} // float blendConstants[4];
815 };
816
817 m_graphicsPipeline.setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
818 .setDefaultDepthStencilState()
819 .setDefaultRasterizationState()
820 .setDefaultMultisampleState()
821 .setupVertexInputState(&vertexInputStateParams)
822 .setupPreRasterizationShaderState(viewports, scissors, m_preRasterizationStatePipelineLayout, *m_renderPass,
823 0u, m_vertexShaderModule)
824 .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule)
825 .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams)
826 .buildPipeline();
827 }
828
829 // Create vertex buffer
830 {
831 const VkDeviceSize vertexBufferSize = (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4));
832 const VkBufferCreateInfo vertexBufferParams = {
833 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
834 nullptr, // const void* pNext;
835 0u, // VkBufferCreateFlags flags;
836 vertexBufferSize, // VkDeviceSize size;
837 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
838 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
839 1u, // uint32_t queueFamilyIndexCount;
840 &queueFamilyIndex // const uint32_t* pQueueFamilyIndices;
841 };
842
843 DE_ASSERT(vertexBufferSize > 0);
844
845 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
846 m_vertexBufferAlloc = allocateBuffer(vki, vk, physDevice, vkDevice, *m_vertexBuffer,
847 MemoryRequirement::HostVisible, memAlloc, m_allocationKind);
848 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
849 m_vertexBufferAlloc->getOffset()));
850
851 // Load vertices into vertex buffer
852 deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize);
853 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
854 }
855
856 // Create command pool
857 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
858
859 // Create command buffer
860 {
861 const std::vector<VkClearValue> attachmentClearValues(m_imageCount, defaultClearValue(m_colorFormat));
862
863 std::vector<VkImageMemoryBarrier> preAttachmentBarriers(m_imageCount);
864
865 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
866 {
867 preAttachmentBarriers[imgNdx].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; // VkStructureType sType;
868 preAttachmentBarriers[imgNdx].pNext = nullptr; // const void* pNext;
869 preAttachmentBarriers[imgNdx].srcAccessMask = 0u; // VkAccessFlags srcAccessMask;
870 preAttachmentBarriers[imgNdx].dstAccessMask =
871 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; // VkAccessFlags dstAccessMask;
872 preAttachmentBarriers[imgNdx].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; // VkImageLayout oldLayout;
873 preAttachmentBarriers[imgNdx].newLayout =
874 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout newLayout;
875 preAttachmentBarriers[imgNdx].srcQueueFamilyIndex =
876 VK_QUEUE_FAMILY_IGNORED; // uint32_t srcQueueFamilyIndex;
877 preAttachmentBarriers[imgNdx].dstQueueFamilyIndex =
878 VK_QUEUE_FAMILY_IGNORED; // uint32_t dstQueueFamilyIndex;
879 preAttachmentBarriers[imgNdx].image = **m_colorImages[imgNdx]; // VkImage image;
880 preAttachmentBarriers[imgNdx].subresourceRange.aspectMask =
881 VK_IMAGE_ASPECT_COLOR_BIT; // VkImageSubresourceRange subresourceRange;
882 preAttachmentBarriers[imgNdx].subresourceRange.baseMipLevel = 0u;
883 preAttachmentBarriers[imgNdx].subresourceRange.levelCount = 1u;
884 preAttachmentBarriers[imgNdx].subresourceRange.baseArrayLayer = 0u;
885 preAttachmentBarriers[imgNdx].subresourceRange.layerCount = 1u;
886 }
887
888 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
889
890 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
891
892 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
893 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0u, nullptr, 0u,
894 nullptr, (uint32_t)m_imageCount, &preAttachmentBarriers[0]);
895
896 m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
897 (uint32_t)attachmentClearValues.size(), &attachmentClearValues[0]);
898
899 m_graphicsPipeline.bind(*m_cmdBuffer);
900
901 m_fragmentStatePipelineLayout.bindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 1,
902 &m_descriptorSet.get(), 0, nullptr);
903
904 const VkDeviceSize vertexBufferOffset = 0;
905 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
906 vk.cmdDraw(*m_cmdBuffer, (uint32_t)m_vertices.size(), 1, 0, 0);
907
908 m_renderPass.end(vk, *m_cmdBuffer);
909 endCommandBuffer(vk, *m_cmdBuffer);
910 }
911 }
912
~ImageSamplingInstance(void)913 ImageSamplingInstance::~ImageSamplingInstance(void)
914 {
915 }
916
iterate(void)917 tcu::TestStatus ImageSamplingInstance::iterate(void)
918 {
919 const DeviceInterface &vk = m_context.getDeviceInterface();
920 const VkDevice vkDevice = m_context.getDevice();
921 const VkQueue queue = m_context.getUniversalQueue();
922
923 setup();
924
925 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
926
927 return verifyImage();
928 }
929
930 namespace
931 {
932
isLookupResultValid(const tcu::Texture1DView & texture,const tcu::Sampler & sampler,const tcu::LookupPrecision & precision,const tcu::Vec4 & coords,const tcu::Vec2 & lodBounds,const tcu::Vec4 & result)933 bool isLookupResultValid(const tcu::Texture1DView &texture, const tcu::Sampler &sampler,
934 const tcu::LookupPrecision &precision, const tcu::Vec4 &coords, const tcu::Vec2 &lodBounds,
935 const tcu::Vec4 &result)
936 {
937 return tcu::isLookupResultValid(texture, sampler, precision, coords.x(), lodBounds, result);
938 }
939
isLookupResultValid(const tcu::Texture1DArrayView & texture,const tcu::Sampler & sampler,const tcu::LookupPrecision & precision,const tcu::Vec4 & coords,const tcu::Vec2 & lodBounds,const tcu::Vec4 & result)940 bool isLookupResultValid(const tcu::Texture1DArrayView &texture, const tcu::Sampler &sampler,
941 const tcu::LookupPrecision &precision, const tcu::Vec4 &coords, const tcu::Vec2 &lodBounds,
942 const tcu::Vec4 &result)
943 {
944 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0, 1), lodBounds, result);
945 }
946
isLookupResultValid(const tcu::Texture2DView & texture,const tcu::Sampler & sampler,const tcu::LookupPrecision & precision,const tcu::Vec4 & coords,const tcu::Vec2 & lodBounds,const tcu::Vec4 & result)947 bool isLookupResultValid(const tcu::Texture2DView &texture, const tcu::Sampler &sampler,
948 const tcu::LookupPrecision &precision, const tcu::Vec4 &coords, const tcu::Vec2 &lodBounds,
949 const tcu::Vec4 &result)
950 {
951 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0, 1), lodBounds, result);
952 }
953
isLookupResultValid(const tcu::Texture2DArrayView & texture,const tcu::Sampler & sampler,const tcu::LookupPrecision & precision,const tcu::Vec4 & coords,const tcu::Vec2 & lodBounds,const tcu::Vec4 & result)954 bool isLookupResultValid(const tcu::Texture2DArrayView &texture, const tcu::Sampler &sampler,
955 const tcu::LookupPrecision &precision, const tcu::Vec4 &coords, const tcu::Vec2 &lodBounds,
956 const tcu::Vec4 &result)
957 {
958 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0, 1, 2), lodBounds, result);
959 }
960
isLookupResultValid(const tcu::TextureCubeView & texture,const tcu::Sampler & sampler,const tcu::LookupPrecision & precision,const tcu::Vec4 & coords,const tcu::Vec2 & lodBounds,const tcu::Vec4 & result)961 bool isLookupResultValid(const tcu::TextureCubeView &texture, const tcu::Sampler &sampler,
962 const tcu::LookupPrecision &precision, const tcu::Vec4 &coords, const tcu::Vec2 &lodBounds,
963 const tcu::Vec4 &result)
964 {
965 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0, 1, 2), lodBounds, result);
966 }
967
isLookupResultValid(const tcu::TextureCubeArrayView & texture,const tcu::Sampler & sampler,const tcu::LookupPrecision & precision,const tcu::Vec4 & coords,const tcu::Vec2 & lodBounds,const tcu::Vec4 & result)968 bool isLookupResultValid(const tcu::TextureCubeArrayView &texture, const tcu::Sampler &sampler,
969 const tcu::LookupPrecision &precision, const tcu::Vec4 &coords, const tcu::Vec2 &lodBounds,
970 const tcu::Vec4 &result)
971 {
972 return tcu::isLookupResultValid(texture, sampler, precision, tcu::IVec4(precision.coordBits.x()), coords, lodBounds,
973 result);
974 }
975
isLookupResultValid(const tcu::Texture3DView & texture,const tcu::Sampler & sampler,const tcu::LookupPrecision & precision,const tcu::Vec4 & coords,const tcu::Vec2 & lodBounds,const tcu::Vec4 & result)976 bool isLookupResultValid(const tcu::Texture3DView &texture, const tcu::Sampler &sampler,
977 const tcu::LookupPrecision &precision, const tcu::Vec4 &coords, const tcu::Vec2 &lodBounds,
978 const tcu::Vec4 &result)
979 {
980 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0, 1, 2), lodBounds, result);
981 }
982
983 template <typename TextureViewType>
validateResultImage(const TextureViewType & texture,const tcu::Sampler & sampler,const tcu::ConstPixelBufferAccess & texCoords,const tcu::Vec2 & lodBounds,const tcu::LookupPrecision & lookupPrecision,const tcu::Vec4 & lookupScale,const tcu::Vec4 & lookupBias,const tcu::ConstPixelBufferAccess & result,const tcu::PixelBufferAccess & errorMask)984 bool validateResultImage(const TextureViewType &texture, const tcu::Sampler &sampler,
985 const tcu::ConstPixelBufferAccess &texCoords, const tcu::Vec2 &lodBounds,
986 const tcu::LookupPrecision &lookupPrecision, const tcu::Vec4 &lookupScale,
987 const tcu::Vec4 &lookupBias, const tcu::ConstPixelBufferAccess &result,
988 const tcu::PixelBufferAccess &errorMask)
989 {
990 const int w = result.getWidth();
991 const int h = result.getHeight();
992 bool allOk = true;
993
994 for (int y = 0; y < h; ++y)
995 {
996 for (int x = 0; x < w; ++x)
997 {
998 const tcu::Vec4 resultPixel = result.getPixel(x, y);
999 const tcu::Vec4 resultColor = (resultPixel - lookupBias) / lookupScale;
1000 const tcu::Vec4 texCoord = texCoords.getPixel(x, y);
1001 const bool pixelOk =
1002 isLookupResultValid(texture, sampler, lookupPrecision, texCoord, lodBounds, resultColor);
1003
1004 errorMask.setPixel(tcu::Vec4(pixelOk ? 0.0f : 1.0f, pixelOk ? 1.0f : 0.0f, 0.0f, 1.0f), x, y);
1005
1006 if (!pixelOk)
1007 allOk = false;
1008 }
1009 }
1010
1011 return allOk;
1012 }
1013
1014 template <typename ScalarType>
getSwizzledComp(const tcu::Vector<ScalarType,4> & vec,vk::VkComponentSwizzle comp,int identityNdx)1015 ScalarType getSwizzledComp(const tcu::Vector<ScalarType, 4> &vec, vk::VkComponentSwizzle comp, int identityNdx)
1016 {
1017 if (comp == vk::VK_COMPONENT_SWIZZLE_IDENTITY)
1018 return vec[identityNdx];
1019 else if (comp == vk::VK_COMPONENT_SWIZZLE_ZERO)
1020 return ScalarType(0);
1021 else if (comp == vk::VK_COMPONENT_SWIZZLE_ONE)
1022 return ScalarType(1);
1023 else
1024 return vec[comp - vk::VK_COMPONENT_SWIZZLE_R];
1025 }
1026
1027 template <typename ScalarType>
swizzle(const tcu::Vector<ScalarType,4> & vec,const vk::VkComponentMapping & swz)1028 tcu::Vector<ScalarType, 4> swizzle(const tcu::Vector<ScalarType, 4> &vec, const vk::VkComponentMapping &swz)
1029 {
1030 return tcu::Vector<ScalarType, 4>(getSwizzledComp(vec, swz.r, 0), getSwizzledComp(vec, swz.g, 1),
1031 getSwizzledComp(vec, swz.b, 2), getSwizzledComp(vec, swz.a, 3));
1032 }
1033
1034 /*--------------------------------------------------------------------*//*!
1035 * \brief Swizzle scale or bias vector by given mapping
1036 *
1037 * \param vec scale or bias vector
1038 * \param swz swizzle component mapping, may include ZERO, ONE, or IDENTITY
1039 * \param zeroOrOneValue vector value for component swizzled as ZERO or ONE
1040 * \return swizzled vector
1041 *//*--------------------------------------------------------------------*/
swizzleScaleBias(const tcu::Vec4 & vec,const vk::VkComponentMapping & swz,float zeroOrOneValue)1042 tcu::Vec4 swizzleScaleBias(const tcu::Vec4 &vec, const vk::VkComponentMapping &swz, float zeroOrOneValue)
1043 {
1044
1045 // Remove VK_COMPONENT_SWIZZLE_IDENTITY to avoid addressing channelValues[0]
1046 const vk::VkComponentMapping nonIdentitySwz = {
1047 swz.r == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_R : swz.r,
1048 swz.g == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_G : swz.g,
1049 swz.b == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_B : swz.b,
1050 swz.a == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_A : swz.a};
1051
1052 const float channelValues[] = {
1053 -1.0f, // impossible
1054 zeroOrOneValue, // SWIZZLE_ZERO
1055 zeroOrOneValue, // SWIZZLE_ONE
1056 vec.x(), vec.y(), vec.z(), vec.w(),
1057 };
1058
1059 return tcu::Vec4(channelValues[nonIdentitySwz.r], channelValues[nonIdentitySwz.g], channelValues[nonIdentitySwz.b],
1060 channelValues[nonIdentitySwz.a]);
1061 }
1062
1063 template <typename ScalarType>
swizzleT(const tcu::ConstPixelBufferAccess & src,const tcu::PixelBufferAccess & dst,const vk::VkComponentMapping & swz)1064 void swizzleT(const tcu::ConstPixelBufferAccess &src, const tcu::PixelBufferAccess &dst,
1065 const vk::VkComponentMapping &swz)
1066 {
1067 for (int z = 0; z < dst.getDepth(); ++z)
1068 for (int y = 0; y < dst.getHeight(); ++y)
1069 for (int x = 0; x < dst.getWidth(); ++x)
1070 dst.setPixel(swizzle(src.getPixelT<ScalarType>(x, y, z), swz), x, y, z);
1071 }
1072
swizzleFromSRGB(const tcu::ConstPixelBufferAccess & src,const tcu::PixelBufferAccess & dst,const vk::VkComponentMapping & swz)1073 void swizzleFromSRGB(const tcu::ConstPixelBufferAccess &src, const tcu::PixelBufferAccess &dst,
1074 const vk::VkComponentMapping &swz)
1075 {
1076 for (int z = 0; z < dst.getDepth(); ++z)
1077 for (int y = 0; y < dst.getHeight(); ++y)
1078 for (int x = 0; x < dst.getWidth(); ++x)
1079 dst.setPixel(swizzle(tcu::sRGBToLinear(src.getPixelT<float>(x, y, z)), swz), x, y, z);
1080 }
1081
swizzle(const tcu::ConstPixelBufferAccess & src,const tcu::PixelBufferAccess & dst,const vk::VkComponentMapping & swz)1082 void swizzle(const tcu::ConstPixelBufferAccess &src, const tcu::PixelBufferAccess &dst,
1083 const vk::VkComponentMapping &swz)
1084 {
1085 const tcu::TextureChannelClass chnClass = tcu::getTextureChannelClass(dst.getFormat().type);
1086
1087 DE_ASSERT(src.getWidth() == dst.getWidth() && src.getHeight() == dst.getHeight() &&
1088 src.getDepth() == dst.getDepth());
1089
1090 if (chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1091 swizzleT<int32_t>(src, dst, swz);
1092 else if (chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1093 swizzleT<uint32_t>(src, dst, swz);
1094 else if (tcu::isSRGB(src.getFormat()) && !tcu::isSRGB(dst.getFormat()))
1095 swizzleFromSRGB(src, dst, swz);
1096 else
1097 swizzleT<float>(src, dst, swz);
1098 }
1099
isIdentitySwizzle(const vk::VkComponentMapping & swz)1100 bool isIdentitySwizzle(const vk::VkComponentMapping &swz)
1101 {
1102 return (swz.r == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.r == vk::VK_COMPONENT_SWIZZLE_R) &&
1103 (swz.g == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.g == vk::VK_COMPONENT_SWIZZLE_G) &&
1104 (swz.b == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.b == vk::VK_COMPONENT_SWIZZLE_B) &&
1105 (swz.a == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.a == vk::VK_COMPONENT_SWIZZLE_A);
1106 }
1107
1108 template <typename TextureViewType>
1109 struct TexViewTraits;
1110
1111 template <>
1112 struct TexViewTraits<tcu::Texture1DView>
1113 {
1114 typedef tcu::Texture1D TextureType;
1115 };
1116 template <>
1117 struct TexViewTraits<tcu::Texture1DArrayView>
1118 {
1119 typedef tcu::Texture1DArray TextureType;
1120 };
1121 template <>
1122 struct TexViewTraits<tcu::Texture2DView>
1123 {
1124 typedef tcu::Texture2D TextureType;
1125 };
1126 template <>
1127 struct TexViewTraits<tcu::Texture2DArrayView>
1128 {
1129 typedef tcu::Texture2DArray TextureType;
1130 };
1131 template <>
1132 struct TexViewTraits<tcu::TextureCubeView>
1133 {
1134 typedef tcu::TextureCube TextureType;
1135 };
1136 template <>
1137 struct TexViewTraits<tcu::TextureCubeArrayView>
1138 {
1139 typedef tcu::TextureCubeArray TextureType;
1140 };
1141 template <>
1142 struct TexViewTraits<tcu::Texture3DView>
1143 {
1144 typedef tcu::Texture3D TextureType;
1145 };
1146
1147 template <typename TextureViewType>
1148 typename TexViewTraits<TextureViewType>::TextureType *createSkeletonClone(tcu::TextureFormat format,
1149 const tcu::ConstPixelBufferAccess &level0);
1150
getSwizzleTargetFormat(tcu::TextureFormat format)1151 tcu::TextureFormat getSwizzleTargetFormat(tcu::TextureFormat format)
1152 {
1153 // Swizzled texture needs to hold all four channels
1154 // \todo [2016-09-21 pyry] We could save some memory by using smaller formats
1155 // when possible (for example U8).
1156
1157 const tcu::TextureChannelClass chnClass = tcu::getTextureChannelClass(format.type);
1158
1159 if (chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1160 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
1161 else if (chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1162 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
1163 else
1164 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
1165 }
1166
1167 template <>
createSkeletonClone(tcu::TextureFormat format,const tcu::ConstPixelBufferAccess & level0)1168 tcu::Texture1D *createSkeletonClone<tcu::Texture1DView>(tcu::TextureFormat format,
1169 const tcu::ConstPixelBufferAccess &level0)
1170 {
1171 return new tcu::Texture1D(format, level0.getWidth());
1172 }
1173
1174 template <>
createSkeletonClone(tcu::TextureFormat format,const tcu::ConstPixelBufferAccess & level0)1175 tcu::Texture1DArray *createSkeletonClone<tcu::Texture1DArrayView>(tcu::TextureFormat format,
1176 const tcu::ConstPixelBufferAccess &level0)
1177 {
1178 return new tcu::Texture1DArray(format, level0.getWidth(), level0.getHeight());
1179 }
1180
1181 template <>
createSkeletonClone(tcu::TextureFormat format,const tcu::ConstPixelBufferAccess & level0)1182 tcu::Texture2D *createSkeletonClone<tcu::Texture2DView>(tcu::TextureFormat format,
1183 const tcu::ConstPixelBufferAccess &level0)
1184 {
1185 return new tcu::Texture2D(format, level0.getWidth(), level0.getHeight());
1186 }
1187
1188 template <>
createSkeletonClone(tcu::TextureFormat format,const tcu::ConstPixelBufferAccess & level0)1189 tcu::Texture2DArray *createSkeletonClone<tcu::Texture2DArrayView>(tcu::TextureFormat format,
1190 const tcu::ConstPixelBufferAccess &level0)
1191 {
1192 return new tcu::Texture2DArray(format, level0.getWidth(), level0.getHeight(), level0.getDepth());
1193 }
1194
1195 template <>
createSkeletonClone(tcu::TextureFormat format,const tcu::ConstPixelBufferAccess & level0)1196 tcu::Texture3D *createSkeletonClone<tcu::Texture3DView>(tcu::TextureFormat format,
1197 const tcu::ConstPixelBufferAccess &level0)
1198 {
1199 return new tcu::Texture3D(format, level0.getWidth(), level0.getHeight(), level0.getDepth());
1200 }
1201
1202 template <>
createSkeletonClone(tcu::TextureFormat format,const tcu::ConstPixelBufferAccess & level0)1203 tcu::TextureCubeArray *createSkeletonClone<tcu::TextureCubeArrayView>(tcu::TextureFormat format,
1204 const tcu::ConstPixelBufferAccess &level0)
1205 {
1206 return new tcu::TextureCubeArray(format, level0.getWidth(), level0.getDepth());
1207 }
1208
1209 template <typename TextureViewType>
createSwizzledCopy(const TextureViewType & texture,const vk::VkComponentMapping & swz)1210 MovePtr<typename TexViewTraits<TextureViewType>::TextureType> createSwizzledCopy(const TextureViewType &texture,
1211 const vk::VkComponentMapping &swz)
1212 {
1213 MovePtr<typename TexViewTraits<TextureViewType>::TextureType> copy(createSkeletonClone<TextureViewType>(
1214 getSwizzleTargetFormat(texture.getLevel(0).getFormat()), texture.getLevel(0)));
1215
1216 for (int levelNdx = 0; levelNdx < texture.getNumLevels(); ++levelNdx)
1217 {
1218 copy->allocLevel(levelNdx);
1219 swizzle(texture.getLevel(levelNdx), copy->getLevel(levelNdx), swz);
1220 }
1221
1222 return copy;
1223 }
1224
1225 template <>
createSwizzledCopy(const tcu::TextureCubeView & texture,const vk::VkComponentMapping & swz)1226 MovePtr<tcu::TextureCube> createSwizzledCopy(const tcu::TextureCubeView &texture, const vk::VkComponentMapping &swz)
1227 {
1228 MovePtr<tcu::TextureCube> copy(new tcu::TextureCube(
1229 getSwizzleTargetFormat(texture.getLevelFace(0, tcu::CUBEFACE_NEGATIVE_X).getFormat()), texture.getSize()));
1230
1231 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1232 {
1233 for (int levelNdx = 0; levelNdx < texture.getNumLevels(); ++levelNdx)
1234 {
1235 copy->allocLevel((tcu::CubeFace)faceNdx, levelNdx);
1236 swizzle(texture.getLevelFace(levelNdx, (tcu::CubeFace)faceNdx),
1237 copy->getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), swz);
1238 }
1239 }
1240
1241 return copy;
1242 }
1243
1244 template <typename TextureViewType>
validateResultImage(const TextureViewType & texture,const tcu::Sampler & sampler,const vk::VkComponentMapping & swz,const tcu::ConstPixelBufferAccess & texCoords,const tcu::Vec2 & lodBounds,const tcu::LookupPrecision & lookupPrecision,const tcu::Vec4 & lookupScale,const tcu::Vec4 & lookupBias,const tcu::ConstPixelBufferAccess & result,const tcu::PixelBufferAccess & errorMask)1245 bool validateResultImage(const TextureViewType &texture, const tcu::Sampler &sampler, const vk::VkComponentMapping &swz,
1246 const tcu::ConstPixelBufferAccess &texCoords, const tcu::Vec2 &lodBounds,
1247 const tcu::LookupPrecision &lookupPrecision, const tcu::Vec4 &lookupScale,
1248 const tcu::Vec4 &lookupBias, const tcu::ConstPixelBufferAccess &result,
1249 const tcu::PixelBufferAccess &errorMask)
1250 {
1251 if (isIdentitySwizzle(swz))
1252 return validateResultImage(texture, sampler, texCoords, lodBounds, lookupPrecision, lookupScale, lookupBias,
1253 result, errorMask);
1254 else
1255 {
1256 // There is (currently) no way to handle swizzling inside validation loop
1257 // and thus we need to pre-swizzle the texture.
1258 UniquePtr<typename TexViewTraits<TextureViewType>::TextureType> swizzledTex(createSwizzledCopy(texture, swz));
1259
1260 return validateResultImage(*swizzledTex, sampler, texCoords, lodBounds, lookupPrecision,
1261 swizzleScaleBias(lookupScale, swz, 1.0f), swizzleScaleBias(lookupBias, swz, 0.0f),
1262 result, errorMask);
1263 }
1264 }
1265
resolveSubresourceRange(const TestTexture & testTexture,const vk::VkImageSubresourceRange & subresource)1266 vk::VkImageSubresourceRange resolveSubresourceRange(const TestTexture &testTexture,
1267 const vk::VkImageSubresourceRange &subresource)
1268 {
1269 vk::VkImageSubresourceRange resolved = subresource;
1270
1271 if (subresource.levelCount == VK_REMAINING_MIP_LEVELS)
1272 resolved.levelCount = testTexture.getNumLevels() - subresource.baseMipLevel;
1273
1274 if (subresource.layerCount == VK_REMAINING_ARRAY_LAYERS)
1275 resolved.layerCount = testTexture.getArraySize() - subresource.baseArrayLayer;
1276
1277 return resolved;
1278 }
1279
getTexture1DView(const TestTexture & testTexture,const vk::VkImageSubresourceRange & subresource,std::vector<tcu::ConstPixelBufferAccess> & levels)1280 MovePtr<tcu::Texture1DView> getTexture1DView(const TestTexture &testTexture,
1281 const vk::VkImageSubresourceRange &subresource,
1282 std::vector<tcu::ConstPixelBufferAccess> &levels)
1283 {
1284 DE_ASSERT(subresource.layerCount == 1);
1285
1286 levels.resize(subresource.levelCount);
1287
1288 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1289 {
1290 const tcu::ConstPixelBufferAccess &srcLevel =
1291 testTexture.getLevel((int)subresource.baseMipLevel + levelNdx, subresource.baseArrayLayer);
1292
1293 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, 0, srcLevel.getWidth(), 1, 1);
1294 }
1295
1296 return MovePtr<tcu::Texture1DView>(new tcu::Texture1DView((int)levels.size(), &levels[0]));
1297 }
1298
getTexture1DArrayView(const TestTexture & testTexture,const vk::VkImageSubresourceRange & subresource,std::vector<tcu::ConstPixelBufferAccess> & levels)1299 MovePtr<tcu::Texture1DArrayView> getTexture1DArrayView(const TestTexture &testTexture,
1300 const vk::VkImageSubresourceRange &subresource,
1301 std::vector<tcu::ConstPixelBufferAccess> &levels)
1302 {
1303 const TestTexture1D *tex1D = dynamic_cast<const TestTexture1D *>(&testTexture);
1304 const TestTexture1DArray *tex1DArray = dynamic_cast<const TestTexture1DArray *>(&testTexture);
1305
1306 DE_ASSERT(!!tex1D != !!tex1DArray);
1307 DE_ASSERT(tex1DArray || subresource.baseArrayLayer == 0);
1308
1309 levels.resize(subresource.levelCount);
1310
1311 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1312 {
1313 const tcu::ConstPixelBufferAccess &srcLevel =
1314 tex1D ? tex1D->getTexture().getLevel((int)subresource.baseMipLevel + levelNdx) :
1315 tex1DArray->getTexture().getLevel((int)subresource.baseMipLevel + levelNdx);
1316
1317 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, (int)subresource.baseArrayLayer, 0, srcLevel.getWidth(),
1318 (int)subresource.layerCount, 1);
1319 }
1320
1321 return MovePtr<tcu::Texture1DArrayView>(new tcu::Texture1DArrayView((int)levels.size(), &levels[0]));
1322 }
1323
getTexture2DView(const TestTexture & testTexture,const vk::VkImageSubresourceRange & subresource,std::vector<tcu::ConstPixelBufferAccess> & levels)1324 MovePtr<tcu::Texture2DView> getTexture2DView(const TestTexture &testTexture,
1325 const vk::VkImageSubresourceRange &subresource,
1326 std::vector<tcu::ConstPixelBufferAccess> &levels)
1327 {
1328 const TestTexture2D *tex2D = dynamic_cast<const TestTexture2D *>(&testTexture);
1329 const TestTexture2DArray *tex2DArray = dynamic_cast<const TestTexture2DArray *>(&testTexture);
1330
1331 DE_ASSERT(subresource.layerCount == 1);
1332 DE_ASSERT(!!tex2D != !!tex2DArray);
1333 DE_ASSERT(tex2DArray || subresource.baseArrayLayer == 0);
1334
1335 levels.resize(subresource.levelCount);
1336
1337 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1338 {
1339 const tcu::ConstPixelBufferAccess &srcLevel =
1340 tex2D ? tex2D->getTexture().getLevel((int)subresource.baseMipLevel + levelNdx) :
1341 tex2DArray->getTexture().getLevel((int)subresource.baseMipLevel + levelNdx);
1342
1343 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(),
1344 srcLevel.getHeight(), 1);
1345 }
1346
1347 return MovePtr<tcu::Texture2DView>(new tcu::Texture2DView((int)levels.size(), &levels[0]));
1348 }
1349
getTexture2DArrayView(const TestTexture & testTexture,const vk::VkImageSubresourceRange & subresource,std::vector<tcu::ConstPixelBufferAccess> & levels)1350 MovePtr<tcu::Texture2DArrayView> getTexture2DArrayView(const TestTexture &testTexture,
1351 const vk::VkImageSubresourceRange &subresource,
1352 std::vector<tcu::ConstPixelBufferAccess> &levels)
1353 {
1354 const TestTexture2D *tex2D = dynamic_cast<const TestTexture2D *>(&testTexture);
1355 const TestTexture2DArray *tex2DArray = dynamic_cast<const TestTexture2DArray *>(&testTexture);
1356
1357 DE_ASSERT(!!tex2D != !!tex2DArray);
1358 DE_ASSERT(tex2DArray || subresource.baseArrayLayer == 0);
1359
1360 levels.resize(subresource.levelCount);
1361
1362 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1363 {
1364 const tcu::ConstPixelBufferAccess &srcLevel =
1365 tex2D ? tex2D->getTexture().getLevel((int)subresource.baseMipLevel + levelNdx) :
1366 tex2DArray->getTexture().getLevel((int)subresource.baseMipLevel + levelNdx);
1367
1368 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(),
1369 srcLevel.getHeight(), (int)subresource.layerCount);
1370 }
1371
1372 return MovePtr<tcu::Texture2DArrayView>(new tcu::Texture2DArrayView((int)levels.size(), &levels[0]));
1373 }
1374
getTextureCubeView(const TestTexture & testTexture,const vk::VkImageSubresourceRange & subresource,std::vector<tcu::ConstPixelBufferAccess> & levels)1375 MovePtr<tcu::TextureCubeView> getTextureCubeView(const TestTexture &testTexture,
1376 const vk::VkImageSubresourceRange &subresource,
1377 std::vector<tcu::ConstPixelBufferAccess> &levels)
1378 {
1379 const static tcu::CubeFace s_faceMap[tcu::CUBEFACE_LAST] = {tcu::CUBEFACE_POSITIVE_X, tcu::CUBEFACE_NEGATIVE_X,
1380 tcu::CUBEFACE_POSITIVE_Y, tcu::CUBEFACE_NEGATIVE_Y,
1381 tcu::CUBEFACE_POSITIVE_Z, tcu::CUBEFACE_NEGATIVE_Z};
1382
1383 const TestTextureCube *texCube = dynamic_cast<const TestTextureCube *>(&testTexture);
1384 const TestTextureCubeArray *texCubeArray = dynamic_cast<const TestTextureCubeArray *>(&testTexture);
1385
1386 DE_ASSERT(!!texCube != !!texCubeArray);
1387 DE_ASSERT(subresource.layerCount == 6);
1388 DE_ASSERT(texCubeArray || subresource.baseArrayLayer == 0);
1389
1390 levels.resize(subresource.levelCount * tcu::CUBEFACE_LAST);
1391
1392 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1393 {
1394 for (int levelNdx = 0; levelNdx < (int)subresource.levelCount; ++levelNdx)
1395 {
1396 const tcu::ConstPixelBufferAccess &srcLevel =
1397 texCubeArray ? texCubeArray->getTexture().getLevel((int)subresource.baseMipLevel + levelNdx) :
1398 texCube->getTexture().getLevelFace(levelNdx, s_faceMap[faceNdx]);
1399
1400 levels[faceNdx * subresource.levelCount + levelNdx] =
1401 tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer + (texCubeArray ? faceNdx : 0),
1402 srcLevel.getWidth(), srcLevel.getHeight(), 1);
1403 }
1404 }
1405
1406 {
1407 const tcu::ConstPixelBufferAccess *reordered[tcu::CUBEFACE_LAST];
1408
1409 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1410 reordered[s_faceMap[faceNdx]] = &levels[faceNdx * subresource.levelCount];
1411
1412 return MovePtr<tcu::TextureCubeView>(new tcu::TextureCubeView((int)subresource.levelCount, reordered));
1413 }
1414 }
1415
getTextureCubeArrayView(const TestTexture & testTexture,const vk::VkImageSubresourceRange & subresource,std::vector<tcu::ConstPixelBufferAccess> & levels)1416 MovePtr<tcu::TextureCubeArrayView> getTextureCubeArrayView(const TestTexture &testTexture,
1417 const vk::VkImageSubresourceRange &subresource,
1418 std::vector<tcu::ConstPixelBufferAccess> &levels)
1419 {
1420 const TestTextureCubeArray *texCubeArray = dynamic_cast<const TestTextureCubeArray *>(&testTexture);
1421
1422 DE_ASSERT(texCubeArray);
1423 DE_ASSERT(subresource.layerCount % 6 == 0);
1424
1425 levels.resize(subresource.levelCount);
1426
1427 for (int levelNdx = 0; levelNdx < (int)subresource.levelCount; ++levelNdx)
1428 {
1429 const tcu::ConstPixelBufferAccess &srcLevel =
1430 texCubeArray->getTexture().getLevel((int)subresource.baseMipLevel + levelNdx);
1431
1432 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(),
1433 srcLevel.getHeight(), (int)subresource.layerCount);
1434 }
1435
1436 return MovePtr<tcu::TextureCubeArrayView>(new tcu::TextureCubeArrayView((int)levels.size(), &levels[0]));
1437 }
1438
getTexture3DView(const TestTexture & testTexture,const vk::VkImageSubresourceRange & subresource,std::vector<tcu::ConstPixelBufferAccess> & levels)1439 MovePtr<tcu::Texture3DView> getTexture3DView(const TestTexture &testTexture,
1440 const vk::VkImageSubresourceRange &subresource,
1441 std::vector<tcu::ConstPixelBufferAccess> &levels)
1442 {
1443 DE_ASSERT(subresource.baseArrayLayer == 0 && subresource.layerCount == 1);
1444
1445 levels.resize(subresource.levelCount);
1446
1447 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1448 levels[levelNdx] = testTexture.getLevel((int)subresource.baseMipLevel + levelNdx, subresource.baseArrayLayer);
1449
1450 return MovePtr<tcu::Texture3DView>(new tcu::Texture3DView((int)levels.size(), &levels[0]));
1451 }
1452
validateResultImage(const TestTexture & texture,const VkImageViewType imageViewType,const VkImageSubresourceRange & subresource,const tcu::Sampler & sampler,const vk::VkComponentMapping & componentMapping,const tcu::ConstPixelBufferAccess & coordAccess,const tcu::Vec2 & lodBounds,const tcu::LookupPrecision & lookupPrecision,const tcu::Vec4 & lookupScale,const tcu::Vec4 & lookupBias,const tcu::ConstPixelBufferAccess & resultAccess,const tcu::PixelBufferAccess & errorAccess)1453 bool validateResultImage(const TestTexture &texture, const VkImageViewType imageViewType,
1454 const VkImageSubresourceRange &subresource, const tcu::Sampler &sampler,
1455 const vk::VkComponentMapping &componentMapping, const tcu::ConstPixelBufferAccess &coordAccess,
1456 const tcu::Vec2 &lodBounds, const tcu::LookupPrecision &lookupPrecision,
1457 const tcu::Vec4 &lookupScale, const tcu::Vec4 &lookupBias,
1458 const tcu::ConstPixelBufferAccess &resultAccess, const tcu::PixelBufferAccess &errorAccess)
1459 {
1460 std::vector<tcu::ConstPixelBufferAccess> levels;
1461
1462 switch (imageViewType)
1463 {
1464 case VK_IMAGE_VIEW_TYPE_1D:
1465 {
1466 UniquePtr<tcu::Texture1DView> texView(getTexture1DView(texture, subresource, levels));
1467
1468 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision,
1469 lookupScale, lookupBias, resultAccess, errorAccess);
1470 }
1471
1472 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1473 {
1474 UniquePtr<tcu::Texture1DArrayView> texView(getTexture1DArrayView(texture, subresource, levels));
1475
1476 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision,
1477 lookupScale, lookupBias, resultAccess, errorAccess);
1478 }
1479
1480 case VK_IMAGE_VIEW_TYPE_2D:
1481 {
1482 UniquePtr<tcu::Texture2DView> texView(getTexture2DView(texture, subresource, levels));
1483
1484 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision,
1485 lookupScale, lookupBias, resultAccess, errorAccess);
1486 }
1487
1488 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1489 {
1490 UniquePtr<tcu::Texture2DArrayView> texView(getTexture2DArrayView(texture, subresource, levels));
1491
1492 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision,
1493 lookupScale, lookupBias, resultAccess, errorAccess);
1494 }
1495
1496 case VK_IMAGE_VIEW_TYPE_CUBE:
1497 {
1498 UniquePtr<tcu::TextureCubeView> texView(getTextureCubeView(texture, subresource, levels));
1499
1500 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision,
1501 lookupScale, lookupBias, resultAccess, errorAccess);
1502 }
1503
1504 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1505 {
1506 UniquePtr<tcu::TextureCubeArrayView> texView(getTextureCubeArrayView(texture, subresource, levels));
1507
1508 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision,
1509 lookupScale, lookupBias, resultAccess, errorAccess);
1510 }
1511
1512 case VK_IMAGE_VIEW_TYPE_3D:
1513 {
1514 UniquePtr<tcu::Texture3DView> texView(getTexture3DView(texture, subresource, levels));
1515
1516 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision,
1517 lookupScale, lookupBias, resultAccess, errorAccess);
1518 }
1519
1520 default:
1521 DE_ASSERT(false);
1522 return false;
1523 }
1524 }
1525
1526 } // namespace
1527
verifyImage(void)1528 tcu::TestStatus ImageSamplingInstance::verifyImage(void)
1529 {
1530 const VkPhysicalDeviceLimits &limits = m_context.getDeviceProperties().limits;
1531 // \note Color buffer is used to capture coordinates - not sampled texture values
1532 const tcu::TextureFormat colorFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
1533 const tcu::TextureFormat depthStencilFormat; // Undefined depth/stencil format.
1534 const CoordinateCaptureProgram coordCaptureProgram;
1535 const rr::Program rrProgram = coordCaptureProgram.getReferenceProgram();
1536 ReferenceRenderer refRenderer(m_renderSize.x(), m_renderSize.y(), 1, colorFormat, depthStencilFormat, &rrProgram);
1537 const bool useStencilAspect = (m_subresourceRange.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT);
1538
1539 bool compareOkAll = true;
1540
1541 tcu::Vec4 lookupScale(1.0f);
1542 tcu::Vec4 lookupBias(0.0f);
1543
1544 getLookupScaleBias(m_imageFormat, lookupScale, lookupBias, useStencilAspect);
1545
1546 // Render out coordinates
1547 {
1548 const rr::RenderState renderState(refRenderer.getViewportState(),
1549 m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1550 refRenderer.draw(renderState, rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
1551 }
1552
1553 // Verify results
1554 {
1555 const tcu::Sampler sampler = mapVkSampler(m_samplerParams);
1556 const float referenceLod =
1557 de::clamp(m_samplerParams.mipLodBias + m_samplerLod, m_samplerParams.minLod, m_samplerParams.maxLod);
1558 const float lodError = 1.0f / static_cast<float>((1u << limits.mipmapPrecisionBits) - 1u);
1559 const tcu::Vec2 lodBounds(referenceLod - lodError, referenceLod + lodError);
1560 const vk::VkImageSubresourceRange subresource = resolveSubresourceRange(*m_texture, m_subresourceRange);
1561
1562 const tcu::ConstPixelBufferAccess coordAccess = refRenderer.getAccess();
1563 tcu::TextureLevel errorMask(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1564 (int)m_renderSize.x(), (int)m_renderSize.y());
1565 const tcu::PixelBufferAccess errorAccess = errorMask.getAccess();
1566
1567 const bool isNearestOnly =
1568 (m_samplerParams.minFilter == VK_FILTER_NEAREST && m_samplerParams.magFilter == VK_FILTER_NEAREST);
1569
1570 tcu::LookupPrecision lookupPrecision;
1571
1572 // Set precision requirements - very low for these tests as
1573 // the point of the test is not to validate accuracy.
1574 lookupPrecision.coordBits = tcu::IVec3(17, 17, 17);
1575 lookupPrecision.uvwBits = tcu::IVec3(5, 5, 5);
1576 lookupPrecision.colorMask = m_componentMask;
1577 lookupPrecision.colorThreshold =
1578 tcu::computeFixedPointThreshold(max((tcu::IVec4(8, 8, 8, 8) - (isNearestOnly ? 1 : 2)), tcu::IVec4(0))) /
1579 swizzleScaleBias(lookupScale, m_componentMapping, 1.0f);
1580
1581 if (m_imageFormat == VK_FORMAT_BC5_UNORM_BLOCK || m_imageFormat == VK_FORMAT_BC5_SNORM_BLOCK)
1582 lookupPrecision.colorThreshold = tcu::Vec4(0.06f, 0.06f, 0.06f, 0.06f);
1583 if (tcu::isSRGB(m_texture->getTextureFormat()))
1584 lookupPrecision.colorThreshold += tcu::Vec4(4.f / 255.f);
1585
1586 de::MovePtr<TestTexture> textureCopy;
1587 TestTexture *texture = nullptr;
1588
1589 if (isCombinedDepthStencilType(m_texture->getTextureFormat().type))
1590 {
1591 // Verification loop does not support reading from combined depth stencil texture levels.
1592 // Get rid of stencil component.
1593
1594 tcu::TextureFormat::ChannelOrder channelOrder = tcu::TextureFormat::CHANNELORDER_LAST;
1595 tcu::TextureFormat::ChannelType channelType = tcu::TextureFormat::CHANNELTYPE_LAST;
1596
1597 if (subresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
1598 {
1599 channelOrder = tcu::TextureFormat::S;
1600 channelType = tcu::TextureFormat::UNSIGNED_INT8;
1601 }
1602 else
1603 {
1604 channelOrder = tcu::TextureFormat::D;
1605
1606 switch (m_texture->getTextureFormat().type)
1607 {
1608 case tcu::TextureFormat::UNSIGNED_INT_16_8_8:
1609 channelType = tcu::TextureFormat::UNORM_INT16;
1610 break;
1611 case tcu::TextureFormat::UNSIGNED_INT_24_8:
1612 case tcu::TextureFormat::UNSIGNED_INT_24_8_REV:
1613 channelType = tcu::TextureFormat::UNORM_INT24;
1614 break;
1615 case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
1616 channelType = tcu::TextureFormat::FLOAT;
1617 break;
1618 default:
1619 DE_FATAL("Unhandled texture format type in switch");
1620 }
1621 }
1622
1623 textureCopy = m_texture->copy(tcu::TextureFormat(channelOrder, channelType));
1624 texture = textureCopy.get();
1625 }
1626 else
1627 {
1628 texture = m_texture.get();
1629 }
1630
1631 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1632 {
1633 // Read back result image
1634 UniquePtr<tcu::TextureLevel> result(readColorAttachment(
1635 m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueue(),
1636 m_context.getUniversalQueueFamilyIndex(), m_context.getDefaultAllocator(), **m_colorImages[imgNdx],
1637 m_colorFormat, m_renderSize));
1638 const tcu::ConstPixelBufferAccess resultAccess = result->getAccess();
1639 bool compareOk =
1640 validateResultImage(*texture, m_imageViewType, subresource, sampler, m_componentMapping, coordAccess,
1641 lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1642 if (!compareOk)
1643 m_context.getTestContext().getLog() << tcu::TestLog::Image("Result", "Result Image", resultAccess)
1644 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorAccess);
1645
1646 compareOkAll = compareOkAll && compareOk;
1647 }
1648 }
1649
1650 if (compareOkAll)
1651 return tcu::TestStatus::pass("Result image matches reference");
1652 else
1653 return tcu::TestStatus::fail("Image mismatch");
1654 }
1655
1656 } // namespace pipeline
1657 } // namespace vkt
1658