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 ¶ms, 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 ¶ms)
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