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