1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Imagination Technologies Ltd.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Image sampling case
23 *//*--------------------------------------------------------------------*/
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 "tcuTestLog.hpp"
36 #include "deSTLUtil.hpp"
49 de::MovePtr<Allocation> allocateBuffer (const InstanceInterface& vki,
50 const DeviceInterface& vkd,
51 const VkPhysicalDevice& physDevice,
52 const VkDevice device,
53 const VkBuffer& buffer,
54 const MemoryRequirement requirement,
56 AllocationKind allocationKind)
58 switch (allocationKind)
60 case ALLOCATION_KIND_SUBALLOCATED:
62 const VkMemoryRequirements memoryRequirements = getBufferMemoryRequirements(vkd, device, buffer);
64 return allocator.allocate(memoryRequirements, requirement);
67 case ALLOCATION_KIND_DEDICATED:
69 return allocateDedicated(vki, vkd, physDevice, device, buffer, requirement);
74 TCU_THROW(InternalError, "Invalid allocation kind");
79 de::MovePtr<Allocation> allocateImage (const InstanceInterface& vki,
80 const DeviceInterface& vkd,
81 const VkPhysicalDevice& physDevice,
82 const VkDevice device,
84 const MemoryRequirement requirement,
86 AllocationKind allocationKind)
88 switch (allocationKind)
90 case ALLOCATION_KIND_SUBALLOCATED:
92 const VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vkd, device, image);
94 return allocator.allocate(memoryRequirements, requirement);
97 case ALLOCATION_KIND_DEDICATED:
99 return allocateDedicated(vki, vkd, physDevice, device, image, requirement);
104 TCU_THROW(InternalError, "Invalid allocation kind");
109 static VkImageType getCompatibleImageType (VkImageViewType viewType)
113 case VK_IMAGE_VIEW_TYPE_1D: return VK_IMAGE_TYPE_1D;
114 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return VK_IMAGE_TYPE_1D;
115 case VK_IMAGE_VIEW_TYPE_2D: return VK_IMAGE_TYPE_2D;
116 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: return VK_IMAGE_TYPE_2D;
117 case VK_IMAGE_VIEW_TYPE_3D: return VK_IMAGE_TYPE_3D;
118 case VK_IMAGE_VIEW_TYPE_CUBE: return VK_IMAGE_TYPE_2D;
119 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return VK_IMAGE_TYPE_2D;
125 return VK_IMAGE_TYPE_1D;
128 template<typename TcuFormatType>
129 static MovePtr<TestTexture> createTestTexture (const TcuFormatType format, VkImageViewType viewType, const tcu::IVec3& size, int layerCount)
131 MovePtr<TestTexture> texture;
132 const VkImageType imageType = getCompatibleImageType(viewType);
136 case VK_IMAGE_TYPE_1D:
138 texture = MovePtr<TestTexture>(new TestTexture1D(format, size.x()));
140 texture = MovePtr<TestTexture>(new TestTexture1DArray(format, size.x(), layerCount));
144 case VK_IMAGE_TYPE_2D:
147 texture = MovePtr<TestTexture>(new TestTexture2D(format, size.x(), size.y()));
151 if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
153 if (layerCount == tcu::CUBEFACE_LAST && viewType == VK_IMAGE_VIEW_TYPE_CUBE)
155 texture = MovePtr<TestTexture>(new TestTextureCube(format, size.x()));
159 DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0);
161 texture = MovePtr<TestTexture>(new TestTextureCubeArray(format, size.x(), layerCount));
166 texture = MovePtr<TestTexture>(new TestTexture2DArray(format, size.x(), size.y(), layerCount));
172 case VK_IMAGE_TYPE_3D:
173 texture = MovePtr<TestTexture>(new TestTexture3D(format, size.x(), size.y(), size.z()));
185 ImageSamplingInstance::ImageSamplingInstance (Context& context,
186 const tcu::UVec2& renderSize,
187 VkImageViewType imageViewType,
188 VkFormat imageFormat,
189 const tcu::IVec3& imageSize,
191 const VkComponentMapping& componentMapping,
192 const VkImageSubresourceRange& subresourceRange,
193 const VkSamplerCreateInfo& samplerParams,
195 const std::vector<Vertex4Tex4>& vertices,
196 VkDescriptorType samplingType,
198 AllocationKind allocationKind)
199 : vkt::TestInstance (context)
200 , m_allocationKind (allocationKind)
201 , m_samplingType (samplingType)
202 , m_imageViewType (imageViewType)
203 , m_imageFormat (imageFormat)
204 , m_imageSize (imageSize)
205 , m_layerCount (layerCount)
206 , m_imageCount (imageCount)
207 , m_componentMapping (componentMapping)
208 , m_subresourceRange (subresourceRange)
209 , m_samplerParams (samplerParams)
210 , m_samplerLod (samplerLod)
211 , m_renderSize (renderSize)
212 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
213 , m_vertices (vertices)
215 const InstanceInterface& vki = context.getInstanceInterface();
216 const DeviceInterface& vk = context.getDeviceInterface();
217 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
218 const VkDevice vkDevice = context.getDevice();
219 const VkQueue queue = context.getUniversalQueue();
220 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
221 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
222 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
224 if (!isSupportedSamplableFormat(context.getInstanceInterface(), context.getPhysicalDevice(), imageFormat))
225 throw tcu::NotSupportedError(std::string("Unsupported format for sampling: ") + getFormatName(imageFormat));
227 if ((deUint32)imageCount > context.getDeviceProperties().limits.maxColorAttachments)
228 throw tcu::NotSupportedError(std::string("Unsupported render target count: ") + de::toString(imageCount));
230 if ((samplerParams.minFilter == VK_FILTER_LINEAR ||
231 samplerParams.magFilter == VK_FILTER_LINEAR ||
232 samplerParams.mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR) &&
233 !isLinearFilteringSupported(context.getInstanceInterface(), context.getPhysicalDevice(), imageFormat, VK_IMAGE_TILING_OPTIMAL))
234 throw tcu::NotSupportedError(std::string("Unsupported format for linear filtering: ") + getFormatName(imageFormat));
236 if ((samplerParams.addressModeU == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE ||
237 samplerParams.addressModeV == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE ||
238 samplerParams.addressModeW == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE) &&
239 !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_sampler_mirror_clamp_to_edge"))
240 TCU_THROW(NotSupportedError, "VK_KHR_sampler_mirror_clamp_to_edge not supported");
242 if (isCompressedFormat(imageFormat) && imageViewType == VK_IMAGE_VIEW_TYPE_3D)
244 // \todo [2016-01-22 pyry] Mandate VK_ERROR_FORMAT_NOT_SUPPORTED
247 const VkImageFormatProperties formatProperties = getPhysicalDeviceImageFormatProperties(context.getInstanceInterface(),
248 context.getPhysicalDevice(),
251 VK_IMAGE_TILING_OPTIMAL,
252 VK_IMAGE_USAGE_SAMPLED_BIT,
253 (VkImageCreateFlags)0);
255 if (formatProperties.maxExtent.width == 0 &&
256 formatProperties.maxExtent.height == 0 &&
257 formatProperties.maxExtent.depth == 0)
258 TCU_THROW(NotSupportedError, "3D compressed format not supported");
262 TCU_THROW(NotSupportedError, "3D compressed format not supported");
266 if (imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY && !context.getDeviceFeatures().imageCubeArray)
267 TCU_THROW(NotSupportedError, "imageCubeArray feature is not supported");
269 if (m_allocationKind == ALLOCATION_KIND_DEDICATED)
271 const std::string extensionName("VK_KHR_dedicated_allocation");
273 if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), extensionName))
274 TCU_THROW(NotSupportedError, std::string(extensionName + " is not supported").c_str());
277 // Create texture images, views and samplers
279 VkImageCreateFlags imageFlags = 0u;
281 if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
282 imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
284 // Initialize texture data
285 if (isCompressedFormat(imageFormat))
286 m_texture = createTestTexture(mapVkCompressedFormat(imageFormat), imageViewType, imageSize, layerCount);
288 m_texture = createTestTexture(mapVkFormat(imageFormat), imageViewType, imageSize, layerCount);
290 const VkImageCreateInfo imageParams =
292 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
293 DE_NULL, // const void* pNext;
294 imageFlags, // VkImageCreateFlags flags;
295 getCompatibleImageType(m_imageViewType), // VkImageType imageType;
296 imageFormat, // VkFormat format;
297 { // VkExtent3D extent;
298 (deUint32)m_imageSize.x(),
299 (deUint32)m_imageSize.y(),
300 (deUint32)m_imageSize.z()
302 (deUint32)m_texture->getNumLevels(), // deUint32 mipLevels;
303 (deUint32)m_layerCount, // deUint32 arrayLayers;
304 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
305 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
306 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
307 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
308 1u, // deUint32 queueFamilyIndexCount;
309 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
310 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
313 m_images.resize(m_imageCount);
314 m_imageAllocs.resize(m_imageCount);
315 m_imageViews.resize(m_imageCount);
317 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
319 m_images[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &imageParams)));
320 m_imageAllocs[imgNdx] = SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_images[imgNdx], MemoryRequirement::Any, memAlloc, m_allocationKind)));
321 VK_CHECK(vk.bindImageMemory(vkDevice, **m_images[imgNdx], (*m_imageAllocs[imgNdx])->getMemory(), (*m_imageAllocs[imgNdx])->getOffset()));
323 // Upload texture data
324 uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, **m_images[imgNdx]);
326 // Create image view and sampler
327 const VkImageViewCreateInfo imageViewParams =
329 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
330 DE_NULL, // const void* pNext;
331 0u, // VkImageViewCreateFlags flags;
332 **m_images[imgNdx], // VkImage image;
333 m_imageViewType, // VkImageViewType viewType;
334 imageFormat, // VkFormat format;
335 m_componentMapping, // VkComponentMapping components;
336 m_subresourceRange, // VkImageSubresourceRange subresourceRange;
339 m_imageViews[imgNdx] = SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &imageViewParams)));
342 m_sampler = createSampler(vk, vkDevice, &m_samplerParams);
345 // Create descriptor set for image and sampler
347 DescriptorPoolBuilder descriptorPoolBuilder;
348 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
349 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 1u);
350 descriptorPoolBuilder.addType(m_samplingType, m_imageCount);
351 m_descriptorPool = descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
352 m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? m_imageCount + 1u : m_imageCount);
354 DescriptorSetLayoutBuilder setLayoutBuilder;
355 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
356 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
357 setLayoutBuilder.addArrayBinding(m_samplingType, m_imageCount, VK_SHADER_STAGE_FRAGMENT_BIT);
358 m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice);
360 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
362 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
363 DE_NULL, // const void* pNext;
364 *m_descriptorPool, // VkDescriptorPool descriptorPool;
365 1u, // deUint32 setLayoutCount;
366 &m_descriptorSetLayout.get() // const VkDescriptorSetLayout* pSetLayouts;
369 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
371 const VkSampler sampler = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? DE_NULL : *m_sampler;
372 std::vector<VkDescriptorImageInfo> descriptorImageInfo(m_imageCount);
373 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
375 descriptorImageInfo[imgNdx].sampler = sampler; // VkSampler sampler;
376 descriptorImageInfo[imgNdx].imageView = **m_imageViews[imgNdx]; // VkImageView imageView;
377 descriptorImageInfo[imgNdx].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; // VkImageLayout imageLayout;
380 DescriptorSetUpdateBuilder setUpdateBuilder;
381 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
383 const VkDescriptorImageInfo descriptorSamplerInfo =
385 *m_sampler, // VkSampler sampler;
386 DE_NULL, // VkImageView imageView;
387 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout;
389 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_SAMPLER, &descriptorSamplerInfo);
392 const deUint32 binding = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? 1u : 0u;
393 setUpdateBuilder.writeArray(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(binding), m_samplingType, m_imageCount, descriptorImageInfo.data());
394 setUpdateBuilder.update(vk, vkDevice);
397 // Create color images and views
399 const VkImageCreateInfo colorImageParams =
401 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
402 DE_NULL, // const void* pNext;
403 0u, // VkImageCreateFlags flags;
404 VK_IMAGE_TYPE_2D, // VkImageType imageType;
405 m_colorFormat, // VkFormat format;
406 { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u }, // VkExtent3D extent;
407 1u, // deUint32 mipLevels;
408 1u, // deUint32 arrayLayers;
409 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
410 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
411 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
412 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
413 1u, // deUint32 queueFamilyIndexCount;
414 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
415 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
418 m_colorImages.resize(m_imageCount);
419 m_colorImageAllocs.resize(m_imageCount);
420 m_colorAttachmentViews.resize(m_imageCount);
422 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
424 m_colorImages[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &colorImageParams)));
425 m_colorImageAllocs[imgNdx] = SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_colorImages[imgNdx], MemoryRequirement::Any, memAlloc, m_allocationKind)));
426 VK_CHECK(vk.bindImageMemory(vkDevice, **m_colorImages[imgNdx], (*m_colorImageAllocs[imgNdx])->getMemory(), (*m_colorImageAllocs[imgNdx])->getOffset()));
428 const VkImageViewCreateInfo colorAttachmentViewParams =
430 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
431 DE_NULL, // const void* pNext;
432 0u, // VkImageViewCreateFlags flags;
433 **m_colorImages[imgNdx], // VkImage image;
434 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
435 m_colorFormat, // VkFormat format;
436 componentMappingRGBA, // VkComponentMapping components;
437 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
440 m_colorAttachmentViews[imgNdx] = SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &colorAttachmentViewParams)));
444 // Create render pass
446 std::vector<VkAttachmentDescription> colorAttachmentDescriptions(m_imageCount);
447 std::vector<VkAttachmentReference> colorAttachmentReferences(m_imageCount);
449 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
451 colorAttachmentDescriptions[imgNdx].flags = 0u; // VkAttachmentDescriptionFlags flags;
452 colorAttachmentDescriptions[imgNdx].format = m_colorFormat; // VkFormat format;
453 colorAttachmentDescriptions[imgNdx].samples = VK_SAMPLE_COUNT_1_BIT; // VkSampleCountFlagBits samples;
454 colorAttachmentDescriptions[imgNdx].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // VkAttachmentLoadOp loadOp;
455 colorAttachmentDescriptions[imgNdx].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // VkAttachmentStoreOp storeOp;
456 colorAttachmentDescriptions[imgNdx].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // VkAttachmentLoadOp stencilLoadOp;
457 colorAttachmentDescriptions[imgNdx].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // VkAttachmentStoreOp stencilStoreOp;
458 colorAttachmentDescriptions[imgNdx].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout initialLayout;
459 colorAttachmentDescriptions[imgNdx].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout finalLayout;
461 colorAttachmentReferences[imgNdx].attachment = (deUint32)imgNdx; // deUint32 attachment;
462 colorAttachmentReferences[imgNdx].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout layout;
465 const VkSubpassDescription subpassDescription =
467 0u, // VkSubpassDescriptionFlags flags;
468 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
469 0u, // deUint32 inputAttachmentCount;
470 DE_NULL, // const VkAttachmentReference* pInputAttachments;
471 (deUint32)m_imageCount, // deUint32 colorAttachmentCount;
472 &colorAttachmentReferences[0], // const VkAttachmentReference* pColorAttachments;
473 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
474 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
475 0u, // deUint32 preserveAttachmentCount;
476 DE_NULL // const VkAttachmentReference* pPreserveAttachments;
479 const VkRenderPassCreateInfo renderPassParams =
481 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
482 DE_NULL, // const void* pNext;
483 0u, // VkRenderPassCreateFlags flags;
484 (deUint32)m_imageCount, // deUint32 attachmentCount;
485 &colorAttachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
486 1u, // deUint32 subpassCount;
487 &subpassDescription, // const VkSubpassDescription* pSubpasses;
488 0u, // deUint32 dependencyCount;
489 DE_NULL // const VkSubpassDependency* pDependencies;
492 m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
495 // Create framebuffer
497 std::vector<VkImageView> pAttachments(m_imageCount);
498 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
499 pAttachments[imgNdx] = m_colorAttachmentViews[imgNdx]->get();
501 const VkFramebufferCreateInfo framebufferParams =
503 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
504 DE_NULL, // const void* pNext;
505 0u, // VkFramebufferCreateFlags flags;
506 *m_renderPass, // VkRenderPass renderPass;
507 (deUint32)m_imageCount, // deUint32 attachmentCount;
508 &pAttachments[0], // const VkImageView* pAttachments;
509 (deUint32)m_renderSize.x(), // deUint32 width;
510 (deUint32)m_renderSize.y(), // deUint32 height;
511 1u // deUint32 layers;
514 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
517 // Create pipeline layout
519 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
521 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
522 DE_NULL, // const void* pNext;
523 0u, // VkPipelineLayoutCreateFlags flags;
524 1u, // deUint32 setLayoutCount;
525 &m_descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
526 0u, // deUint32 pushConstantRangeCount;
527 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
530 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
533 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0);
534 m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0);
538 const VkPipelineShaderStageCreateInfo shaderStages[2] =
541 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
542 DE_NULL, // const void* pNext;
543 0u, // VkPipelineShaderStageCreateFlags flags;
544 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
545 *m_vertexShaderModule, // VkShaderModule module;
546 "main", // const char* pName;
547 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
550 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
551 DE_NULL, // const void* pNext;
552 0u, // VkPipelineShaderStageCreateFlags flags;
553 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
554 *m_fragmentShaderModule, // VkShaderModule module;
555 "main", // const char* pName;
556 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
560 const VkVertexInputBindingDescription vertexInputBindingDescription =
562 0u, // deUint32 binding;
563 sizeof(Vertex4Tex4), // deUint32 strideInBytes;
564 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
567 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
570 0u, // deUint32 location;
571 0u, // deUint32 binding;
572 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
573 0u // deUint32 offset;
576 1u, // deUint32 location;
577 0u, // deUint32 binding;
578 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
579 DE_OFFSET_OF(Vertex4Tex4, texCoord), // deUint32 offset;
583 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
585 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
586 DE_NULL, // const void* pNext;
587 0u, // VkPipelineVertexInputStateCreateFlags flags;
588 1u, // deUint32 vertexBindingDescriptionCount;
589 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
590 2u, // deUint32 vertexAttributeDescriptionCount;
591 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
594 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
596 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
597 DE_NULL, // const void* pNext;
598 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
599 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
600 false // VkBool32 primitiveRestartEnable;
603 const VkViewport viewport =
607 (float)m_renderSize.x(), // float width;
608 (float)m_renderSize.y(), // float height;
609 0.0f, // float minDepth;
610 1.0f // float maxDepth;
613 const VkRect2D scissor = { { 0, 0 }, { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() } };
615 const VkPipelineViewportStateCreateInfo viewportStateParams =
617 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
618 DE_NULL, // const void* pNext;
619 0u, // VkPipelineViewportStateCreateFlags flags;
620 1u, // deUint32 viewportCount;
621 &viewport, // const VkViewport* pViewports;
622 1u, // deUint32 scissorCount;
623 &scissor // const VkRect2D* pScissors;
626 const VkPipelineRasterizationStateCreateInfo rasterStateParams =
628 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
629 DE_NULL, // const void* pNext;
630 0u, // VkPipelineRasterizationStateCreateFlags flags;
631 false, // VkBool32 depthClampEnable;
632 false, // VkBool32 rasterizerDiscardEnable;
633 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
634 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
635 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
636 false, // VkBool32 depthBiasEnable;
637 0.0f, // float depthBiasConstantFactor;
638 0.0f, // float depthBiasClamp;
639 0.0f, // float depthBiasSlopeFactor;
640 1.0f // float lineWidth;
643 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates(m_imageCount);
645 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
647 colorBlendAttachmentStates[imgNdx].blendEnable = false; // VkBool32 blendEnable;
648 colorBlendAttachmentStates[imgNdx].srcColorBlendFactor = VK_BLEND_FACTOR_ONE; // VkBlendFactor srcColorBlendFactor;
649 colorBlendAttachmentStates[imgNdx].dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // VkBlendFactor dstColorBlendFactor;
650 colorBlendAttachmentStates[imgNdx].colorBlendOp = VK_BLEND_OP_ADD; // VkBlendOp colorBlendOp;
651 colorBlendAttachmentStates[imgNdx].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; // VkBlendFactor srcAlphaBlendFactor;
652 colorBlendAttachmentStates[imgNdx].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // VkBlendFactor dstAlphaBlendFactor;
653 colorBlendAttachmentStates[imgNdx].alphaBlendOp = VK_BLEND_OP_ADD; // VkBlendOp alphaBlendOp;
654 colorBlendAttachmentStates[imgNdx].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
655 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
658 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
660 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
661 DE_NULL, // const void* pNext;
662 0u, // VkPipelineColorBlendStateCreateFlags flags;
663 false, // VkBool32 logicOpEnable;
664 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
665 (deUint32)m_imageCount, // deUint32 attachmentCount;
666 &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState* pAttachments;
667 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4];
670 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
672 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
673 DE_NULL, // const void* pNext;
674 0u, // VkPipelineMultisampleStateCreateFlags flags;
675 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
676 false, // VkBool32 sampleShadingEnable;
677 0.0f, // float minSampleShading;
678 DE_NULL, // const VkSampleMask* pSampleMask;
679 false, // VkBool32 alphaToCoverageEnable;
680 false // VkBool32 alphaToOneEnable;
683 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
685 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
686 DE_NULL, // const void* pNext;
687 0u, // VkPipelineDepthStencilStateCreateFlags flags;
688 false, // VkBool32 depthTestEnable;
689 false, // VkBool32 depthWriteEnable;
690 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
691 false, // VkBool32 depthBoundsTestEnable;
692 false, // VkBool32 stencilTestEnable;
693 { // VkStencilOpState front;
694 VK_STENCIL_OP_ZERO, // VkStencilOp failOp;
695 VK_STENCIL_OP_ZERO, // VkStencilOp passOp;
696 VK_STENCIL_OP_ZERO, // VkStencilOp depthFailOp;
697 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
698 0u, // deUint32 compareMask;
699 0u, // deUint32 writeMask;
700 0u // deUint32 reference;
702 { // VkStencilOpState back;
703 VK_STENCIL_OP_ZERO, // VkStencilOp failOp;
704 VK_STENCIL_OP_ZERO, // VkStencilOp passOp;
705 VK_STENCIL_OP_ZERO, // VkStencilOp depthFailOp;
706 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
707 0u, // deUint32 compareMask;
708 0u, // deUint32 writeMask;
709 0u // deUint32 reference;
711 0.0f, // float minDepthBounds;
712 1.0f // float maxDepthBounds;
715 const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
717 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
718 DE_NULL, // const void* pNext;
719 0u, // VkPipelineCreateFlags flags;
720 2u, // deUint32 stageCount;
721 shaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
722 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
723 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
724 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
725 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
726 &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
727 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
728 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
729 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
730 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
731 *m_pipelineLayout, // VkPipelineLayout layout;
732 *m_renderPass, // VkRenderPass renderPass;
733 0u, // deUint32 subpass;
734 0u, // VkPipeline basePipelineHandle;
735 0u // deInt32 basePipelineIndex;
738 m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
741 // Create vertex buffer
743 const VkDeviceSize vertexBufferSize = (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4));
744 const VkBufferCreateInfo vertexBufferParams =
746 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
747 DE_NULL, // const void* pNext;
748 0u, // VkBufferCreateFlags flags;
749 vertexBufferSize, // VkDeviceSize size;
750 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
751 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
752 1u, // deUint32 queueFamilyIndexCount;
753 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
756 DE_ASSERT(vertexBufferSize > 0);
758 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
759 m_vertexBufferAlloc = allocateBuffer(vki, vk, physDevice, vkDevice, *m_vertexBuffer, MemoryRequirement::HostVisible, memAlloc, m_allocationKind);
760 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
762 // Load vertices into vertex buffer
763 deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize);
764 flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexBufferParams.size);
767 // Create command pool
768 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
770 // Create command buffer
772 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
774 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
775 DE_NULL, // const void* pNext;
776 0u, // VkCommandBufferUsageFlags flags;
777 (const VkCommandBufferInheritanceInfo*)DE_NULL,
780 const std::vector<VkClearValue> attachmentClearValues (m_imageCount, defaultClearValue(m_colorFormat));
782 const VkRenderPassBeginInfo renderPassBeginInfo =
784 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
785 DE_NULL, // const void* pNext;
786 *m_renderPass, // VkRenderPass renderPass;
787 *m_framebuffer, // VkFramebuffer framebuffer;
790 { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }
791 }, // VkRect2D renderArea;
792 static_cast<deUint32>(attachmentClearValues.size()), // deUint32 clearValueCount;
793 &attachmentClearValues[0] // const VkClearValue* pClearValues;
796 std::vector<VkImageMemoryBarrier> preAttachmentBarriers(m_imageCount);
798 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
800 preAttachmentBarriers[imgNdx].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; // VkStructureType sType;
801 preAttachmentBarriers[imgNdx].pNext = DE_NULL; // const void* pNext;
802 preAttachmentBarriers[imgNdx].srcAccessMask = 0u; // VkAccessFlags srcAccessMask;
803 preAttachmentBarriers[imgNdx].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; // VkAccessFlags dstAccessMask;
804 preAttachmentBarriers[imgNdx].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; // VkImageLayout oldLayout;
805 preAttachmentBarriers[imgNdx].newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout newLayout;
806 preAttachmentBarriers[imgNdx].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // deUint32 srcQueueFamilyIndex;
807 preAttachmentBarriers[imgNdx].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // deUint32 dstQueueFamilyIndex;
808 preAttachmentBarriers[imgNdx].image = **m_colorImages[imgNdx]; // VkImage image;
809 preAttachmentBarriers[imgNdx].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; // VkImageSubresourceRange subresourceRange;
810 preAttachmentBarriers[imgNdx].subresourceRange.baseMipLevel = 0u;
811 preAttachmentBarriers[imgNdx].subresourceRange.levelCount = 1u;
812 preAttachmentBarriers[imgNdx].subresourceRange.baseArrayLayer = 0u;
813 preAttachmentBarriers[imgNdx].subresourceRange.layerCount = 1u;
816 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
818 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
820 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
821 0u, DE_NULL, 0u, DE_NULL, (deUint32)m_imageCount, &preAttachmentBarriers[0]);
823 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
825 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
827 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
829 const VkDeviceSize vertexBufferOffset = 0;
830 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
831 vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
833 vk.cmdEndRenderPass(*m_cmdBuffer);
834 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
838 m_fence = createFence(vk, vkDevice);
841 ImageSamplingInstance::~ImageSamplingInstance (void)
845 tcu::TestStatus ImageSamplingInstance::iterate (void)
847 const DeviceInterface& vk = m_context.getDeviceInterface();
848 const VkDevice vkDevice = m_context.getDevice();
849 const VkQueue queue = m_context.getUniversalQueue();
850 const VkSubmitInfo submitInfo =
852 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
853 DE_NULL, // const void* pNext;
854 0u, // deUint32 waitSemaphoreCount;
855 DE_NULL, // const VkSemaphore* pWaitSemaphores;
857 1u, // deUint32 commandBufferCount;
858 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
859 0u, // deUint32 signalSemaphoreCount;
860 DE_NULL // const VkSemaphore* pSignalSemaphores;
863 VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
864 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
865 VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
867 return verifyImage();
873 bool isLookupResultValid (const tcu::Texture1DView& texture,
874 const tcu::Sampler& sampler,
875 const tcu::LookupPrecision& precision,
876 const tcu::Vec4& coords,
877 const tcu::Vec2& lodBounds,
878 const tcu::Vec4& result)
880 return tcu::isLookupResultValid(texture, sampler, precision, coords.x(), lodBounds, result);
883 bool isLookupResultValid (const tcu::Texture1DArrayView& texture,
884 const tcu::Sampler& sampler,
885 const tcu::LookupPrecision& precision,
886 const tcu::Vec4& coords,
887 const tcu::Vec2& lodBounds,
888 const tcu::Vec4& result)
890 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1), lodBounds, result);
893 bool isLookupResultValid (const tcu::Texture2DView& texture,
894 const tcu::Sampler& sampler,
895 const tcu::LookupPrecision& precision,
896 const tcu::Vec4& coords,
897 const tcu::Vec2& lodBounds,
898 const tcu::Vec4& result)
900 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1), lodBounds, result);
903 bool isLookupResultValid (const tcu::Texture2DArrayView& texture,
904 const tcu::Sampler& sampler,
905 const tcu::LookupPrecision& precision,
906 const tcu::Vec4& coords,
907 const tcu::Vec2& lodBounds,
908 const tcu::Vec4& result)
910 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result);
913 bool isLookupResultValid (const tcu::TextureCubeView& texture,
914 const tcu::Sampler& sampler,
915 const tcu::LookupPrecision& precision,
916 const tcu::Vec4& coords,
917 const tcu::Vec2& lodBounds,
918 const tcu::Vec4& result)
920 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result);
923 bool isLookupResultValid (const tcu::TextureCubeArrayView& texture,
924 const tcu::Sampler& sampler,
925 const tcu::LookupPrecision& precision,
926 const tcu::Vec4& coords,
927 const tcu::Vec2& lodBounds,
928 const tcu::Vec4& result)
930 return tcu::isLookupResultValid(texture, sampler, precision, tcu::IVec4(precision.coordBits.x()), coords, lodBounds, result);
933 bool isLookupResultValid(const tcu::Texture3DView& texture,
934 const tcu::Sampler& sampler,
935 const tcu::LookupPrecision& precision,
936 const tcu::Vec4& coords,
937 const tcu::Vec2& lodBounds,
938 const tcu::Vec4& result)
940 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result);
943 template<typename TextureViewType>
944 bool validateResultImage (const TextureViewType& texture,
945 const tcu::Sampler& sampler,
946 const tcu::ConstPixelBufferAccess& texCoords,
947 const tcu::Vec2& lodBounds,
948 const tcu::LookupPrecision& lookupPrecision,
949 const tcu::Vec4& lookupScale,
950 const tcu::Vec4& lookupBias,
951 const tcu::ConstPixelBufferAccess& result,
952 const tcu::PixelBufferAccess& errorMask)
954 const int w = result.getWidth();
955 const int h = result.getHeight();
958 for (int y = 0; y < h; ++y)
960 for (int x = 0; x < w; ++x)
962 const tcu::Vec4 resultPixel = result.getPixel(x, y);
963 const tcu::Vec4 resultColor = (resultPixel - lookupBias) / lookupScale;
964 const tcu::Vec4 texCoord = texCoords.getPixel(x, y);
965 const bool pixelOk = isLookupResultValid(texture, sampler, lookupPrecision, texCoord, lodBounds, resultColor);
967 errorMask.setPixel(tcu::Vec4(pixelOk?0.0f:1.0f, pixelOk?1.0f:0.0f, 0.0f, 1.0f), x, y);
977 template<typename ScalarType>
978 ScalarType getSwizzledComp (const tcu::Vector<ScalarType, 4>& vec, vk::VkComponentSwizzle comp, int identityNdx)
980 if (comp == vk::VK_COMPONENT_SWIZZLE_IDENTITY)
981 return vec[identityNdx];
982 else if (comp == vk::VK_COMPONENT_SWIZZLE_ZERO)
983 return ScalarType(0);
984 else if (comp == vk::VK_COMPONENT_SWIZZLE_ONE)
985 return ScalarType(1);
987 return vec[comp - vk::VK_COMPONENT_SWIZZLE_R];
990 template<typename ScalarType>
991 tcu::Vector<ScalarType, 4> swizzle (const tcu::Vector<ScalarType, 4>& vec, const vk::VkComponentMapping& swz)
993 return tcu::Vector<ScalarType, 4>(getSwizzledComp(vec, swz.r, 0),
994 getSwizzledComp(vec, swz.g, 1),
995 getSwizzledComp(vec, swz.b, 2),
996 getSwizzledComp(vec, swz.a, 3));
999 tcu::Vec4 swizzleScaleBias (const tcu::Vec4& vec, const vk::VkComponentMapping& swz)
1001 const float channelValues[] =
1012 return tcu::Vec4(channelValues[swz.r], channelValues[swz.g], channelValues[swz.b], channelValues[swz.a]);
1015 template<typename ScalarType>
1016 void swizzleT (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)
1018 for (int z = 0; z < dst.getDepth(); ++z)
1019 for (int y = 0; y < dst.getHeight(); ++y)
1020 for (int x = 0; x < dst.getWidth(); ++x)
1021 dst.setPixel(swizzle(src.getPixelT<ScalarType>(x, y, z), swz), x, y, z);
1024 void swizzleFromSRGB (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)
1026 for (int z = 0; z < dst.getDepth(); ++z)
1027 for (int y = 0; y < dst.getHeight(); ++y)
1028 for (int x = 0; x < dst.getWidth(); ++x)
1029 dst.setPixel(swizzle(tcu::sRGBToLinear(src.getPixelT<float>(x, y, z)), swz), x, y, z);
1032 void swizzle (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)
1034 const tcu::TextureChannelClass chnClass = tcu::getTextureChannelClass(dst.getFormat().type);
1036 DE_ASSERT(src.getWidth() == dst.getWidth() &&
1037 src.getHeight() == dst.getHeight() &&
1038 src.getDepth() == dst.getDepth());
1040 if (chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1041 swizzleT<deInt32>(src, dst, swz);
1042 else if (chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1043 swizzleT<deUint32>(src, dst, swz);
1044 else if (tcu::isSRGB(src.getFormat()) && !tcu::isSRGB(dst.getFormat()))
1045 swizzleFromSRGB(src, dst, swz);
1047 swizzleT<float>(src, dst, swz);
1050 bool isIdentitySwizzle (const vk::VkComponentMapping& swz)
1052 return (swz.r == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.r == vk::VK_COMPONENT_SWIZZLE_R) &&
1053 (swz.g == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.g == vk::VK_COMPONENT_SWIZZLE_G) &&
1054 (swz.b == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.b == vk::VK_COMPONENT_SWIZZLE_B) &&
1055 (swz.a == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.a == vk::VK_COMPONENT_SWIZZLE_A);
1058 template<typename TextureViewType> struct TexViewTraits;
1060 template<> struct TexViewTraits<tcu::Texture1DView> { typedef tcu::Texture1D TextureType; };
1061 template<> struct TexViewTraits<tcu::Texture1DArrayView> { typedef tcu::Texture1DArray TextureType; };
1062 template<> struct TexViewTraits<tcu::Texture2DView> { typedef tcu::Texture2D TextureType; };
1063 template<> struct TexViewTraits<tcu::Texture2DArrayView> { typedef tcu::Texture2DArray TextureType; };
1064 template<> struct TexViewTraits<tcu::TextureCubeView> { typedef tcu::TextureCube TextureType; };
1065 template<> struct TexViewTraits<tcu::TextureCubeArrayView> { typedef tcu::TextureCubeArray TextureType; };
1066 template<> struct TexViewTraits<tcu::Texture3DView> { typedef tcu::Texture3D TextureType; };
1068 template<typename TextureViewType>
1069 typename TexViewTraits<TextureViewType>::TextureType* createSkeletonClone (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0);
1071 tcu::TextureFormat getSwizzleTargetFormat (tcu::TextureFormat format)
1073 // Swizzled texture needs to hold all four channels
1074 // \todo [2016-09-21 pyry] We could save some memory by using smaller formats
1075 // when possible (for example U8).
1077 const tcu::TextureChannelClass chnClass = tcu::getTextureChannelClass(format.type);
1079 if (chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1080 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
1081 else if (chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1082 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
1084 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
1088 tcu::Texture1D* createSkeletonClone<tcu::Texture1DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1090 return new tcu::Texture1D(format, level0.getWidth());
1094 tcu::Texture1DArray* createSkeletonClone<tcu::Texture1DArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1096 return new tcu::Texture1DArray(format, level0.getWidth(), level0.getHeight());
1100 tcu::Texture2D* createSkeletonClone<tcu::Texture2DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1102 return new tcu::Texture2D(format, level0.getWidth(), level0.getHeight());
1106 tcu::Texture2DArray* createSkeletonClone<tcu::Texture2DArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1108 return new tcu::Texture2DArray(format, level0.getWidth(), level0.getHeight(), level0.getDepth());
1112 tcu::Texture3D* createSkeletonClone<tcu::Texture3DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1114 return new tcu::Texture3D(format, level0.getWidth(), level0.getHeight(), level0.getDepth());
1118 tcu::TextureCubeArray* createSkeletonClone<tcu::TextureCubeArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1120 return new tcu::TextureCubeArray(format, level0.getWidth(), level0.getDepth());
1123 template<typename TextureViewType>
1124 MovePtr<typename TexViewTraits<TextureViewType>::TextureType> createSwizzledCopy (const TextureViewType& texture, const vk::VkComponentMapping& swz)
1126 MovePtr<typename TexViewTraits<TextureViewType>::TextureType> copy (createSkeletonClone<TextureViewType>(getSwizzleTargetFormat(texture.getLevel(0).getFormat()), texture.getLevel(0)));
1128 for (int levelNdx = 0; levelNdx < texture.getNumLevels(); ++levelNdx)
1130 copy->allocLevel(levelNdx);
1131 swizzle(texture.getLevel(levelNdx), copy->getLevel(levelNdx), swz);
1138 MovePtr<tcu::TextureCube> createSwizzledCopy (const tcu::TextureCubeView& texture, const vk::VkComponentMapping& swz)
1140 MovePtr<tcu::TextureCube> copy (new tcu::TextureCube(getSwizzleTargetFormat(texture.getLevelFace(0, tcu::CUBEFACE_NEGATIVE_X).getFormat()), texture.getSize()));
1142 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1144 for (int levelNdx = 0; levelNdx < texture.getNumLevels(); ++levelNdx)
1146 copy->allocLevel((tcu::CubeFace)faceNdx, levelNdx);
1147 swizzle(texture.getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), copy->getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), swz);
1154 template<typename TextureViewType>
1155 bool validateResultImage (const TextureViewType& texture,
1156 const tcu::Sampler& sampler,
1157 const vk::VkComponentMapping& swz,
1158 const tcu::ConstPixelBufferAccess& texCoords,
1159 const tcu::Vec2& lodBounds,
1160 const tcu::LookupPrecision& lookupPrecision,
1161 const tcu::Vec4& lookupScale,
1162 const tcu::Vec4& lookupBias,
1163 const tcu::ConstPixelBufferAccess& result,
1164 const tcu::PixelBufferAccess& errorMask)
1166 if (isIdentitySwizzle(swz))
1167 return validateResultImage(texture, sampler, texCoords, lodBounds, lookupPrecision, lookupScale, lookupBias, result, errorMask);
1170 // There is (currently) no way to handle swizzling inside validation loop
1171 // and thus we need to pre-swizzle the texture.
1172 UniquePtr<typename TexViewTraits<TextureViewType>::TextureType> swizzledTex (createSwizzledCopy(texture, swz));
1174 return validateResultImage(*swizzledTex, sampler, texCoords, lodBounds, lookupPrecision, swizzleScaleBias(lookupScale, swz), swizzleScaleBias(lookupBias, swz), result, errorMask);
1178 vk::VkImageSubresourceRange resolveSubresourceRange (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource)
1180 vk::VkImageSubresourceRange resolved = subresource;
1182 if (subresource.levelCount == VK_REMAINING_MIP_LEVELS)
1183 resolved.levelCount = testTexture.getNumLevels()-subresource.baseMipLevel;
1185 if (subresource.layerCount == VK_REMAINING_ARRAY_LAYERS)
1186 resolved.layerCount = testTexture.getArraySize()-subresource.baseArrayLayer;
1191 MovePtr<tcu::Texture1DView> getTexture1DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1193 DE_ASSERT(subresource.layerCount == 1);
1195 levels.resize(subresource.levelCount);
1197 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1199 const tcu::ConstPixelBufferAccess& srcLevel = testTexture.getLevel((int)subresource.baseMipLevel+levelNdx, subresource.baseArrayLayer);
1201 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, 0, srcLevel.getWidth(), 1, 1);
1204 return MovePtr<tcu::Texture1DView>(new tcu::Texture1DView((int)levels.size(), &levels[0]));
1207 MovePtr<tcu::Texture1DArrayView> getTexture1DArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1209 const TestTexture1D* tex1D = dynamic_cast<const TestTexture1D*>(&testTexture);
1210 const TestTexture1DArray* tex1DArray = dynamic_cast<const TestTexture1DArray*>(&testTexture);
1212 DE_ASSERT(!!tex1D != !!tex1DArray);
1213 DE_ASSERT(tex1DArray || subresource.baseArrayLayer == 0);
1215 levels.resize(subresource.levelCount);
1217 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1219 const tcu::ConstPixelBufferAccess& srcLevel = tex1D ? tex1D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1220 : tex1DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1222 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, (int)subresource.baseArrayLayer, 0, srcLevel.getWidth(), (int)subresource.layerCount, 1);
1225 return MovePtr<tcu::Texture1DArrayView>(new tcu::Texture1DArrayView((int)levels.size(), &levels[0]));
1228 MovePtr<tcu::Texture2DView> getTexture2DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1230 const TestTexture2D* tex2D = dynamic_cast<const TestTexture2D*>(&testTexture);
1231 const TestTexture2DArray* tex2DArray = dynamic_cast<const TestTexture2DArray*>(&testTexture);
1233 DE_ASSERT(subresource.layerCount == 1);
1234 DE_ASSERT(!!tex2D != !!tex2DArray);
1235 DE_ASSERT(tex2DArray || subresource.baseArrayLayer == 0);
1237 levels.resize(subresource.levelCount);
1239 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1241 const tcu::ConstPixelBufferAccess& srcLevel = tex2D ? tex2D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1242 : tex2DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1244 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), 1);
1247 return MovePtr<tcu::Texture2DView>(new tcu::Texture2DView((int)levels.size(), &levels[0]));
1250 MovePtr<tcu::Texture2DArrayView> getTexture2DArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1252 const TestTexture2D* tex2D = dynamic_cast<const TestTexture2D*>(&testTexture);
1253 const TestTexture2DArray* tex2DArray = dynamic_cast<const TestTexture2DArray*>(&testTexture);
1255 DE_ASSERT(!!tex2D != !!tex2DArray);
1256 DE_ASSERT(tex2DArray || subresource.baseArrayLayer == 0);
1258 levels.resize(subresource.levelCount);
1260 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1262 const tcu::ConstPixelBufferAccess& srcLevel = tex2D ? tex2D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1263 : tex2DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1265 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), (int)subresource.layerCount);
1268 return MovePtr<tcu::Texture2DArrayView>(new tcu::Texture2DArrayView((int)levels.size(), &levels[0]));
1271 MovePtr<tcu::TextureCubeView> getTextureCubeView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1273 const static tcu::CubeFace s_faceMap[tcu::CUBEFACE_LAST] =
1275 tcu::CUBEFACE_POSITIVE_X,
1276 tcu::CUBEFACE_NEGATIVE_X,
1277 tcu::CUBEFACE_POSITIVE_Y,
1278 tcu::CUBEFACE_NEGATIVE_Y,
1279 tcu::CUBEFACE_POSITIVE_Z,
1280 tcu::CUBEFACE_NEGATIVE_Z
1283 const TestTextureCube* texCube = dynamic_cast<const TestTextureCube*>(&testTexture);
1284 const TestTextureCubeArray* texCubeArray = dynamic_cast<const TestTextureCubeArray*>(&testTexture);
1286 DE_ASSERT(!!texCube != !!texCubeArray);
1287 DE_ASSERT(subresource.layerCount == 6);
1288 DE_ASSERT(texCubeArray || subresource.baseArrayLayer == 0);
1290 levels.resize(subresource.levelCount*tcu::CUBEFACE_LAST);
1292 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1294 for (int levelNdx = 0; levelNdx < (int)subresource.levelCount; ++levelNdx)
1296 const tcu::ConstPixelBufferAccess& srcLevel = texCubeArray ? texCubeArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1297 : texCube->getTexture().getLevelFace(levelNdx, s_faceMap[faceNdx]);
1299 levels[faceNdx*subresource.levelCount + levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer + (texCubeArray ? faceNdx : 0), srcLevel.getWidth(), srcLevel.getHeight(), 1);
1304 const tcu::ConstPixelBufferAccess* reordered[tcu::CUBEFACE_LAST];
1306 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1307 reordered[s_faceMap[faceNdx]] = &levels[faceNdx*subresource.levelCount];
1309 return MovePtr<tcu::TextureCubeView>(new tcu::TextureCubeView((int)subresource.levelCount, reordered));
1313 MovePtr<tcu::TextureCubeArrayView> getTextureCubeArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1315 const TestTextureCubeArray* texCubeArray = dynamic_cast<const TestTextureCubeArray*>(&testTexture);
1317 DE_ASSERT(texCubeArray);
1318 DE_ASSERT(subresource.layerCount%6 == 0);
1320 levels.resize(subresource.levelCount);
1322 for (int levelNdx = 0; levelNdx < (int)subresource.levelCount; ++levelNdx)
1324 const tcu::ConstPixelBufferAccess& srcLevel = texCubeArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1326 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), (int)subresource.layerCount);
1329 return MovePtr<tcu::TextureCubeArrayView>(new tcu::TextureCubeArrayView((int)levels.size(), &levels[0]));
1332 MovePtr<tcu::Texture3DView> getTexture3DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1334 DE_ASSERT(subresource.baseArrayLayer == 0 && subresource.layerCount == 1);
1336 levels.resize(subresource.levelCount);
1338 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1339 levels[levelNdx] = testTexture.getLevel((int)subresource.baseMipLevel+levelNdx, subresource.baseArrayLayer);
1341 return MovePtr<tcu::Texture3DView>(new tcu::Texture3DView((int)levels.size(), &levels[0]));
1344 bool validateResultImage (const TestTexture& texture,
1345 const VkImageViewType imageViewType,
1346 const VkImageSubresourceRange& subresource,
1347 const tcu::Sampler& sampler,
1348 const vk::VkComponentMapping& componentMapping,
1349 const tcu::ConstPixelBufferAccess& coordAccess,
1350 const tcu::Vec2& lodBounds,
1351 const tcu::LookupPrecision& lookupPrecision,
1352 const tcu::Vec4& lookupScale,
1353 const tcu::Vec4& lookupBias,
1354 const tcu::ConstPixelBufferAccess& resultAccess,
1355 const tcu::PixelBufferAccess& errorAccess)
1357 std::vector<tcu::ConstPixelBufferAccess> levels;
1359 switch (imageViewType)
1361 case VK_IMAGE_VIEW_TYPE_1D:
1363 UniquePtr<tcu::Texture1DView> texView(getTexture1DView(texture, subresource, levels));
1365 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1368 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1370 UniquePtr<tcu::Texture1DArrayView> texView(getTexture1DArrayView(texture, subresource, levels));
1372 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1375 case VK_IMAGE_VIEW_TYPE_2D:
1377 UniquePtr<tcu::Texture2DView> texView(getTexture2DView(texture, subresource, levels));
1379 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1382 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1384 UniquePtr<tcu::Texture2DArrayView> texView(getTexture2DArrayView(texture, subresource, levels));
1386 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1389 case VK_IMAGE_VIEW_TYPE_CUBE:
1391 UniquePtr<tcu::TextureCubeView> texView(getTextureCubeView(texture, subresource, levels));
1393 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1396 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1398 UniquePtr<tcu::TextureCubeArrayView> texView(getTextureCubeArrayView(texture, subresource, levels));
1400 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1404 case VK_IMAGE_VIEW_TYPE_3D:
1406 UniquePtr<tcu::Texture3DView> texView(getTexture3DView(texture, subresource, levels));
1408 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1419 tcu::TestStatus ImageSamplingInstance::verifyImage (void)
1421 const VkPhysicalDeviceLimits& limits = m_context.getDeviceProperties().limits;
1422 // \note Color buffer is used to capture coordinates - not sampled texture values
1423 const tcu::TextureFormat colorFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
1424 const tcu::TextureFormat depthStencilFormat; // Undefined depth/stencil format.
1425 const CoordinateCaptureProgram coordCaptureProgram;
1426 const rr::Program rrProgram = coordCaptureProgram.getReferenceProgram();
1427 ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, colorFormat, depthStencilFormat, &rrProgram);
1429 bool compareOkAll = true;
1430 bool anyWarnings = false;
1432 tcu::Vec4 lookupScale (1.0f);
1433 tcu::Vec4 lookupBias (0.0f);
1435 getLookupScaleBias(m_imageFormat, lookupScale, lookupBias);
1437 // Render out coordinates
1439 const rr::RenderState renderState(refRenderer.getViewportState());
1440 refRenderer.draw(renderState, rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
1445 const tcu::Sampler sampler = mapVkSampler(m_samplerParams);
1446 const float referenceLod = de::clamp(m_samplerParams.mipLodBias + m_samplerLod, m_samplerParams.minLod, m_samplerParams.maxLod);
1447 const float lodError = 1.0f / static_cast<float>((1u << limits.mipmapPrecisionBits) - 1u);
1448 const tcu::Vec2 lodBounds (referenceLod - lodError, referenceLod + lodError);
1449 const vk::VkImageSubresourceRange subresource = resolveSubresourceRange(*m_texture, m_subresourceRange);
1451 const tcu::ConstPixelBufferAccess coordAccess = refRenderer.getAccess();
1452 tcu::TextureLevel errorMask (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), (int)m_renderSize.x(), (int)m_renderSize.y());
1453 const tcu::PixelBufferAccess errorAccess = errorMask.getAccess();
1455 const bool allowSnorm8Bug = m_texture->getTextureFormat().type == tcu::TextureFormat::SNORM_INT8 &&
1456 (m_samplerParams.minFilter == VK_FILTER_LINEAR || m_samplerParams.magFilter == VK_FILTER_LINEAR);
1457 const bool isNearestOnly = (m_samplerParams.minFilter == VK_FILTER_NEAREST && m_samplerParams.magFilter == VK_FILTER_NEAREST);
1459 tcu::LookupPrecision lookupPrecision;
1461 // Set precision requirements - very low for these tests as
1462 // the point of the test is not to validate accuracy.
1463 lookupPrecision.coordBits = tcu::IVec3(17, 17, 17);
1464 lookupPrecision.uvwBits = tcu::IVec3(5, 5, 5);
1465 lookupPrecision.colorMask = tcu::BVec4(true);
1466 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(max((tcu::IVec4(8, 8, 8, 8) - (isNearestOnly ? 1 : 2)), tcu::IVec4(0))) / swizzleScaleBias(lookupScale, m_componentMapping);
1468 if (tcu::isSRGB(m_texture->getTextureFormat()))
1469 lookupPrecision.colorThreshold += tcu::Vec4(4.f / 255.f);
1471 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1473 // Read back result image
1474 UniquePtr<tcu::TextureLevel> result (readColorAttachment(m_context.getDeviceInterface(),
1475 m_context.getDevice(),
1476 m_context.getUniversalQueue(),
1477 m_context.getUniversalQueueFamilyIndex(),
1478 m_context.getDefaultAllocator(),
1479 **m_colorImages[imgNdx],
1482 const tcu::ConstPixelBufferAccess resultAccess = result->getAccess();
1483 bool compareOk = validateResultImage(*m_texture,
1496 if (!compareOk && allowSnorm8Bug)
1498 // HW waiver (VK-GL-CTS issue: 229)
1500 // Due to an error in bit replication of the fixed point SNORM values, linear filtered
1501 // negative SNORM values will differ slightly from ideal precision in the last bit, moving
1502 // the values towards 0.
1504 // This occurs on all members of the PowerVR Rogue family of GPUs
1505 tcu::LookupPrecision relaxedPrecision;
1507 relaxedPrecision.colorThreshold += tcu::Vec4(4.f / 255.f);
1509 m_context.getTestContext().getLog()
1510 << tcu::TestLog::Message
1511 << "Warning: Strict validation failed, re-trying with lower precision for SNORM8 format"
1512 << tcu::TestLog::EndMessage;
1515 compareOk = validateResultImage(*m_texture,
1530 m_context.getTestContext().getLog()
1531 << tcu::TestLog::Image("Result", "Result Image", resultAccess)
1532 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorAccess);
1534 compareOkAll = compareOkAll && compareOk;
1541 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Inaccurate filtering results");
1543 return tcu::TestStatus::pass("Result image matches reference");
1546 return tcu::TestStatus::fail("Image mismatch");