xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/ycbcr/vktYCbCrImageQueryTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief OpImageQuery & YCbCr Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktYCbCrImageQueryTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26 #include "vktTestGroupUtil.hpp"
27 #include "vktShaderExecutor.hpp"
28 #include "vktYCbCrUtil.hpp"
29 #include "vktDrawUtil.hpp"
30 
31 #include "vkStrUtil.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkCmdUtil.hpp"
39 #include "vkBarrierUtil.hpp"
40 
41 #include "tcuTestLog.hpp"
42 #include "tcuVectorUtil.hpp"
43 #include "tcuTexLookupVerifier.hpp"
44 
45 #include "deStringUtil.hpp"
46 #include "deSharedPtr.hpp"
47 #include "deUniquePtr.hpp"
48 #include "deRandom.hpp"
49 #include "deSTLUtil.hpp"
50 
51 namespace vkt
52 {
53 namespace ycbcr
54 {
55 namespace
56 {
57 
58 using namespace vk;
59 using namespace shaderexecutor;
60 
61 using de::MovePtr;
62 using de::UniquePtr;
63 using std::string;
64 using std::vector;
65 using tcu::TestLog;
66 using tcu::UVec2;
67 using tcu::Vec2;
68 using tcu::Vec4;
69 
70 enum QueryType
71 {
72     QUERY_TYPE_IMAGE_SIZE_LOD, // OpImageQuerySizeLod
73     QUERY_TYPE_IMAGE_LOD,      // OpImageQueryLod
74     QUERY_TYPE_IMAGE_LEVELS,   // OpImageQueryLevels
75 
76     QUERY_TYPE_LAST
77 };
78 
79 struct TestParameters
80 {
81     QueryType query;
82     VkFormat format;
83     VkImageCreateFlags flags;
84     glu::ShaderType shaderType;
85 
TestParametersvkt::ycbcr::__anond4f4664b0111::TestParameters86     TestParameters(QueryType query_, VkFormat format_, VkImageCreateFlags flags_, glu::ShaderType shaderType_)
87         : query(query_)
88         , format(format_)
89         , flags(flags_)
90         , shaderType(shaderType_)
91     {
92     }
93 
TestParametersvkt::ycbcr::__anond4f4664b0111::TestParameters94     TestParameters(void)
95         : query(QUERY_TYPE_LAST)
96         , format(VK_FORMAT_UNDEFINED)
97         , flags(0u)
98         , shaderType(glu::SHADERTYPE_LAST)
99     {
100     }
101 };
102 
getShaderSpec(const TestParameters & params,const SourceCollections * programCollection=nullptr)103 ShaderSpec getShaderSpec(const TestParameters &params, const SourceCollections *programCollection = nullptr)
104 {
105     ShaderSpec spec;
106     const char *expr         = DE_NULL;
107     glu::DataType resultType = glu::TYPE_LAST;
108 
109     switch (params.query)
110     {
111     case QUERY_TYPE_IMAGE_SIZE_LOD:
112         expr       = "textureSize(u_image, lod)";
113         resultType = glu::TYPE_INT_VEC2;
114         break;
115 
116     case QUERY_TYPE_IMAGE_LEVELS:
117         expr       = "textureQueryLevels(u_image)";
118         resultType = glu::TYPE_INT;
119         break;
120 
121     default:
122         DE_FATAL("Unknown query");
123     }
124 
125     spec.glslVersion = glu::GLSL_VERSION_450;
126 
127     spec.inputs.push_back(Symbol("lod", glu::VarType(glu::TYPE_INT, glu::PRECISION_HIGHP)));
128     spec.outputs.push_back(Symbol("result", glu::VarType(resultType, glu::PRECISION_HIGHP)));
129 
130     spec.globalDeclarations = "layout(binding = 0, set = 1) uniform highp sampler2D u_image;\n";
131 
132     spec.source = string("result = ") + expr + ";\n";
133 
134     const bool isMeshShadingStage =
135         (params.shaderType == glu::SHADERTYPE_MESH || params.shaderType == glu::SHADERTYPE_TASK);
136 
137     if (isMeshShadingStage && programCollection)
138     {
139         const ShaderBuildOptions buildOptions(programCollection->usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
140         spec.buildOptions = buildOptions;
141     }
142 
143     return spec;
144 }
145 
createTestImage(const DeviceInterface & vkd,VkDevice device,VkFormat format,const UVec2 & size,VkImageCreateFlags createFlags)146 Move<VkImage> createTestImage(const DeviceInterface &vkd, VkDevice device, VkFormat format, const UVec2 &size,
147                               VkImageCreateFlags createFlags)
148 {
149     const VkImageCreateInfo createInfo = {
150         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
151         DE_NULL,
152         createFlags,
153         VK_IMAGE_TYPE_2D,
154         format,
155         makeExtent3D(size.x(), size.y(), 1u),
156         1u, // mipLevels
157         1u, // arrayLayers
158         VK_SAMPLE_COUNT_1_BIT,
159         VK_IMAGE_TILING_OPTIMAL,
160         VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
161         VK_SHARING_MODE_EXCLUSIVE,
162         0u,
163         (const uint32_t *)DE_NULL,
164         VK_IMAGE_LAYOUT_UNDEFINED,
165     };
166 
167     return createImage(vkd, device, &createInfo);
168 }
169 
createImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkSamplerYcbcrConversion conversion)170 Move<VkImageView> createImageView(const DeviceInterface &vkd, VkDevice device, VkImage image, VkFormat format,
171                                   VkSamplerYcbcrConversion conversion)
172 {
173     const VkSamplerYcbcrConversionInfo samplerConversionInfo = {VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
174                                                                 DE_NULL, conversion};
175 
176     const VkImageViewCreateInfo viewInfo = {
177         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
178         (conversion != DE_NULL) ? &samplerConversionInfo : DE_NULL,
179         (VkImageViewCreateFlags)0,
180         image,
181         VK_IMAGE_VIEW_TYPE_2D,
182         format,
183         {
184             VK_COMPONENT_SWIZZLE_IDENTITY,
185             VK_COMPONENT_SWIZZLE_IDENTITY,
186             VK_COMPONENT_SWIZZLE_IDENTITY,
187             VK_COMPONENT_SWIZZLE_IDENTITY,
188         },
189         {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u},
190     };
191 
192     return createImageView(vkd, device, &viewInfo);
193 }
194 
195 class TestImage
196 {
197 public:
198     TestImage(const Context &context, const DeviceInterface &vkd, VkDevice device, Allocator &allocator,
199               VkFormat format, const UVec2 &size, const VkImageCreateFlags createFlags,
200               VkSamplerYcbcrConversion conversion);
201 
getSize(void) const202     const UVec2 &getSize(void) const
203     {
204         return m_size;
205     }
getImageView(void) const206     VkImageView getImageView(void) const
207     {
208         return *m_imageView;
209     }
210 
211 private:
212     const UVec2 m_size;
213     const Unique<VkImage> m_image;
214     const vector<AllocationSp> m_allocations;
215     const Unique<VkImageView> m_imageView;
216 };
217 
TestImage(const Context & context,const DeviceInterface & vkd,VkDevice device,Allocator & allocator,VkFormat format,const UVec2 & size,const VkImageCreateFlags createFlags,VkSamplerYcbcrConversion conversion)218 TestImage::TestImage(const Context &context, const DeviceInterface &vkd, VkDevice device, Allocator &allocator,
219                      VkFormat format, const UVec2 &size, const VkImageCreateFlags createFlags,
220                      VkSamplerYcbcrConversion conversion)
221     : m_size(size)
222     , m_image(createTestImage(vkd, device, format, size, createFlags))
223     , m_allocations(allocateAndBindImageMemory(vkd, device, allocator, *m_image, format, createFlags))
224     , m_imageView(createImageView(vkd, device, *m_image, format, conversion))
225 {
226     // Transition image layout
227     {
228         Move<VkCommandPool> cmdPool;
229         Move<VkCommandBuffer> cmdBuffer;
230         const VkQueue queue             = context.getUniversalQueue();
231         const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
232 
233         cmdPool   = createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
234         cmdBuffer = allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
235 
236         beginCommandBuffer(vkd, *cmdBuffer);
237 
238         VkImageSubresourceRange subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u};
239         const VkImageMemoryBarrier imageBarrier =
240             makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
241                                    VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, *m_image, subresourceRange);
242 
243         vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL,
244                                0u, DE_NULL, 1u, &imageBarrier);
245 
246         endCommandBuffer(vkd, *cmdBuffer);
247         submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
248     }
249 }
250 
251 typedef de::SharedPtr<TestImage> TestImageSp;
252 
createDescriptorSetLayout(const DeviceInterface & vkd,VkDevice device,VkSampler sampler)253 Move<VkDescriptorSetLayout> createDescriptorSetLayout(const DeviceInterface &vkd, VkDevice device, VkSampler sampler)
254 {
255     const VkDescriptorSetLayoutBinding binding       = {0u, // binding
256                                                         VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
257                                                         1u, // descriptorCount
258                                                         VK_SHADER_STAGE_ALL, &sampler};
259     const VkDescriptorSetLayoutCreateInfo layoutInfo = {
260         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
261         DE_NULL,
262         (VkDescriptorSetLayoutCreateFlags)0u,
263         1u,
264         &binding,
265     };
266 
267     return createDescriptorSetLayout(vkd, device, &layoutInfo);
268 }
269 
createDescriptorPool(const DeviceInterface & vkd,VkDevice device,const uint32_t combinedSamplerDescriptorCount)270 Move<VkDescriptorPool> createDescriptorPool(const DeviceInterface &vkd, VkDevice device,
271                                             const uint32_t combinedSamplerDescriptorCount)
272 {
273     const VkDescriptorPoolSize poolSizes[] = {
274         {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, combinedSamplerDescriptorCount},
275     };
276     const VkDescriptorPoolCreateInfo poolInfo = {
277         VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
278         DE_NULL,
279         (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
280         1u, // maxSets
281         DE_LENGTH_OF_ARRAY(poolSizes),
282         poolSizes,
283     };
284 
285     return createDescriptorPool(vkd, device, &poolInfo);
286 }
287 
createDescriptorSet(const DeviceInterface & vkd,VkDevice device,VkDescriptorPool descPool,VkDescriptorSetLayout descLayout)288 Move<VkDescriptorSet> createDescriptorSet(const DeviceInterface &vkd, VkDevice device, VkDescriptorPool descPool,
289                                           VkDescriptorSetLayout descLayout)
290 {
291     const VkDescriptorSetAllocateInfo allocInfo = {
292         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL, descPool, 1u, &descLayout,
293     };
294 
295     return allocateDescriptorSet(vkd, device, &allocInfo);
296 }
297 
bindImage(const DeviceInterface & vkd,VkDevice device,VkDescriptorSet descriptorSet,VkImageView imageView,VkSampler sampler)298 void bindImage(const DeviceInterface &vkd, VkDevice device, VkDescriptorSet descriptorSet, VkImageView imageView,
299                VkSampler sampler)
300 {
301     const VkDescriptorImageInfo imageInfo      = {sampler, imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
302     const VkWriteDescriptorSet descriptorWrite = {
303         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
304         DE_NULL,
305         descriptorSet,
306         0u, // dstBinding
307         0u, // dstArrayElement
308         1u, // descriptorCount
309         VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
310         &imageInfo,
311         (const VkDescriptorBufferInfo *)DE_NULL,
312         (const VkBufferView *)DE_NULL,
313     };
314 
315     vkd.updateDescriptorSets(device, 1u, &descriptorWrite, 0u, DE_NULL);
316 }
317 
getMaxPlaneDivisor(const PlanarFormatDescription & formatDesc)318 UVec2 getMaxPlaneDivisor(const PlanarFormatDescription &formatDesc)
319 {
320     UVec2 maxDivisor(formatDesc.blockWidth, formatDesc.blockHeight);
321 
322     for (uint32_t ndx = 0; ndx < formatDesc.numPlanes; ++ndx)
323     {
324         maxDivisor.x() = de::max<uint32_t>(maxDivisor.x(), formatDesc.planes[ndx].widthDivisor);
325         maxDivisor.y() = de::max<uint32_t>(maxDivisor.y(), formatDesc.planes[ndx].heightDivisor);
326     }
327 
328     return maxDivisor;
329 }
330 
testImageQuery(Context & context,TestParameters params)331 tcu::TestStatus testImageQuery(Context &context, TestParameters params)
332 {
333     const bool isYCbCrImage     = isYCbCrFormat(params.format);
334     const InstanceInterface &vk = context.getInstanceInterface();
335     const DeviceInterface &vkd  = context.getDeviceInterface();
336     const VkDevice device       = context.getDevice();
337 
338     const VkSamplerYcbcrConversionCreateInfo conversionInfo = {
339         VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
340         DE_NULL,
341         params.format,
342         VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
343         VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
344         {
345             VK_COMPONENT_SWIZZLE_IDENTITY,
346             VK_COMPONENT_SWIZZLE_IDENTITY,
347             VK_COMPONENT_SWIZZLE_IDENTITY,
348             VK_COMPONENT_SWIZZLE_IDENTITY,
349         },
350         VK_CHROMA_LOCATION_MIDPOINT,
351         VK_CHROMA_LOCATION_MIDPOINT,
352         VK_FILTER_NEAREST,
353         VK_FALSE, // forceExplicitReconstruction
354     };
355     const Unique<VkSamplerYcbcrConversion> conversion(
356         isYCbCrImage ? createSamplerYcbcrConversion(vkd, device, &conversionInfo) : Move<VkSamplerYcbcrConversion>());
357 
358     const VkSamplerYcbcrConversionInfo samplerConversionInfo = {
359         VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
360         DE_NULL,
361         *conversion,
362     };
363 
364     const VkSamplerCreateInfo samplerInfo = {
365         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
366         isYCbCrImage ? &samplerConversionInfo : DE_NULL,
367         0u,
368         VK_FILTER_NEAREST,                       // magFilter
369         VK_FILTER_NEAREST,                       // minFilter
370         VK_SAMPLER_MIPMAP_MODE_NEAREST,          // mipmapMode
371         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // addressModeU
372         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // addressModeV
373         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // addressModeW
374         0.0f,                                    // mipLodBias
375         VK_FALSE,                                // anisotropyEnable
376         1.0f,                                    // maxAnisotropy
377         VK_FALSE,                                // compareEnable
378         VK_COMPARE_OP_ALWAYS,                    // compareOp
379         0.0f,                                    // minLod
380         0.0f,                                    // maxLod
381         VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // borderColor
382         VK_FALSE,                                // unnormalizedCoords
383     };
384 
385     uint32_t combinedSamplerDescriptorCount = 1;
386 
387     if (isYCbCrImage)
388     {
389         const VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {
390             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,        // sType
391             DE_NULL,                                                      // pNext
392             params.format,                                                // format
393             VK_IMAGE_TYPE_2D,                                             // type
394             VK_IMAGE_TILING_OPTIMAL,                                      // tiling
395             VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, // usage
396             params.flags                                                  // flags
397         };
398 
399         VkSamplerYcbcrConversionImageFormatProperties samplerYcbcrConversionImage = {};
400         samplerYcbcrConversionImage.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES;
401         samplerYcbcrConversionImage.pNext = DE_NULL;
402 
403         VkImageFormatProperties2 imageFormatProperties = {};
404         imageFormatProperties.sType                    = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
405         imageFormatProperties.pNext                    = &samplerYcbcrConversionImage;
406 
407         VK_CHECK(vk.getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &imageFormatInfo,
408                                                             &imageFormatProperties));
409         combinedSamplerDescriptorCount = samplerYcbcrConversionImage.combinedImageSamplerDescriptorCount;
410     }
411 
412     const Unique<VkSampler> sampler(createSampler(vkd, device, &samplerInfo));
413     const Unique<VkDescriptorSetLayout> descLayout(createDescriptorSetLayout(vkd, device, *sampler));
414     const Unique<VkDescriptorPool> descPool(createDescriptorPool(vkd, device, combinedSamplerDescriptorCount));
415     const Unique<VkDescriptorSet> descSet(createDescriptorSet(vkd, device, *descPool, *descLayout));
416 
417     vector<TestImageSp> testImages;
418 
419     if (params.query == QUERY_TYPE_IMAGE_SIZE_LOD)
420     {
421         const PlanarFormatDescription &formatDesc = getPlanarFormatDescription(params.format);
422         const UVec2 maxDivisor                    = getMaxPlaneDivisor(formatDesc);
423         vector<UVec2> testSizes;
424 
425         testSizes.push_back(maxDivisor);
426         testSizes.push_back(maxDivisor * UVec2(2u, 1u));
427         testSizes.push_back(maxDivisor * UVec2(1u, 2u));
428         testSizes.push_back(maxDivisor * UVec2(63u, 79u));
429         testSizes.push_back(maxDivisor * UVec2(99u, 1u));
430         testSizes.push_back(maxDivisor * UVec2(421u, 1117u));
431 
432         testImages.resize(testSizes.size());
433 
434         for (size_t ndx = 0; ndx < testSizes.size(); ++ndx)
435             testImages[ndx] = TestImageSp(new TestImage(context, vkd, device, context.getDefaultAllocator(),
436                                                         params.format, testSizes[ndx], params.flags, *conversion));
437     }
438     else
439         testImages.push_back(TestImageSp(new TestImage(context, vkd, device, context.getDefaultAllocator(),
440                                                        params.format, UVec2(16, 18), params.flags, *conversion)));
441 
442     {
443         UniquePtr<ShaderExecutor> executor(
444             createExecutor(context, params.shaderType, getShaderSpec(params), *descLayout));
445         bool allOk = true;
446 
447         for (size_t imageNdx = 0; imageNdx < testImages.size(); ++imageNdx)
448         {
449             const uint32_t lod = 0u;
450             UVec2 result(~0u, ~0u);
451             const void *inputs[] = {&lod};
452             void *outputs[]      = {result.getPtr()};
453 
454             bindImage(vkd, device, *descSet, testImages[imageNdx]->getImageView(), *sampler);
455 
456             executor->execute(1, inputs, outputs, *descSet);
457 
458             switch (params.query)
459             {
460             case QUERY_TYPE_IMAGE_SIZE_LOD:
461             {
462                 const UVec2 reference = testImages[imageNdx]->getSize();
463 
464                 if (result != reference)
465                 {
466                     context.getTestContext().getLog() << TestLog::Message << "ERROR: Image " << imageNdx << ": got "
467                                                       << result << ", expected " << reference << TestLog::EndMessage;
468                     allOk = false;
469                 }
470                 break;
471             }
472 
473             case QUERY_TYPE_IMAGE_LEVELS:
474             {
475                 if (result.x() != 1u)
476                 {
477                     context.getTestContext().getLog() << TestLog::Message << "ERROR: Image " << imageNdx << ": got "
478                                                       << result.x() << ", expected " << 1 << TestLog::EndMessage;
479                     allOk = false;
480                 }
481                 break;
482             }
483 
484             default:
485                 DE_FATAL("Invalid query type");
486             }
487         }
488 
489         if (allOk)
490             return tcu::TestStatus::pass("Queries passed");
491         else
492             return tcu::TestStatus::fail("Got invalid results");
493     }
494 }
495 
checkSupport(Context & context,TestParameters params)496 void checkSupport(Context &context, TestParameters params)
497 {
498     const bool isYCbCrImage = isYCbCrFormat(params.format);
499 
500     if (isYCbCrImage)
501         checkImageSupport(context, params.format, params.flags);
502 
503     checkSupportShader(context, params.shaderType);
504 }
505 
testImageQueryLod(Context & context,TestParameters params)506 tcu::TestStatus testImageQueryLod(Context &context, TestParameters params)
507 {
508     const bool isYCbCrImage     = isYCbCrFormat(params.format);
509     const InstanceInterface &vk = context.getInstanceInterface();
510     const DeviceInterface &vkd  = context.getDeviceInterface();
511     const VkDevice device       = context.getDevice();
512 
513     const VkSamplerYcbcrConversionCreateInfo conversionInfo = {
514         VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
515         DE_NULL,
516         params.format,
517         VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
518         VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
519         {
520             VK_COMPONENT_SWIZZLE_IDENTITY,
521             VK_COMPONENT_SWIZZLE_IDENTITY,
522             VK_COMPONENT_SWIZZLE_IDENTITY,
523             VK_COMPONENT_SWIZZLE_IDENTITY,
524         },
525         VK_CHROMA_LOCATION_MIDPOINT,
526         VK_CHROMA_LOCATION_MIDPOINT,
527         VK_FILTER_NEAREST,
528         VK_FALSE, // forceExplicitReconstruction
529     };
530     const Unique<VkSamplerYcbcrConversion> conversion(
531         isYCbCrImage ? createSamplerYcbcrConversion(vkd, device, &conversionInfo) : Move<VkSamplerYcbcrConversion>());
532 
533     const VkSamplerYcbcrConversionInfo samplerConversionInfo = {
534         VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
535         DE_NULL,
536         *conversion,
537     };
538 
539     const VkSamplerCreateInfo samplerInfo = {
540         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
541         isYCbCrImage ? &samplerConversionInfo : DE_NULL,
542         0u,
543         VK_FILTER_NEAREST,                       // magFilter
544         VK_FILTER_NEAREST,                       // minFilter
545         VK_SAMPLER_MIPMAP_MODE_NEAREST,          // mipmapMode
546         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // addressModeU
547         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // addressModeV
548         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // addressModeW
549         0.0f,                                    // mipLodBias
550         VK_FALSE,                                // anisotropyEnable
551         1.0f,                                    // maxAnisotropy
552         VK_FALSE,                                // compareEnable
553         VK_COMPARE_OP_ALWAYS,                    // compareOp
554         0.0f,                                    // minLod
555         0.0f,                                    // maxLod
556         VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // borderColor
557         VK_FALSE,                                // unnormalizedCoords
558     };
559 
560     uint32_t combinedSamplerDescriptorCount = 1;
561 
562     if (isYCbCrImage)
563     {
564         const VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {
565             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,        // sType;
566             DE_NULL,                                                      // pNext;
567             params.format,                                                // format;
568             VK_IMAGE_TYPE_2D,                                             // type;
569             VK_IMAGE_TILING_OPTIMAL,                                      // tiling;
570             VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, // usage;
571             params.flags                                                  // flags;
572         };
573 
574         VkSamplerYcbcrConversionImageFormatProperties samplerYcbcrConversionImage = {};
575         samplerYcbcrConversionImage.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES;
576         samplerYcbcrConversionImage.pNext = DE_NULL;
577 
578         VkImageFormatProperties2 imageFormatProperties = {};
579         imageFormatProperties.sType                    = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
580         imageFormatProperties.pNext                    = &samplerYcbcrConversionImage;
581 
582         VK_CHECK(vk.getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &imageFormatInfo,
583                                                             &imageFormatProperties));
584         combinedSamplerDescriptorCount = samplerYcbcrConversionImage.combinedImageSamplerDescriptorCount;
585     }
586 
587     const Unique<VkSampler> sampler(createSampler(vkd, device, &samplerInfo));
588     const Unique<VkDescriptorSetLayout> descLayout(createDescriptorSetLayout(vkd, device, *sampler));
589     const Unique<VkDescriptorPool> descPool(createDescriptorPool(vkd, device, combinedSamplerDescriptorCount));
590     const Unique<VkDescriptorSet> descSet(createDescriptorSet(vkd, device, *descPool, *descLayout));
591 
592     vector<TestImageSp> testImages;
593 
594     DE_ASSERT(params.query == QUERY_TYPE_IMAGE_LOD);
595     DE_ASSERT(params.shaderType == glu::SHADERTYPE_FRAGMENT);
596 
597     {
598         const PlanarFormatDescription &formatDesc = getPlanarFormatDescription(params.format);
599         const UVec2 maxDivisor                    = getMaxPlaneDivisor(formatDesc);
600         vector<UVec2> testSizes;
601 
602         testSizes.push_back(maxDivisor);
603         testSizes.push_back(maxDivisor * UVec2(2u, 1u));
604         testSizes.push_back(maxDivisor * UVec2(1u, 2u));
605         testSizes.push_back(maxDivisor * UVec2(4u, 123u));
606         testSizes.push_back(maxDivisor * UVec2(312u, 13u));
607         testSizes.push_back(maxDivisor * UVec2(841u, 917u));
608 
609         testImages.resize(testSizes.size());
610 
611         for (size_t ndx = 0; ndx < testSizes.size(); ++ndx)
612             testImages[ndx] = TestImageSp(new TestImage(context, vkd, device, context.getDefaultAllocator(),
613                                                         params.format, testSizes[ndx], params.flags, *conversion));
614     }
615 
616     {
617         using namespace drawutil;
618 
619         struct LocalUtil
620         {
621             static vector<Vec4> getVertices(void)
622             {
623                 vector<Vec4> vertices;
624 
625                 vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
626                 vertices.push_back(Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
627                 vertices.push_back(Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
628 
629                 vertices.push_back(Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
630                 vertices.push_back(Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
631                 vertices.push_back(Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
632 
633                 return vertices;
634             }
635 
636             static VulkanProgram getProgram(Context &ctx, VkDescriptorSetLayout descriptorLayout,
637                                             VkDescriptorSet descriptorSet)
638             {
639                 VulkanProgram prog(std::vector<VulkanShader>{
640                     VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, ctx.getBinaryCollection().get("vert")),
641                     VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, ctx.getBinaryCollection().get("frag"))});
642                 prog.descriptorSet       = descriptorSet;
643                 prog.descriptorSetLayout = descriptorLayout;
644 
645                 return prog;
646             }
647         };
648 
649         const UVec2 renderSize(128, 256);
650         FrameBufferState frameBufferState(renderSize.x(), renderSize.y());
651         frameBufferState.colorFormat = VK_FORMAT_R32G32_SFLOAT;
652         const vector<Vec4> vertices(LocalUtil::getVertices());
653         PipelineState pipelineState(context.getDeviceProperties().limits.subPixelPrecisionBits);
654         const DrawCallData drawCallData(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vertices);
655         const VulkanProgram program(LocalUtil::getProgram(context, *descLayout, *descSet));
656 
657         bool allOk = true;
658 
659         context.getTestContext().getLog()
660             << TestLog::Message << "Rendering " << renderSize << " quad" << TestLog::EndMessage;
661 
662         for (size_t imageNdx = 0; imageNdx < testImages.size(); ++imageNdx)
663         {
664             context.getTestContext().getLog()
665                 << TestLog::Message << "Testing image size " << testImages[imageNdx]->getSize() << TestLog::EndMessage;
666 
667             bindImage(vkd, device, *descSet, testImages[imageNdx]->getImageView(), *sampler);
668 
669             VulkanDrawContext renderer(context, frameBufferState);
670             renderer.registerDrawObject(pipelineState, program, drawCallData);
671             renderer.draw();
672 
673             {
674                 // Only du/dx and dv/dy are non-zero
675                 const Vec2 dtdp = testImages[imageNdx]->getSize().cast<float>() / renderSize.cast<float>();
676                 const tcu::LodPrecision lodPrec(16, 4); // Pretty lax since we are not verifying LOD precision
677                 const Vec2 lodBounds(tcu::computeLodBoundsFromDerivates(dtdp.x(), 0.0f, 0.0f, dtdp.y(), lodPrec));
678                 tcu::ConstPixelBufferAccess resultImg(renderer.getColorPixels());
679                 const int maxErrors = 5;
680                 int numErrors       = 0;
681 
682                 for (int y = 0; y < resultImg.getHeight(); ++y)
683                     for (int x = 0; x < resultImg.getWidth(); ++x)
684                     {
685                         const Vec2 result  = resultImg.getPixel(x, y).swizzle(0, 1);
686                         const bool levelOk = result.x() == 0.0f;
687                         const bool lodOk   = de::inRange(result.y(), lodBounds.x(), lodBounds.y());
688 
689                         if (!levelOk || !lodOk)
690                         {
691                             if (numErrors < maxErrors)
692                             {
693                                 context.getTestContext().getLog()
694                                     << TestLog::Message << "ERROR: At (" << x << ", " << y << ")"
695                                     << ": got " << result << ", expected (0, [" << lodBounds.x() << ", "
696                                     << lodBounds.y() << "])" << TestLog::EndMessage;
697                             }
698                             else if (numErrors == maxErrors)
699                                 context.getTestContext().getLog() << TestLog::Message << "..." << TestLog::EndMessage;
700 
701                             numErrors += 1;
702                         }
703                     }
704 
705                 allOk = allOk && (numErrors == 0);
706             }
707         }
708 
709         if (allOk)
710             return tcu::TestStatus::pass("Queries passed");
711         else
712             return tcu::TestStatus::fail("Got invalid results");
713     }
714 }
715 
initImageQueryPrograms(SourceCollections & dst,TestParameters params)716 void initImageQueryPrograms(SourceCollections &dst, TestParameters params)
717 {
718     const ShaderSpec spec = getShaderSpec(params, &dst);
719 
720     generateSources(params.shaderType, spec, dst);
721 }
722 
initImageQueryLodPrograms(SourceCollections & dst,TestParameters)723 void initImageQueryLodPrograms(SourceCollections &dst, TestParameters)
724 {
725     dst.glslSources.add("vert") << glu::VertexSource("#version 450\n"
726                                                      "layout(location = 0) in highp vec4 a_position;\n"
727                                                      "layout(location = 0) out highp vec2 v_texCoord;\n"
728                                                      "\n"
729                                                      "void main (void)\n"
730                                                      "{\n"
731                                                      "    gl_Position = a_position;\n"
732                                                      "    v_texCoord = a_position.xy * 0.5 - 0.5;\n"
733                                                      "}\n");
734     dst.glslSources.add("frag") << glu::FragmentSource("#version 450\n"
735                                                        "layout(binding = 0, set = 0) uniform highp sampler2D u_image;\n"
736                                                        "layout(location = 0) in highp vec2 v_texCoord;\n"
737                                                        "layout(location = 0) out highp vec2 o_lod;\n"
738                                                        "\n"
739                                                        "void main (void)\n"
740                                                        "{\n"
741                                                        "    o_lod = textureQueryLod(u_image, v_texCoord);\n"
742                                                        "}\n");
743 }
744 
addImageQueryCase(tcu::TestCaseGroup * group,const TestParameters & params)745 void addImageQueryCase(tcu::TestCaseGroup *group, const TestParameters &params)
746 {
747     std::string name = de::toLower(de::toString(params.format).substr(10));
748     const bool isLod = params.query == QUERY_TYPE_IMAGE_LOD;
749 
750     if ((params.flags & VK_IMAGE_CREATE_DISJOINT_BIT) != 0)
751         name += "_disjoint";
752 
753     addFunctionCaseWithPrograms(group, name, checkSupport, isLod ? initImageQueryLodPrograms : initImageQueryPrograms,
754                                 isLod ? testImageQueryLod : testImageQuery, params);
755 }
756 
757 struct QueryGroupParams
758 {
759     QueryType query;
760     glu::ShaderType shaderType;
761 
QueryGroupParamsvkt::ycbcr::__anond4f4664b0111::QueryGroupParams762     QueryGroupParams(QueryType query_, glu::ShaderType shaderType_) : query(query_), shaderType(shaderType_)
763     {
764     }
765 
QueryGroupParamsvkt::ycbcr::__anond4f4664b0111::QueryGroupParams766     QueryGroupParams(void) : query(QUERY_TYPE_LAST), shaderType(glu::SHADERTYPE_LAST)
767     {
768     }
769 };
770 
populateQueryInShaderGroup(tcu::TestCaseGroup * group,QueryGroupParams params)771 void populateQueryInShaderGroup(tcu::TestCaseGroup *group, QueryGroupParams params)
772 {
773     // "Reference" formats for testing
774     addImageQueryCase(group, TestParameters(params.query, VK_FORMAT_R8G8B8A8_UNORM, 0u, params.shaderType));
775 
776     for (int formatNdx = VK_YCBCR_FORMAT_FIRST; formatNdx < VK_YCBCR_FORMAT_LAST; formatNdx++)
777     {
778         const VkFormat format = (VkFormat)formatNdx;
779 
780         addImageQueryCase(group, TestParameters(params.query, format, 0u, params.shaderType));
781 
782         if (getPlaneCount(format) > 1)
783             addImageQueryCase(group,
784                               TestParameters(params.query, format, (VkImageCreateFlags)VK_IMAGE_CREATE_DISJOINT_BIT,
785                                              params.shaderType));
786     }
787 
788     for (int formatNdx = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT; formatNdx <= VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT;
789          formatNdx++)
790     {
791         const VkFormat format = (VkFormat)formatNdx;
792 
793         addImageQueryCase(group, TestParameters(params.query, format, 0u, params.shaderType));
794 
795         if (getPlaneCount(format) > 1)
796             addImageQueryCase(group,
797                               TestParameters(params.query, format, (VkImageCreateFlags)VK_IMAGE_CREATE_DISJOINT_BIT,
798                                              params.shaderType));
799     }
800 }
801 
populateQueryGroup(tcu::TestCaseGroup * group,QueryType query)802 void populateQueryGroup(tcu::TestCaseGroup *group, QueryType query)
803 {
804     for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; ++shaderTypeNdx)
805     {
806         const glu::ShaderType shaderType = (glu::ShaderType)shaderTypeNdx;
807 
808         if (query == QUERY_TYPE_IMAGE_LOD && shaderType != glu::SHADERTYPE_FRAGMENT)
809             continue;
810 
811         if (!executorSupported(shaderType))
812             continue;
813 
814         addTestGroup(group, glu::getShaderTypeName(shaderType), populateQueryInShaderGroup,
815                      QueryGroupParams(query, shaderType));
816     }
817 }
818 
populateImageQueryGroup(tcu::TestCaseGroup * group)819 void populateImageQueryGroup(tcu::TestCaseGroup *group)
820 {
821     // OpImageQuerySizeLod
822     addTestGroup(group, "size_lod", populateQueryGroup, QUERY_TYPE_IMAGE_SIZE_LOD);
823     // OpImageQueryLod
824     addTestGroup(group, "lod", populateQueryGroup, QUERY_TYPE_IMAGE_LOD);
825     // OpImageQueryLevels
826     addTestGroup(group, "levels", populateQueryGroup, QUERY_TYPE_IMAGE_LEVELS);
827 }
828 
829 } // namespace
830 
createImageQueryTests(tcu::TestContext & testCtx)831 tcu::TestCaseGroup *createImageQueryTests(tcu::TestContext &testCtx)
832 {
833     return createTestGroup(testCtx, "query", populateImageQueryGroup);
834 }
835 
836 } // namespace ycbcr
837 } // namespace vkt
838