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