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