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"
50 static VkImageType getCompatibleImageType (VkImageViewType viewType)
54 case VK_IMAGE_VIEW_TYPE_1D: return VK_IMAGE_TYPE_1D;
55 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return VK_IMAGE_TYPE_1D;
56 case VK_IMAGE_VIEW_TYPE_2D: return VK_IMAGE_TYPE_2D;
57 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: return VK_IMAGE_TYPE_2D;
58 case VK_IMAGE_VIEW_TYPE_3D: return VK_IMAGE_TYPE_3D;
59 case VK_IMAGE_VIEW_TYPE_CUBE: return VK_IMAGE_TYPE_2D;
60 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return VK_IMAGE_TYPE_2D;
66 return VK_IMAGE_TYPE_1D;
69 template<typename TcuFormatType>
70 static MovePtr<TestTexture> createTestTexture (const TcuFormatType format, VkImageViewType viewType, const tcu::IVec3& size, int layerCount)
72 MovePtr<TestTexture> texture;
73 const VkImageType imageType = getCompatibleImageType(viewType);
77 case VK_IMAGE_TYPE_1D:
79 texture = MovePtr<TestTexture>(new TestTexture1D(format, size.x()));
81 texture = MovePtr<TestTexture>(new TestTexture1DArray(format, size.x(), layerCount));
85 case VK_IMAGE_TYPE_2D:
88 texture = MovePtr<TestTexture>(new TestTexture2D(format, size.x(), size.y()));
92 if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
94 if (layerCount == tcu::CUBEFACE_LAST && viewType == VK_IMAGE_VIEW_TYPE_CUBE)
96 texture = MovePtr<TestTexture>(new TestTextureCube(format, size.x()));
100 DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0);
102 texture = MovePtr<TestTexture>(new TestTextureCubeArray(format, size.x(), layerCount));
107 texture = MovePtr<TestTexture>(new TestTexture2DArray(format, size.x(), size.y(), layerCount));
113 case VK_IMAGE_TYPE_3D:
114 texture = MovePtr<TestTexture>(new TestTexture3D(format, size.x(), size.y(), size.z()));
126 ImageSamplingInstance::ImageSamplingInstance (Context& context,
127 const tcu::UVec2& renderSize,
128 VkImageViewType imageViewType,
129 VkFormat imageFormat,
130 const tcu::IVec3& imageSize,
132 const VkComponentMapping& componentMapping,
133 const VkImageSubresourceRange& subresourceRange,
134 const VkSamplerCreateInfo& samplerParams,
136 const std::vector<Vertex4Tex4>& vertices,
137 VkDescriptorType samplingType,
139 : vkt::TestInstance (context)
140 , m_samplingType (samplingType)
141 , m_imageViewType (imageViewType)
142 , m_imageFormat (imageFormat)
143 , m_imageSize (imageSize)
144 , m_layerCount (layerCount)
145 , m_imageCount (imageCount)
146 , m_componentMapping (componentMapping)
147 , m_subresourceRange (subresourceRange)
148 , m_samplerParams (samplerParams)
149 , m_samplerLod (samplerLod)
150 , m_renderSize (renderSize)
151 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
152 , m_vertices (vertices)
154 const DeviceInterface& vk = context.getDeviceInterface();
155 const VkDevice vkDevice = context.getDevice();
156 const VkQueue queue = context.getUniversalQueue();
157 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
158 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
159 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
161 if (!isSupportedSamplableFormat(context.getInstanceInterface(), context.getPhysicalDevice(), imageFormat))
162 throw tcu::NotSupportedError(std::string("Unsupported format for sampling: ") + getFormatName(imageFormat));
164 if ((deUint32)imageCount > context.getDeviceProperties().limits.maxColorAttachments)
165 throw tcu::NotSupportedError(std::string("Unsupported render target count: ") + de::toString(imageCount));
167 if ((samplerParams.minFilter == VK_FILTER_LINEAR ||
168 samplerParams.magFilter == VK_FILTER_LINEAR ||
169 samplerParams.mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR) &&
170 !isLinearFilteringSupported(context.getInstanceInterface(), context.getPhysicalDevice(), imageFormat, VK_IMAGE_TILING_OPTIMAL))
171 throw tcu::NotSupportedError(std::string("Unsupported format for linear filtering: ") + getFormatName(imageFormat));
173 if ((samplerParams.addressModeU == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE ||
174 samplerParams.addressModeV == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE ||
175 samplerParams.addressModeW == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE) &&
176 !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_sampler_mirror_clamp_to_edge"))
177 TCU_THROW(NotSupportedError, "VK_KHR_sampler_mirror_clamp_to_edge not supported");
179 if (isCompressedFormat(imageFormat) && imageViewType == VK_IMAGE_VIEW_TYPE_3D)
181 // \todo [2016-01-22 pyry] Mandate VK_ERROR_FORMAT_NOT_SUPPORTED
184 const VkImageFormatProperties formatProperties = getPhysicalDeviceImageFormatProperties(context.getInstanceInterface(),
185 context.getPhysicalDevice(),
188 VK_IMAGE_TILING_OPTIMAL,
189 VK_IMAGE_USAGE_SAMPLED_BIT,
190 (VkImageCreateFlags)0);
192 if (formatProperties.maxExtent.width == 0 &&
193 formatProperties.maxExtent.height == 0 &&
194 formatProperties.maxExtent.depth == 0)
195 TCU_THROW(NotSupportedError, "3D compressed format not supported");
199 TCU_THROW(NotSupportedError, "3D compressed format not supported");
203 if (imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY && !context.getDeviceFeatures().imageCubeArray)
204 TCU_THROW(NotSupportedError, "imageCubeArray feature is not supported");
206 // Create texture images, views and samplers
208 VkImageCreateFlags imageFlags = 0u;
210 if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
211 imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
213 // Initialize texture data
214 if (isCompressedFormat(imageFormat))
215 m_texture = createTestTexture(mapVkCompressedFormat(imageFormat), imageViewType, imageSize, layerCount);
217 m_texture = createTestTexture(mapVkFormat(imageFormat), imageViewType, imageSize, layerCount);
219 const VkImageCreateInfo imageParams =
221 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
222 DE_NULL, // const void* pNext;
223 imageFlags, // VkImageCreateFlags flags;
224 getCompatibleImageType(m_imageViewType), // VkImageType imageType;
225 imageFormat, // VkFormat format;
226 { // VkExtent3D extent;
227 (deUint32)m_imageSize.x(),
228 (deUint32)m_imageSize.y(),
229 (deUint32)m_imageSize.z()
231 (deUint32)m_texture->getNumLevels(), // deUint32 mipLevels;
232 (deUint32)m_layerCount, // deUint32 arrayLayers;
233 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
234 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
235 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
236 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
237 1u, // deUint32 queueFamilyIndexCount;
238 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
239 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
242 m_images.resize(m_imageCount);
243 m_imageAllocs.resize(m_imageCount);
244 m_imageViews.resize(m_imageCount);
246 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
248 m_images[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &imageParams)));
249 m_imageAllocs[imgNdx] = SharedAllocPtr(new UniqueAlloc(memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, **m_images[imgNdx]), MemoryRequirement::Any)));
250 VK_CHECK(vk.bindImageMemory(vkDevice, **m_images[imgNdx], (*m_imageAllocs[imgNdx])->getMemory(), (*m_imageAllocs[imgNdx])->getOffset()));
252 // Upload texture data
253 uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, **m_images[imgNdx]);
255 // Create image view and sampler
256 const VkImageViewCreateInfo imageViewParams =
258 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
259 DE_NULL, // const void* pNext;
260 0u, // VkImageViewCreateFlags flags;
261 **m_images[imgNdx], // VkImage image;
262 m_imageViewType, // VkImageViewType viewType;
263 imageFormat, // VkFormat format;
264 m_componentMapping, // VkComponentMapping components;
265 m_subresourceRange, // VkImageSubresourceRange subresourceRange;
268 m_imageViews[imgNdx] = SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &imageViewParams)));
271 m_sampler = createSampler(vk, vkDevice, &m_samplerParams);
274 // Create descriptor set for image and sampler
276 DescriptorPoolBuilder descriptorPoolBuilder;
277 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
278 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 1u);
279 descriptorPoolBuilder.addType(m_samplingType, m_imageCount);
280 m_descriptorPool = descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
281 m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? m_imageCount + 1u : m_imageCount);
283 DescriptorSetLayoutBuilder setLayoutBuilder;
284 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
285 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
286 setLayoutBuilder.addArrayBinding(m_samplingType, m_imageCount, VK_SHADER_STAGE_FRAGMENT_BIT);
287 m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice);
289 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
291 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
292 DE_NULL, // const void* pNext;
293 *m_descriptorPool, // VkDescriptorPool descriptorPool;
294 1u, // deUint32 setLayoutCount;
295 &m_descriptorSetLayout.get() // const VkDescriptorSetLayout* pSetLayouts;
298 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
300 const VkSampler sampler = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? DE_NULL : *m_sampler;
301 std::vector<VkDescriptorImageInfo> descriptorImageInfo(m_imageCount);
302 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
304 descriptorImageInfo[imgNdx].sampler = sampler; // VkSampler sampler;
305 descriptorImageInfo[imgNdx].imageView = **m_imageViews[imgNdx]; // VkImageView imageView;
306 descriptorImageInfo[imgNdx].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; // VkImageLayout imageLayout;
309 DescriptorSetUpdateBuilder setUpdateBuilder;
310 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
312 const VkDescriptorImageInfo descriptorSamplerInfo =
314 *m_sampler, // VkSampler sampler;
315 DE_NULL, // VkImageView imageView;
316 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout;
318 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_SAMPLER, &descriptorSamplerInfo);
321 const deUint32 binding = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? 1u : 0u;
322 setUpdateBuilder.writeArray(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(binding), m_samplingType, m_imageCount, descriptorImageInfo.data());
323 setUpdateBuilder.update(vk, vkDevice);
326 // Create color images and views
328 const VkImageCreateInfo colorImageParams =
330 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
331 DE_NULL, // const void* pNext;
332 0u, // VkImageCreateFlags flags;
333 VK_IMAGE_TYPE_2D, // VkImageType imageType;
334 m_colorFormat, // VkFormat format;
335 { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u }, // VkExtent3D extent;
336 1u, // deUint32 mipLevels;
337 1u, // deUint32 arrayLayers;
338 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
339 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
340 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
341 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
342 1u, // deUint32 queueFamilyIndexCount;
343 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
344 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
347 m_colorImages.resize(m_imageCount);
348 m_colorImageAllocs.resize(m_imageCount);
349 m_colorAttachmentViews.resize(m_imageCount);
351 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
353 m_colorImages[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &colorImageParams)));
354 m_colorImageAllocs[imgNdx] = SharedAllocPtr(new UniqueAlloc(memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, **m_colorImages[imgNdx]), MemoryRequirement::Any)));
355 VK_CHECK(vk.bindImageMemory(vkDevice, **m_colorImages[imgNdx], (*m_colorImageAllocs[imgNdx])->getMemory(), (*m_colorImageAllocs[imgNdx])->getOffset()));
357 const VkImageViewCreateInfo colorAttachmentViewParams =
359 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
360 DE_NULL, // const void* pNext;
361 0u, // VkImageViewCreateFlags flags;
362 **m_colorImages[imgNdx], // VkImage image;
363 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
364 m_colorFormat, // VkFormat format;
365 componentMappingRGBA, // VkComponentMapping components;
366 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
369 m_colorAttachmentViews[imgNdx] = SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &colorAttachmentViewParams)));
373 // Create render pass
375 std::vector<VkAttachmentDescription> colorAttachmentDescriptions(m_imageCount);
376 std::vector<VkAttachmentReference> colorAttachmentReferences(m_imageCount);
378 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
380 colorAttachmentDescriptions[imgNdx].flags = 0u; // VkAttachmentDescriptionFlags flags;
381 colorAttachmentDescriptions[imgNdx].format = m_colorFormat; // VkFormat format;
382 colorAttachmentDescriptions[imgNdx].samples = VK_SAMPLE_COUNT_1_BIT; // VkSampleCountFlagBits samples;
383 colorAttachmentDescriptions[imgNdx].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // VkAttachmentLoadOp loadOp;
384 colorAttachmentDescriptions[imgNdx].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // VkAttachmentStoreOp storeOp;
385 colorAttachmentDescriptions[imgNdx].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // VkAttachmentLoadOp stencilLoadOp;
386 colorAttachmentDescriptions[imgNdx].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // VkAttachmentStoreOp stencilStoreOp;
387 colorAttachmentDescriptions[imgNdx].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout initialLayout;
388 colorAttachmentDescriptions[imgNdx].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout finalLayout;
390 colorAttachmentReferences[imgNdx].attachment = (deUint32)imgNdx; // deUint32 attachment;
391 colorAttachmentReferences[imgNdx].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout layout;
394 const VkSubpassDescription subpassDescription =
396 0u, // VkSubpassDescriptionFlags flags;
397 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
398 0u, // deUint32 inputAttachmentCount;
399 DE_NULL, // const VkAttachmentReference* pInputAttachments;
400 (deUint32)m_imageCount, // deUint32 colorAttachmentCount;
401 &colorAttachmentReferences[0], // const VkAttachmentReference* pColorAttachments;
402 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
403 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
404 0u, // deUint32 preserveAttachmentCount;
405 DE_NULL // const VkAttachmentReference* pPreserveAttachments;
408 const VkRenderPassCreateInfo renderPassParams =
410 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
411 DE_NULL, // const void* pNext;
412 0u, // VkRenderPassCreateFlags flags;
413 (deUint32)m_imageCount, // deUint32 attachmentCount;
414 &colorAttachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
415 1u, // deUint32 subpassCount;
416 &subpassDescription, // const VkSubpassDescription* pSubpasses;
417 0u, // deUint32 dependencyCount;
418 DE_NULL // const VkSubpassDependency* pDependencies;
421 m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
424 // Create framebuffer
426 std::vector<VkImageView> pAttachments(m_imageCount);
427 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
428 pAttachments[imgNdx] = m_colorAttachmentViews[imgNdx]->get();
430 const VkFramebufferCreateInfo framebufferParams =
432 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
433 DE_NULL, // const void* pNext;
434 0u, // VkFramebufferCreateFlags flags;
435 *m_renderPass, // VkRenderPass renderPass;
436 (deUint32)m_imageCount, // deUint32 attachmentCount;
437 &pAttachments[0], // const VkImageView* pAttachments;
438 (deUint32)m_renderSize.x(), // deUint32 width;
439 (deUint32)m_renderSize.y(), // deUint32 height;
440 1u // deUint32 layers;
443 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
446 // Create pipeline layout
448 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
450 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
451 DE_NULL, // const void* pNext;
452 0u, // VkPipelineLayoutCreateFlags flags;
453 1u, // deUint32 setLayoutCount;
454 &m_descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
455 0u, // deUint32 pushConstantRangeCount;
456 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
459 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
462 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0);
463 m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0);
467 const VkPipelineShaderStageCreateInfo shaderStages[2] =
470 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
471 DE_NULL, // const void* pNext;
472 0u, // VkPipelineShaderStageCreateFlags flags;
473 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
474 *m_vertexShaderModule, // VkShaderModule module;
475 "main", // const char* pName;
476 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
479 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
480 DE_NULL, // const void* pNext;
481 0u, // VkPipelineShaderStageCreateFlags flags;
482 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
483 *m_fragmentShaderModule, // VkShaderModule module;
484 "main", // const char* pName;
485 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
489 const VkVertexInputBindingDescription vertexInputBindingDescription =
491 0u, // deUint32 binding;
492 sizeof(Vertex4Tex4), // deUint32 strideInBytes;
493 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
496 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
499 0u, // deUint32 location;
500 0u, // deUint32 binding;
501 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
502 0u // deUint32 offset;
505 1u, // deUint32 location;
506 0u, // deUint32 binding;
507 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
508 DE_OFFSET_OF(Vertex4Tex4, texCoord), // deUint32 offset;
512 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
514 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
515 DE_NULL, // const void* pNext;
516 0u, // VkPipelineVertexInputStateCreateFlags flags;
517 1u, // deUint32 vertexBindingDescriptionCount;
518 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
519 2u, // deUint32 vertexAttributeDescriptionCount;
520 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
523 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
525 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
526 DE_NULL, // const void* pNext;
527 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
528 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
529 false // VkBool32 primitiveRestartEnable;
532 const VkViewport viewport =
536 (float)m_renderSize.x(), // float width;
537 (float)m_renderSize.y(), // float height;
538 0.0f, // float minDepth;
539 1.0f // float maxDepth;
542 const VkRect2D scissor = { { 0, 0 }, { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() } };
544 const VkPipelineViewportStateCreateInfo viewportStateParams =
546 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
547 DE_NULL, // const void* pNext;
548 0u, // VkPipelineViewportStateCreateFlags flags;
549 1u, // deUint32 viewportCount;
550 &viewport, // const VkViewport* pViewports;
551 1u, // deUint32 scissorCount;
552 &scissor // const VkRect2D* pScissors;
555 const VkPipelineRasterizationStateCreateInfo rasterStateParams =
557 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
558 DE_NULL, // const void* pNext;
559 0u, // VkPipelineRasterizationStateCreateFlags flags;
560 false, // VkBool32 depthClampEnable;
561 false, // VkBool32 rasterizerDiscardEnable;
562 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
563 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
564 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
565 false, // VkBool32 depthBiasEnable;
566 0.0f, // float depthBiasConstantFactor;
567 0.0f, // float depthBiasClamp;
568 0.0f, // float depthBiasSlopeFactor;
569 1.0f // float lineWidth;
572 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates(m_imageCount);
574 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
576 colorBlendAttachmentStates[imgNdx].blendEnable = false; // VkBool32 blendEnable;
577 colorBlendAttachmentStates[imgNdx].srcColorBlendFactor = VK_BLEND_FACTOR_ONE; // VkBlendFactor srcColorBlendFactor;
578 colorBlendAttachmentStates[imgNdx].dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // VkBlendFactor dstColorBlendFactor;
579 colorBlendAttachmentStates[imgNdx].colorBlendOp = VK_BLEND_OP_ADD; // VkBlendOp colorBlendOp;
580 colorBlendAttachmentStates[imgNdx].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; // VkBlendFactor srcAlphaBlendFactor;
581 colorBlendAttachmentStates[imgNdx].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // VkBlendFactor dstAlphaBlendFactor;
582 colorBlendAttachmentStates[imgNdx].alphaBlendOp = VK_BLEND_OP_ADD; // VkBlendOp alphaBlendOp;
583 colorBlendAttachmentStates[imgNdx].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
584 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
587 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
589 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
590 DE_NULL, // const void* pNext;
591 0u, // VkPipelineColorBlendStateCreateFlags flags;
592 false, // VkBool32 logicOpEnable;
593 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
594 (deUint32)m_imageCount, // deUint32 attachmentCount;
595 &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState* pAttachments;
596 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4];
599 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
601 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
602 DE_NULL, // const void* pNext;
603 0u, // VkPipelineMultisampleStateCreateFlags flags;
604 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
605 false, // VkBool32 sampleShadingEnable;
606 0.0f, // float minSampleShading;
607 DE_NULL, // const VkSampleMask* pSampleMask;
608 false, // VkBool32 alphaToCoverageEnable;
609 false // VkBool32 alphaToOneEnable;
612 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
614 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
615 DE_NULL, // const void* pNext;
616 0u, // VkPipelineDepthStencilStateCreateFlags flags;
617 false, // VkBool32 depthTestEnable;
618 false, // VkBool32 depthWriteEnable;
619 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
620 false, // VkBool32 depthBoundsTestEnable;
621 false, // VkBool32 stencilTestEnable;
622 { // VkStencilOpState front;
623 VK_STENCIL_OP_ZERO, // VkStencilOp failOp;
624 VK_STENCIL_OP_ZERO, // VkStencilOp passOp;
625 VK_STENCIL_OP_ZERO, // VkStencilOp depthFailOp;
626 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
627 0u, // deUint32 compareMask;
628 0u, // deUint32 writeMask;
629 0u // deUint32 reference;
631 { // VkStencilOpState back;
632 VK_STENCIL_OP_ZERO, // VkStencilOp failOp;
633 VK_STENCIL_OP_ZERO, // VkStencilOp passOp;
634 VK_STENCIL_OP_ZERO, // VkStencilOp depthFailOp;
635 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
636 0u, // deUint32 compareMask;
637 0u, // deUint32 writeMask;
638 0u // deUint32 reference;
640 0.0f, // float minDepthBounds;
641 1.0f // float maxDepthBounds;
644 const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
646 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
647 DE_NULL, // const void* pNext;
648 0u, // VkPipelineCreateFlags flags;
649 2u, // deUint32 stageCount;
650 shaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
651 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
652 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
653 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
654 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
655 &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
656 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
657 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
658 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
659 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
660 *m_pipelineLayout, // VkPipelineLayout layout;
661 *m_renderPass, // VkRenderPass renderPass;
662 0u, // deUint32 subpass;
663 0u, // VkPipeline basePipelineHandle;
664 0u // deInt32 basePipelineIndex;
667 m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
670 // Create vertex buffer
672 const VkDeviceSize vertexBufferSize = (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4));
673 const VkBufferCreateInfo vertexBufferParams =
675 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
676 DE_NULL, // const void* pNext;
677 0u, // VkBufferCreateFlags flags;
678 vertexBufferSize, // VkDeviceSize size;
679 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
680 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
681 1u, // deUint32 queueFamilyIndexCount;
682 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
685 DE_ASSERT(vertexBufferSize > 0);
687 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
688 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
690 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
692 // Load vertices into vertex buffer
693 deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize);
694 flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexBufferParams.size);
697 // Create command pool
698 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
700 // Create command buffer
702 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
704 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
705 DE_NULL, // const void* pNext;
706 0u, // VkCommandBufferUsageFlags flags;
707 (const VkCommandBufferInheritanceInfo*)DE_NULL,
710 const std::vector<VkClearValue> attachmentClearValues (m_imageCount, defaultClearValue(m_colorFormat));
712 const VkRenderPassBeginInfo renderPassBeginInfo =
714 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
715 DE_NULL, // const void* pNext;
716 *m_renderPass, // VkRenderPass renderPass;
717 *m_framebuffer, // VkFramebuffer framebuffer;
720 { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }
721 }, // VkRect2D renderArea;
722 static_cast<deUint32>(attachmentClearValues.size()), // deUint32 clearValueCount;
723 &attachmentClearValues[0] // const VkClearValue* pClearValues;
726 std::vector<VkImageMemoryBarrier> preAttachmentBarriers(m_imageCount);
728 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
730 preAttachmentBarriers[imgNdx].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; // VkStructureType sType;
731 preAttachmentBarriers[imgNdx].pNext = DE_NULL; // const void* pNext;
732 preAttachmentBarriers[imgNdx].srcAccessMask = 0u; // VkAccessFlags srcAccessMask;
733 preAttachmentBarriers[imgNdx].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; // VkAccessFlags dstAccessMask;
734 preAttachmentBarriers[imgNdx].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; // VkImageLayout oldLayout;
735 preAttachmentBarriers[imgNdx].newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout newLayout;
736 preAttachmentBarriers[imgNdx].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // deUint32 srcQueueFamilyIndex;
737 preAttachmentBarriers[imgNdx].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // deUint32 dstQueueFamilyIndex;
738 preAttachmentBarriers[imgNdx].image = **m_colorImages[imgNdx]; // VkImage image;
739 preAttachmentBarriers[imgNdx].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; // VkImageSubresourceRange subresourceRange;
740 preAttachmentBarriers[imgNdx].subresourceRange.baseMipLevel = 0u;
741 preAttachmentBarriers[imgNdx].subresourceRange.levelCount = 1u;
742 preAttachmentBarriers[imgNdx].subresourceRange.baseArrayLayer = 0u;
743 preAttachmentBarriers[imgNdx].subresourceRange.layerCount = 1u;
746 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
748 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
750 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
751 0u, DE_NULL, 0u, DE_NULL, (deUint32)m_imageCount, &preAttachmentBarriers[0]);
753 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
755 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
757 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
759 const VkDeviceSize vertexBufferOffset = 0;
760 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
761 vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
763 vk.cmdEndRenderPass(*m_cmdBuffer);
764 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
768 m_fence = createFence(vk, vkDevice);
771 ImageSamplingInstance::~ImageSamplingInstance (void)
775 tcu::TestStatus ImageSamplingInstance::iterate (void)
777 const DeviceInterface& vk = m_context.getDeviceInterface();
778 const VkDevice vkDevice = m_context.getDevice();
779 const VkQueue queue = m_context.getUniversalQueue();
780 const VkSubmitInfo submitInfo =
782 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
783 DE_NULL, // const void* pNext;
784 0u, // deUint32 waitSemaphoreCount;
785 DE_NULL, // const VkSemaphore* pWaitSemaphores;
787 1u, // deUint32 commandBufferCount;
788 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
789 0u, // deUint32 signalSemaphoreCount;
790 DE_NULL // const VkSemaphore* pSignalSemaphores;
793 VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
794 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
795 VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
797 return verifyImage();
803 bool isLookupResultValid (const tcu::Texture1DView& texture,
804 const tcu::Sampler& sampler,
805 const tcu::LookupPrecision& precision,
806 const tcu::Vec4& coords,
807 const tcu::Vec2& lodBounds,
808 const tcu::Vec4& result)
810 return tcu::isLookupResultValid(texture, sampler, precision, coords.x(), lodBounds, result);
813 bool isLookupResultValid (const tcu::Texture1DArrayView& texture,
814 const tcu::Sampler& sampler,
815 const tcu::LookupPrecision& precision,
816 const tcu::Vec4& coords,
817 const tcu::Vec2& lodBounds,
818 const tcu::Vec4& result)
820 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1), lodBounds, result);
823 bool isLookupResultValid (const tcu::Texture2DView& texture,
824 const tcu::Sampler& sampler,
825 const tcu::LookupPrecision& precision,
826 const tcu::Vec4& coords,
827 const tcu::Vec2& lodBounds,
828 const tcu::Vec4& result)
830 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1), lodBounds, result);
833 bool isLookupResultValid (const tcu::Texture2DArrayView& texture,
834 const tcu::Sampler& sampler,
835 const tcu::LookupPrecision& precision,
836 const tcu::Vec4& coords,
837 const tcu::Vec2& lodBounds,
838 const tcu::Vec4& result)
840 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result);
843 bool isLookupResultValid (const tcu::TextureCubeView& texture,
844 const tcu::Sampler& sampler,
845 const tcu::LookupPrecision& precision,
846 const tcu::Vec4& coords,
847 const tcu::Vec2& lodBounds,
848 const tcu::Vec4& result)
850 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result);
853 bool isLookupResultValid (const tcu::TextureCubeArrayView& texture,
854 const tcu::Sampler& sampler,
855 const tcu::LookupPrecision& precision,
856 const tcu::Vec4& coords,
857 const tcu::Vec2& lodBounds,
858 const tcu::Vec4& result)
860 return tcu::isLookupResultValid(texture, sampler, precision, tcu::IVec4(precision.coordBits.x()), coords, lodBounds, result);
863 bool isLookupResultValid(const tcu::Texture3DView& texture,
864 const tcu::Sampler& sampler,
865 const tcu::LookupPrecision& precision,
866 const tcu::Vec4& coords,
867 const tcu::Vec2& lodBounds,
868 const tcu::Vec4& result)
870 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result);
873 template<typename TextureViewType>
874 bool validateResultImage (const TextureViewType& texture,
875 const tcu::Sampler& sampler,
876 const tcu::ConstPixelBufferAccess& texCoords,
877 const tcu::Vec2& lodBounds,
878 const tcu::LookupPrecision& lookupPrecision,
879 const tcu::Vec4& lookupScale,
880 const tcu::Vec4& lookupBias,
881 const tcu::ConstPixelBufferAccess& result,
882 const tcu::PixelBufferAccess& errorMask)
884 const int w = result.getWidth();
885 const int h = result.getHeight();
888 for (int y = 0; y < h; ++y)
890 for (int x = 0; x < w; ++x)
892 const tcu::Vec4 resultPixel = result.getPixel(x, y);
893 const tcu::Vec4 resultColor = (resultPixel - lookupBias) / lookupScale;
894 const tcu::Vec4 texCoord = texCoords.getPixel(x, y);
895 const bool pixelOk = isLookupResultValid(texture, sampler, lookupPrecision, texCoord, lodBounds, resultColor);
897 errorMask.setPixel(tcu::Vec4(pixelOk?0.0f:1.0f, pixelOk?1.0f:0.0f, 0.0f, 1.0f), x, y);
907 template<typename ScalarType>
908 ScalarType getSwizzledComp (const tcu::Vector<ScalarType, 4>& vec, vk::VkComponentSwizzle comp, int identityNdx)
910 if (comp == vk::VK_COMPONENT_SWIZZLE_IDENTITY)
911 return vec[identityNdx];
912 else if (comp == vk::VK_COMPONENT_SWIZZLE_ZERO)
913 return ScalarType(0);
914 else if (comp == vk::VK_COMPONENT_SWIZZLE_ONE)
915 return ScalarType(1);
917 return vec[comp - vk::VK_COMPONENT_SWIZZLE_R];
920 template<typename ScalarType>
921 tcu::Vector<ScalarType, 4> swizzle (const tcu::Vector<ScalarType, 4>& vec, const vk::VkComponentMapping& swz)
923 return tcu::Vector<ScalarType, 4>(getSwizzledComp(vec, swz.r, 0),
924 getSwizzledComp(vec, swz.g, 1),
925 getSwizzledComp(vec, swz.b, 2),
926 getSwizzledComp(vec, swz.a, 3));
929 tcu::Vec4 swizzleScaleBias (const tcu::Vec4& vec, const vk::VkComponentMapping& swz)
931 const float channelValues[] =
942 return tcu::Vec4(channelValues[swz.r], channelValues[swz.g], channelValues[swz.b], channelValues[swz.a]);
945 template<typename ScalarType>
946 void swizzleT (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)
948 for (int z = 0; z < dst.getDepth(); ++z)
949 for (int y = 0; y < dst.getHeight(); ++y)
950 for (int x = 0; x < dst.getWidth(); ++x)
951 dst.setPixel(swizzle(src.getPixelT<ScalarType>(x, y, z), swz), x, y, z);
954 void swizzleFromSRGB (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)
956 for (int z = 0; z < dst.getDepth(); ++z)
957 for (int y = 0; y < dst.getHeight(); ++y)
958 for (int x = 0; x < dst.getWidth(); ++x)
959 dst.setPixel(swizzle(tcu::sRGBToLinear(src.getPixelT<float>(x, y, z)), swz), x, y, z);
962 void swizzle (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)
964 const tcu::TextureChannelClass chnClass = tcu::getTextureChannelClass(dst.getFormat().type);
966 DE_ASSERT(src.getWidth() == dst.getWidth() &&
967 src.getHeight() == dst.getHeight() &&
968 src.getDepth() == dst.getDepth());
970 if (chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
971 swizzleT<deInt32>(src, dst, swz);
972 else if (chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
973 swizzleT<deUint32>(src, dst, swz);
974 else if (tcu::isSRGB(src.getFormat()) && !tcu::isSRGB(dst.getFormat()))
975 swizzleFromSRGB(src, dst, swz);
977 swizzleT<float>(src, dst, swz);
980 bool isIdentitySwizzle (const vk::VkComponentMapping& swz)
982 return (swz.r == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.r == vk::VK_COMPONENT_SWIZZLE_R) &&
983 (swz.g == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.g == vk::VK_COMPONENT_SWIZZLE_G) &&
984 (swz.b == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.b == vk::VK_COMPONENT_SWIZZLE_B) &&
985 (swz.a == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.a == vk::VK_COMPONENT_SWIZZLE_A);
988 template<typename TextureViewType> struct TexViewTraits;
990 template<> struct TexViewTraits<tcu::Texture1DView> { typedef tcu::Texture1D TextureType; };
991 template<> struct TexViewTraits<tcu::Texture1DArrayView> { typedef tcu::Texture1DArray TextureType; };
992 template<> struct TexViewTraits<tcu::Texture2DView> { typedef tcu::Texture2D TextureType; };
993 template<> struct TexViewTraits<tcu::Texture2DArrayView> { typedef tcu::Texture2DArray TextureType; };
994 template<> struct TexViewTraits<tcu::TextureCubeView> { typedef tcu::TextureCube TextureType; };
995 template<> struct TexViewTraits<tcu::TextureCubeArrayView> { typedef tcu::TextureCubeArray TextureType; };
996 template<> struct TexViewTraits<tcu::Texture3DView> { typedef tcu::Texture3D TextureType; };
998 template<typename TextureViewType>
999 typename TexViewTraits<TextureViewType>::TextureType* createSkeletonClone (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0);
1001 tcu::TextureFormat getSwizzleTargetFormat (tcu::TextureFormat format)
1003 // Swizzled texture needs to hold all four channels
1004 // \todo [2016-09-21 pyry] We could save some memory by using smaller formats
1005 // when possible (for example U8).
1007 const tcu::TextureChannelClass chnClass = tcu::getTextureChannelClass(format.type);
1009 if (chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1010 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
1011 else if (chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1012 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
1014 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
1018 tcu::Texture1D* createSkeletonClone<tcu::Texture1DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1020 return new tcu::Texture1D(format, level0.getWidth());
1024 tcu::Texture1DArray* createSkeletonClone<tcu::Texture1DArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1026 return new tcu::Texture1DArray(format, level0.getWidth(), level0.getHeight());
1030 tcu::Texture2D* createSkeletonClone<tcu::Texture2DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1032 return new tcu::Texture2D(format, level0.getWidth(), level0.getHeight());
1036 tcu::Texture2DArray* createSkeletonClone<tcu::Texture2DArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1038 return new tcu::Texture2DArray(format, level0.getWidth(), level0.getHeight(), level0.getDepth());
1042 tcu::Texture3D* createSkeletonClone<tcu::Texture3DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1044 return new tcu::Texture3D(format, level0.getWidth(), level0.getHeight(), level0.getDepth());
1048 tcu::TextureCubeArray* createSkeletonClone<tcu::TextureCubeArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1050 return new tcu::TextureCubeArray(format, level0.getWidth(), level0.getDepth());
1053 template<typename TextureViewType>
1054 MovePtr<typename TexViewTraits<TextureViewType>::TextureType> createSwizzledCopy (const TextureViewType& texture, const vk::VkComponentMapping& swz)
1056 MovePtr<typename TexViewTraits<TextureViewType>::TextureType> copy (createSkeletonClone<TextureViewType>(getSwizzleTargetFormat(texture.getLevel(0).getFormat()), texture.getLevel(0)));
1058 for (int levelNdx = 0; levelNdx < texture.getNumLevels(); ++levelNdx)
1060 copy->allocLevel(levelNdx);
1061 swizzle(texture.getLevel(levelNdx), copy->getLevel(levelNdx), swz);
1068 MovePtr<tcu::TextureCube> createSwizzledCopy (const tcu::TextureCubeView& texture, const vk::VkComponentMapping& swz)
1070 MovePtr<tcu::TextureCube> copy (new tcu::TextureCube(getSwizzleTargetFormat(texture.getLevelFace(0, tcu::CUBEFACE_NEGATIVE_X).getFormat()), texture.getSize()));
1072 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1074 for (int levelNdx = 0; levelNdx < texture.getNumLevels(); ++levelNdx)
1076 copy->allocLevel((tcu::CubeFace)faceNdx, levelNdx);
1077 swizzle(texture.getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), copy->getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), swz);
1084 template<typename TextureViewType>
1085 bool validateResultImage (const TextureViewType& texture,
1086 const tcu::Sampler& sampler,
1087 const vk::VkComponentMapping& swz,
1088 const tcu::ConstPixelBufferAccess& texCoords,
1089 const tcu::Vec2& lodBounds,
1090 const tcu::LookupPrecision& lookupPrecision,
1091 const tcu::Vec4& lookupScale,
1092 const tcu::Vec4& lookupBias,
1093 const tcu::ConstPixelBufferAccess& result,
1094 const tcu::PixelBufferAccess& errorMask)
1096 if (isIdentitySwizzle(swz))
1097 return validateResultImage(texture, sampler, texCoords, lodBounds, lookupPrecision, lookupScale, lookupBias, result, errorMask);
1100 // There is (currently) no way to handle swizzling inside validation loop
1101 // and thus we need to pre-swizzle the texture.
1102 UniquePtr<typename TexViewTraits<TextureViewType>::TextureType> swizzledTex (createSwizzledCopy(texture, swz));
1104 return validateResultImage(*swizzledTex, sampler, texCoords, lodBounds, lookupPrecision, swizzleScaleBias(lookupScale, swz), swizzleScaleBias(lookupBias, swz), result, errorMask);
1108 vk::VkImageSubresourceRange resolveSubresourceRange (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource)
1110 vk::VkImageSubresourceRange resolved = subresource;
1112 if (subresource.levelCount == VK_REMAINING_MIP_LEVELS)
1113 resolved.levelCount = testTexture.getNumLevels()-subresource.baseMipLevel;
1115 if (subresource.layerCount == VK_REMAINING_ARRAY_LAYERS)
1116 resolved.layerCount = testTexture.getArraySize()-subresource.baseArrayLayer;
1121 MovePtr<tcu::Texture1DView> getTexture1DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1123 DE_ASSERT(subresource.layerCount == 1);
1125 levels.resize(subresource.levelCount);
1127 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1129 const tcu::ConstPixelBufferAccess& srcLevel = testTexture.getLevel((int)subresource.baseMipLevel+levelNdx, subresource.baseArrayLayer);
1131 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, 0, srcLevel.getWidth(), 1, 1);
1134 return MovePtr<tcu::Texture1DView>(new tcu::Texture1DView((int)levels.size(), &levels[0]));
1137 MovePtr<tcu::Texture1DArrayView> getTexture1DArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1139 const TestTexture1D* tex1D = dynamic_cast<const TestTexture1D*>(&testTexture);
1140 const TestTexture1DArray* tex1DArray = dynamic_cast<const TestTexture1DArray*>(&testTexture);
1142 DE_ASSERT(!!tex1D != !!tex1DArray);
1143 DE_ASSERT(tex1DArray || subresource.baseArrayLayer == 0);
1145 levels.resize(subresource.levelCount);
1147 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1149 const tcu::ConstPixelBufferAccess& srcLevel = tex1D ? tex1D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1150 : tex1DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1152 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, (int)subresource.baseArrayLayer, 0, srcLevel.getWidth(), (int)subresource.layerCount, 1);
1155 return MovePtr<tcu::Texture1DArrayView>(new tcu::Texture1DArrayView((int)levels.size(), &levels[0]));
1158 MovePtr<tcu::Texture2DView> getTexture2DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1160 const TestTexture2D* tex2D = dynamic_cast<const TestTexture2D*>(&testTexture);
1161 const TestTexture2DArray* tex2DArray = dynamic_cast<const TestTexture2DArray*>(&testTexture);
1163 DE_ASSERT(subresource.layerCount == 1);
1164 DE_ASSERT(!!tex2D != !!tex2DArray);
1165 DE_ASSERT(tex2DArray || subresource.baseArrayLayer == 0);
1167 levels.resize(subresource.levelCount);
1169 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1171 const tcu::ConstPixelBufferAccess& srcLevel = tex2D ? tex2D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1172 : tex2DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1174 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), 1);
1177 return MovePtr<tcu::Texture2DView>(new tcu::Texture2DView((int)levels.size(), &levels[0]));
1180 MovePtr<tcu::Texture2DArrayView> getTexture2DArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1182 const TestTexture2D* tex2D = dynamic_cast<const TestTexture2D*>(&testTexture);
1183 const TestTexture2DArray* tex2DArray = dynamic_cast<const TestTexture2DArray*>(&testTexture);
1185 DE_ASSERT(!!tex2D != !!tex2DArray);
1186 DE_ASSERT(tex2DArray || subresource.baseArrayLayer == 0);
1188 levels.resize(subresource.levelCount);
1190 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1192 const tcu::ConstPixelBufferAccess& srcLevel = tex2D ? tex2D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1193 : tex2DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1195 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), (int)subresource.layerCount);
1198 return MovePtr<tcu::Texture2DArrayView>(new tcu::Texture2DArrayView((int)levels.size(), &levels[0]));
1201 MovePtr<tcu::TextureCubeView> getTextureCubeView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1203 const static tcu::CubeFace s_faceMap[tcu::CUBEFACE_LAST] =
1205 tcu::CUBEFACE_POSITIVE_X,
1206 tcu::CUBEFACE_NEGATIVE_X,
1207 tcu::CUBEFACE_POSITIVE_Y,
1208 tcu::CUBEFACE_NEGATIVE_Y,
1209 tcu::CUBEFACE_POSITIVE_Z,
1210 tcu::CUBEFACE_NEGATIVE_Z
1213 const TestTextureCube* texCube = dynamic_cast<const TestTextureCube*>(&testTexture);
1214 const TestTextureCubeArray* texCubeArray = dynamic_cast<const TestTextureCubeArray*>(&testTexture);
1216 DE_ASSERT(!!texCube != !!texCubeArray);
1217 DE_ASSERT(subresource.layerCount == 6);
1218 DE_ASSERT(texCubeArray || subresource.baseArrayLayer == 0);
1220 levels.resize(subresource.levelCount*tcu::CUBEFACE_LAST);
1222 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1224 for (int levelNdx = 0; levelNdx < (int)subresource.levelCount; ++levelNdx)
1226 const tcu::ConstPixelBufferAccess& srcLevel = texCubeArray ? texCubeArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1227 : texCube->getTexture().getLevelFace(levelNdx, s_faceMap[faceNdx]);
1229 levels[faceNdx*subresource.levelCount + levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer + (texCubeArray ? faceNdx : 0), srcLevel.getWidth(), srcLevel.getHeight(), 1);
1234 const tcu::ConstPixelBufferAccess* reordered[tcu::CUBEFACE_LAST];
1236 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1237 reordered[s_faceMap[faceNdx]] = &levels[faceNdx*subresource.levelCount];
1239 return MovePtr<tcu::TextureCubeView>(new tcu::TextureCubeView((int)subresource.levelCount, reordered));
1243 MovePtr<tcu::TextureCubeArrayView> getTextureCubeArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1245 const TestTextureCubeArray* texCubeArray = dynamic_cast<const TestTextureCubeArray*>(&testTexture);
1247 DE_ASSERT(texCubeArray);
1248 DE_ASSERT(subresource.layerCount%6 == 0);
1250 levels.resize(subresource.levelCount);
1252 for (int levelNdx = 0; levelNdx < (int)subresource.levelCount; ++levelNdx)
1254 const tcu::ConstPixelBufferAccess& srcLevel = texCubeArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1256 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), (int)subresource.layerCount);
1259 return MovePtr<tcu::TextureCubeArrayView>(new tcu::TextureCubeArrayView((int)levels.size(), &levels[0]));
1262 MovePtr<tcu::Texture3DView> getTexture3DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1264 DE_ASSERT(subresource.baseArrayLayer == 0 && subresource.layerCount == 1);
1266 levels.resize(subresource.levelCount);
1268 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1269 levels[levelNdx] = testTexture.getLevel((int)subresource.baseMipLevel+levelNdx, subresource.baseArrayLayer);
1271 return MovePtr<tcu::Texture3DView>(new tcu::Texture3DView((int)levels.size(), &levels[0]));
1274 bool validateResultImage (const TestTexture& texture,
1275 const VkImageViewType imageViewType,
1276 const VkImageSubresourceRange& subresource,
1277 const tcu::Sampler& sampler,
1278 const vk::VkComponentMapping& componentMapping,
1279 const tcu::ConstPixelBufferAccess& coordAccess,
1280 const tcu::Vec2& lodBounds,
1281 const tcu::LookupPrecision& lookupPrecision,
1282 const tcu::Vec4& lookupScale,
1283 const tcu::Vec4& lookupBias,
1284 const tcu::ConstPixelBufferAccess& resultAccess,
1285 const tcu::PixelBufferAccess& errorAccess)
1287 std::vector<tcu::ConstPixelBufferAccess> levels;
1289 switch (imageViewType)
1291 case VK_IMAGE_VIEW_TYPE_1D:
1293 UniquePtr<tcu::Texture1DView> texView(getTexture1DView(texture, subresource, levels));
1295 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1298 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1300 UniquePtr<tcu::Texture1DArrayView> texView(getTexture1DArrayView(texture, subresource, levels));
1302 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1305 case VK_IMAGE_VIEW_TYPE_2D:
1307 UniquePtr<tcu::Texture2DView> texView(getTexture2DView(texture, subresource, levels));
1309 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1312 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1314 UniquePtr<tcu::Texture2DArrayView> texView(getTexture2DArrayView(texture, subresource, levels));
1316 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1319 case VK_IMAGE_VIEW_TYPE_CUBE:
1321 UniquePtr<tcu::TextureCubeView> texView(getTextureCubeView(texture, subresource, levels));
1323 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1326 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1328 UniquePtr<tcu::TextureCubeArrayView> texView(getTextureCubeArrayView(texture, subresource, levels));
1330 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1334 case VK_IMAGE_VIEW_TYPE_3D:
1336 UniquePtr<tcu::Texture3DView> texView(getTexture3DView(texture, subresource, levels));
1338 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1349 tcu::TestStatus ImageSamplingInstance::verifyImage (void)
1351 const VkPhysicalDeviceLimits& limits = m_context.getDeviceProperties().limits;
1352 // \note Color buffer is used to capture coordinates - not sampled texture values
1353 const tcu::TextureFormat colorFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
1354 const tcu::TextureFormat depthStencilFormat; // Undefined depth/stencil format.
1355 const CoordinateCaptureProgram coordCaptureProgram;
1356 const rr::Program rrProgram = coordCaptureProgram.getReferenceProgram();
1357 ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, colorFormat, depthStencilFormat, &rrProgram);
1359 bool compareOkAll = true;
1360 bool anyWarnings = false;
1362 tcu::Vec4 lookupScale (1.0f);
1363 tcu::Vec4 lookupBias (0.0f);
1365 getLookupScaleBias(m_imageFormat, lookupScale, lookupBias);
1367 // Render out coordinates
1369 const rr::RenderState renderState(refRenderer.getViewportState());
1370 refRenderer.draw(renderState, rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
1375 const tcu::Sampler sampler = mapVkSampler(m_samplerParams);
1376 const float referenceLod = de::clamp(m_samplerParams.mipLodBias + m_samplerLod, m_samplerParams.minLod, m_samplerParams.maxLod);
1377 const float lodError = 1.0f / static_cast<float>((1u << limits.mipmapPrecisionBits) - 1u);
1378 const tcu::Vec2 lodBounds (referenceLod - lodError, referenceLod + lodError);
1379 const vk::VkImageSubresourceRange subresource = resolveSubresourceRange(*m_texture, m_subresourceRange);
1381 const tcu::ConstPixelBufferAccess coordAccess = refRenderer.getAccess();
1382 tcu::TextureLevel errorMask (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), (int)m_renderSize.x(), (int)m_renderSize.y());
1383 const tcu::PixelBufferAccess errorAccess = errorMask.getAccess();
1385 const bool allowSnorm8Bug = m_texture->getTextureFormat().type == tcu::TextureFormat::SNORM_INT8 &&
1386 (m_samplerParams.minFilter == VK_FILTER_LINEAR || m_samplerParams.magFilter == VK_FILTER_LINEAR);
1388 tcu::LookupPrecision lookupPrecision;
1390 // Set precision requirements - very low for these tests as
1391 // the point of the test is not to validate accuracy.
1392 lookupPrecision.coordBits = tcu::IVec3(17, 17, 17);
1393 lookupPrecision.uvwBits = tcu::IVec3(5, 5, 5);
1394 lookupPrecision.colorMask = tcu::BVec4(true);
1395 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(tcu::IVec4(8, 8, 8, 8)) / swizzleScaleBias(lookupScale, m_componentMapping);
1397 if (tcu::isSRGB(m_texture->getTextureFormat()))
1398 lookupPrecision.colorThreshold += tcu::Vec4(4.f / 255.f);
1400 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1402 // Read back result image
1403 UniquePtr<tcu::TextureLevel> result (readColorAttachment(m_context.getDeviceInterface(),
1404 m_context.getDevice(),
1405 m_context.getUniversalQueue(),
1406 m_context.getUniversalQueueFamilyIndex(),
1407 m_context.getDefaultAllocator(),
1408 **m_colorImages[imgNdx],
1411 const tcu::ConstPixelBufferAccess resultAccess = result->getAccess();
1412 bool compareOk = validateResultImage(*m_texture,
1425 if (!compareOk && allowSnorm8Bug)
1427 // HW waiver (VK-GL-CTS issue: 229)
1429 // Due to an error in bit replication of the fixed point SNORM values, linear filtered
1430 // negative SNORM values will differ slightly from ideal precision in the last bit, moving
1431 // the values towards 0.
1433 // This occurs on all members of the PowerVR Rogue family of GPUs
1434 tcu::LookupPrecision relaxedPrecision;
1436 relaxedPrecision.colorThreshold += tcu::Vec4(4.f / 255.f);
1438 m_context.getTestContext().getLog()
1439 << tcu::TestLog::Message
1440 << "Warning: Strict validation failed, re-trying with lower precision for SNORM8 format"
1441 << tcu::TestLog::EndMessage;
1444 compareOk = validateResultImage(*m_texture,
1459 m_context.getTestContext().getLog()
1460 << tcu::TestLog::Image("Result", "Result Image", resultAccess)
1461 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorAccess);
1463 compareOkAll = compareOkAll && compareOk;
1470 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Inaccurate filtering results");
1472 return tcu::TestStatus::pass("Result image matches reference");
1475 return tcu::TestStatus::fail("Image mismatch");