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