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