1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 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
39 #include "tcuTestLog.hpp"
40 #include "tcuVectorUtil.hpp"
41 #include "tcuTexLookupVerifier.hpp"
42
43 #include "deStringUtil.hpp"
44 #include "deSharedPtr.hpp"
45 #include "deUniquePtr.hpp"
46 #include "deRandom.hpp"
47 #include "deSTLUtil.hpp"
48
49 namespace vkt
50 {
51 namespace ycbcr
52 {
53 namespace
54 {
55
56 using namespace vk;
57 using namespace shaderexecutor;
58
59 using tcu::UVec2;
60 using tcu::Vec2;
61 using tcu::Vec4;
62 using tcu::TestLog;
63 using de::MovePtr;
64 using de::UniquePtr;
65 using std::vector;
66 using std::string;
67
68 typedef de::SharedPtr<Allocation> AllocationSp;
69 typedef de::SharedPtr<vk::Unique<VkBuffer> > VkBufferSp;
70
71 enum QueryType
72 {
73 QUERY_TYPE_IMAGE_SIZE_LOD, // OpImageQuerySizeLod
74 QUERY_TYPE_IMAGE_LOD, // OpImageQueryLod
75 QUERY_TYPE_IMAGE_LEVELS, // OpImageQueryLevels
76
77 QUERY_TYPE_LAST
78 };
79
80 struct TestParameters
81 {
82 QueryType query;
83 VkFormat format;
84 VkImageCreateFlags flags;
85 glu::ShaderType shaderType;
86
TestParametersvkt::ycbcr::__anon37eb4e340111::TestParameters87 TestParameters (QueryType query_, VkFormat format_, VkImageCreateFlags flags_, glu::ShaderType shaderType_)
88 : query (query_)
89 , format (format_)
90 , flags (flags_)
91 , shaderType(shaderType_)
92 {
93 }
94
TestParametersvkt::ycbcr::__anon37eb4e340111::TestParameters95 TestParameters (void)
96 : query (QUERY_TYPE_LAST)
97 , format (VK_FORMAT_UNDEFINED)
98 , flags (0u)
99 , shaderType(glu::SHADERTYPE_LAST)
100 {
101 }
102 };
103
getShaderSpec(const TestParameters & params)104 ShaderSpec getShaderSpec (const TestParameters& params)
105 {
106 ShaderSpec spec;
107 const char* expr = DE_NULL;
108 glu::DataType resultType = glu::TYPE_LAST;
109
110 switch (params.query)
111 {
112 case QUERY_TYPE_IMAGE_SIZE_LOD:
113 expr = "textureSize(u_image, lod)";
114 resultType = glu::TYPE_INT_VEC2;
115 break;
116
117 case QUERY_TYPE_IMAGE_LEVELS:
118 expr = "textureQueryLevels(u_image)";
119 resultType = glu::TYPE_INT;
120 break;
121
122 default:
123 DE_FATAL("Unknown query");
124 }
125
126 spec.glslVersion = glu::GLSL_VERSION_450;
127
128 spec.inputs.push_back(Symbol("lod", glu::VarType(glu::TYPE_INT, glu::PRECISION_HIGHP)));
129 spec.outputs.push_back(Symbol("result", glu::VarType(resultType, glu::PRECISION_HIGHP)));
130
131 spec.globalDeclarations =
132 "layout(binding = 0, set = 1) uniform highp sampler2D u_image;\n";
133
134 spec.source =
135 string("result = ") + expr + ";\n";
136
137 return spec;
138 }
139
createTestImage(const DeviceInterface & vkd,VkDevice device,VkFormat format,const UVec2 & size,VkImageCreateFlags createFlags)140 Move<VkImage> createTestImage (const DeviceInterface& vkd,
141 VkDevice device,
142 VkFormat format,
143 const UVec2& size,
144 VkImageCreateFlags createFlags)
145 {
146 const VkImageCreateInfo createInfo =
147 {
148 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
149 DE_NULL,
150 createFlags,
151 VK_IMAGE_TYPE_2D,
152 format,
153 makeExtent3D(size.x(), size.y(), 1u),
154 1u, // mipLevels
155 1u, // arrayLayers
156 VK_SAMPLE_COUNT_1_BIT,
157 VK_IMAGE_TILING_OPTIMAL,
158 VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT,
159 VK_SHARING_MODE_EXCLUSIVE,
160 0u,
161 (const deUint32*)DE_NULL,
162 VK_IMAGE_LAYOUT_UNDEFINED,
163 };
164
165 return createImage(vkd, device, &createInfo);
166 }
167
createImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format)168 Move<VkImageView> createImageView (const DeviceInterface& vkd,
169 VkDevice device,
170 VkImage image,
171 VkFormat format)
172 {
173 const VkImageViewCreateInfo viewInfo =
174 {
175 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
176 DE_NULL,
177 (VkImageViewCreateFlags)0,
178 image,
179 VK_IMAGE_VIEW_TYPE_2D,
180 format,
181 {
182 VK_COMPONENT_SWIZZLE_IDENTITY,
183 VK_COMPONENT_SWIZZLE_IDENTITY,
184 VK_COMPONENT_SWIZZLE_IDENTITY,
185 VK_COMPONENT_SWIZZLE_IDENTITY,
186 },
187 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },
188 };
189
190 return createImageView(vkd, device, &viewInfo);
191 }
192
193 class TestImage
194 {
195 public:
196 TestImage (const DeviceInterface& vkd,
197 VkDevice device,
198 Allocator& allocator,
199 VkFormat format,
200 const UVec2& size,
201 const VkImageCreateFlags createFlags);
202
getSize(void) const203 const UVec2& getSize (void) const { return m_size; }
getImageView(void) const204 VkImageView getImageView (void) const { return *m_imageView; }
205
206 private:
207 const UVec2 m_size;
208 const Unique<VkImage> m_image;
209 const vector<AllocationSp> m_allocations;
210 const Unique<VkImageView> m_imageView;
211 };
212
TestImage(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,VkFormat format,const UVec2 & size,const VkImageCreateFlags createFlags)213 TestImage::TestImage (const DeviceInterface& vkd,
214 VkDevice device,
215 Allocator& allocator,
216 VkFormat format,
217 const UVec2& size,
218 const VkImageCreateFlags createFlags)
219 : m_size (size)
220 , m_image (createTestImage(vkd, device, format, size, createFlags))
221 , m_allocations (allocateAndBindImageMemory(vkd, device, allocator, *m_image, format, createFlags))
222 , m_imageView (createImageView(vkd, device, *m_image, format))
223 {
224 }
225
226 typedef de::SharedPtr<TestImage> TestImageSp;
227
createDescriptorSetLayout(const DeviceInterface & vkd,VkDevice device,VkSampler sampler)228 Move<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vkd, VkDevice device, VkSampler sampler)
229 {
230 const VkDescriptorSetLayoutBinding binding =
231 {
232 0u, // binding
233 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
234 1u, // descriptorCount
235 VK_SHADER_STAGE_ALL,
236 &sampler
237 };
238 const VkDescriptorSetLayoutCreateInfo layoutInfo =
239 {
240 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
241 DE_NULL,
242 (VkDescriptorSetLayoutCreateFlags)0u,
243 1u,
244 &binding,
245 };
246
247 return createDescriptorSetLayout(vkd, device, &layoutInfo);
248 }
249
createDescriptorPool(const DeviceInterface & vkd,VkDevice device)250 Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vkd, VkDevice device)
251 {
252 const VkDescriptorPoolSize poolSizes[] =
253 {
254 { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u },
255 };
256 const VkDescriptorPoolCreateInfo poolInfo =
257 {
258 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
259 DE_NULL,
260 (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
261 1u, // maxSets
262 DE_LENGTH_OF_ARRAY(poolSizes),
263 poolSizes,
264 };
265
266 return createDescriptorPool(vkd, device, & poolInfo);
267 }
268
createDescriptorSet(const DeviceInterface & vkd,VkDevice device,VkDescriptorPool descPool,VkDescriptorSetLayout descLayout)269 Move<VkDescriptorSet> createDescriptorSet (const DeviceInterface& vkd,
270 VkDevice device,
271 VkDescriptorPool descPool,
272 VkDescriptorSetLayout descLayout)
273 {
274 const VkDescriptorSetAllocateInfo allocInfo =
275 {
276 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
277 DE_NULL,
278 descPool,
279 1u,
280 &descLayout,
281 };
282
283 return allocateDescriptorSet(vkd, device, &allocInfo);
284 }
285
bindImage(const DeviceInterface & vkd,VkDevice device,VkDescriptorSet descriptorSet,VkImageView imageView,VkSampler sampler)286 void bindImage (const DeviceInterface& vkd,
287 VkDevice device,
288 VkDescriptorSet descriptorSet,
289 VkImageView imageView,
290 VkSampler sampler)
291 {
292 const VkDescriptorImageInfo imageInfo =
293 {
294 sampler,
295 imageView,
296 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
297 };
298 const VkWriteDescriptorSet descriptorWrite =
299 {
300 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
301 DE_NULL,
302 descriptorSet,
303 0u, // dstBinding
304 0u, // dstArrayElement
305 1u, // descriptorCount
306 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
307 &imageInfo,
308 (const VkDescriptorBufferInfo*)DE_NULL,
309 (const VkBufferView*)DE_NULL,
310 };
311
312 vkd.updateDescriptorSets(device, 1u, &descriptorWrite, 0u, DE_NULL);
313 }
314
getMaxPlaneDivisor(const PlanarFormatDescription & formatDesc)315 UVec2 getMaxPlaneDivisor (const PlanarFormatDescription& formatDesc)
316 {
317 UVec2 maxDivisor (1u, 1u);
318
319 for (deUint32 ndx = 0; ndx < formatDesc.numPlanes; ++ndx)
320 {
321 maxDivisor.x() = de::max<deUint32>(maxDivisor.x(), formatDesc.planes[ndx].widthDivisor);
322 maxDivisor.y() = de::max<deUint32>(maxDivisor.y(), formatDesc.planes[ndx].heightDivisor);
323 }
324
325 return maxDivisor;
326 }
327
testImageQuery(Context & context,TestParameters params)328 tcu::TestStatus testImageQuery (Context& context, TestParameters params)
329 {
330 const bool isYCbCrImage = isYCbCrFormat(params.format);
331
332 if (isYCbCrImage)
333 checkImageSupport(context, params.format, params.flags);
334
335 const DeviceInterface& vkd = context.getDeviceInterface();
336 const VkDevice device = context.getDevice();
337
338 const VkSamplerYcbcrConversionCreateInfoKHR conversionInfo =
339 {
340 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR,
341 DE_NULL,
342 params.format,
343 VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR,
344 VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR,
345 {
346 VK_COMPONENT_SWIZZLE_IDENTITY,
347 VK_COMPONENT_SWIZZLE_IDENTITY,
348 VK_COMPONENT_SWIZZLE_IDENTITY,
349 VK_COMPONENT_SWIZZLE_IDENTITY,
350 },
351 VK_CHROMA_LOCATION_MIDPOINT_KHR,
352 VK_CHROMA_LOCATION_MIDPOINT_KHR,
353 VK_FILTER_NEAREST,
354 VK_FALSE, // forceExplicitReconstruction
355 };
356 const Unique<VkSamplerYcbcrConversionKHR> conversion (isYCbCrImage
357 ? createSamplerYcbcrConversionKHR(vkd, device, &conversionInfo)
358 : Move<VkSamplerYcbcrConversionKHR>());
359
360 const VkSamplerYcbcrConversionInfoKHR samplerConversionInfo =
361 {
362 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR,
363 DE_NULL,
364 *conversion,
365 };
366
367 const VkSamplerCreateInfo samplerInfo =
368 {
369 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
370 isYCbCrImage ? &samplerConversionInfo : DE_NULL,
371 0u,
372 VK_FILTER_NEAREST, // magFilter
373 VK_FILTER_NEAREST, // minFilter
374 VK_SAMPLER_MIPMAP_MODE_NEAREST, // mipmapMode
375 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
376 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
377 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
378 0.0f, // mipLodBias
379 VK_FALSE, // anisotropyEnable
380 1.0f, // maxAnisotropy
381 VK_FALSE, // compareEnable
382 VK_COMPARE_OP_ALWAYS, // compareOp
383 0.0f, // minLod
384 0.0f, // maxLod
385 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // borderColor
386 VK_FALSE, // unnormalizedCoords
387 };
388
389 const Unique<VkSampler> sampler (createSampler(vkd, device, &samplerInfo));
390 const Unique<VkDescriptorSetLayout> descLayout (createDescriptorSetLayout(vkd, device, *sampler));
391 const Unique<VkDescriptorPool> descPool (createDescriptorPool(vkd, device));
392 const Unique<VkDescriptorSet> descSet (createDescriptorSet(vkd, device, *descPool, *descLayout));
393
394 vector<TestImageSp> testImages;
395
396 if (params.query == QUERY_TYPE_IMAGE_SIZE_LOD)
397 {
398 const PlanarFormatDescription& formatDesc = getPlanarFormatDescription(params.format);
399 const UVec2 maxDivisor = getMaxPlaneDivisor(formatDesc);
400 vector<UVec2> testSizes;
401
402 testSizes.push_back(maxDivisor);
403 testSizes.push_back(maxDivisor * UVec2(2u, 1u));
404 testSizes.push_back(maxDivisor * UVec2(1u, 2u));
405 testSizes.push_back(maxDivisor * UVec2(63u, 79u));
406 testSizes.push_back(maxDivisor * UVec2(99u, 1u));
407 testSizes.push_back(maxDivisor * UVec2(421u, 1117u));
408
409 testImages.resize(testSizes.size());
410
411 for (size_t ndx = 0; ndx < testSizes.size(); ++ndx)
412 testImages[ndx] = TestImageSp(new TestImage(vkd, device, context.getDefaultAllocator(), params.format, testSizes[ndx], params.flags));
413 }
414 else
415 testImages.push_back(TestImageSp(new TestImage(vkd, device, context.getDefaultAllocator(), params.format, UVec2(16, 18), params.flags)));
416
417 {
418 UniquePtr<ShaderExecutor> executor (createExecutor(context, params.shaderType, getShaderSpec(params), *descLayout));
419 bool allOk = true;
420
421 for (size_t imageNdx = 0; imageNdx < testImages.size(); ++imageNdx)
422 {
423 const deUint32 lod = 0u;
424 UVec2 result (~0u, ~0u);
425 const void* inputs[] = { &lod };
426 void* outputs[] = { result.getPtr() };
427
428 bindImage(vkd, device, *descSet, testImages[imageNdx]->getImageView(), *sampler);
429
430 executor->execute(1, inputs, outputs, *descSet);
431
432 switch (params.query)
433 {
434 case QUERY_TYPE_IMAGE_SIZE_LOD:
435 {
436 const UVec2 reference = testImages[imageNdx]->getSize();
437
438 if (result != reference)
439 {
440 context.getTestContext().getLog()
441 << TestLog::Message << "ERROR: Image " << imageNdx
442 << ": got " << result
443 << ", expected " << reference
444 << TestLog::EndMessage;
445 allOk = false;
446 }
447 break;
448 }
449
450 case QUERY_TYPE_IMAGE_LEVELS:
451 {
452 if (result.x() != 1u)
453 {
454 context.getTestContext().getLog()
455 << TestLog::Message << "ERROR: Image " << imageNdx
456 << ": got " << result.x()
457 << ", expected " << 1
458 << TestLog::EndMessage;
459 allOk = false;
460 }
461 break;
462 }
463
464 default:
465 DE_FATAL("Invalid query type");
466 }
467 }
468
469 if (allOk)
470 return tcu::TestStatus::pass("Queries passed");
471 else
472 return tcu::TestStatus::fail("Got invalid results");
473 }
474 }
475
testImageQueryLod(Context & context,TestParameters params)476 tcu::TestStatus testImageQueryLod (Context& context, TestParameters params)
477 {
478 const bool isYCbCrImage = isYCbCrFormat(params.format);
479
480 if (isYCbCrImage)
481 checkImageSupport(context, params.format, params.flags);
482
483 const DeviceInterface& vkd = context.getDeviceInterface();
484 const VkDevice device = context.getDevice();
485
486 const VkSamplerYcbcrConversionCreateInfoKHR conversionInfo =
487 {
488 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR,
489 DE_NULL,
490 params.format,
491 VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR,
492 VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR,
493 {
494 VK_COMPONENT_SWIZZLE_IDENTITY,
495 VK_COMPONENT_SWIZZLE_IDENTITY,
496 VK_COMPONENT_SWIZZLE_IDENTITY,
497 VK_COMPONENT_SWIZZLE_IDENTITY,
498 },
499 VK_CHROMA_LOCATION_MIDPOINT_KHR,
500 VK_CHROMA_LOCATION_MIDPOINT_KHR,
501 VK_FILTER_NEAREST,
502 VK_FALSE, // forceExplicitReconstruction
503 };
504 const Unique<VkSamplerYcbcrConversionKHR> conversion (isYCbCrImage
505 ? createSamplerYcbcrConversionKHR(vkd, device, &conversionInfo)
506 : Move<VkSamplerYcbcrConversionKHR>());
507
508 const VkSamplerYcbcrConversionInfoKHR samplerConversionInfo =
509 {
510 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR,
511 DE_NULL,
512 *conversion,
513 };
514
515 const VkSamplerCreateInfo samplerInfo =
516 {
517 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
518 isYCbCrImage ? &samplerConversionInfo : DE_NULL,
519 0u,
520 VK_FILTER_NEAREST, // magFilter
521 VK_FILTER_NEAREST, // minFilter
522 VK_SAMPLER_MIPMAP_MODE_NEAREST, // mipmapMode
523 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
524 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
525 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
526 0.0f, // mipLodBias
527 VK_FALSE, // anisotropyEnable
528 1.0f, // maxAnisotropy
529 VK_FALSE, // compareEnable
530 VK_COMPARE_OP_ALWAYS, // compareOp
531 0.0f, // minLod
532 0.0f, // maxLod
533 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // borderColor
534 VK_FALSE, // unnormalizedCoords
535 };
536
537 const Unique<VkSampler> sampler (createSampler(vkd, device, &samplerInfo));
538 const Unique<VkDescriptorSetLayout> descLayout (createDescriptorSetLayout(vkd, device, *sampler));
539 const Unique<VkDescriptorPool> descPool (createDescriptorPool(vkd, device));
540 const Unique<VkDescriptorSet> descSet (createDescriptorSet(vkd, device, *descPool, *descLayout));
541
542 vector<TestImageSp> testImages;
543
544 DE_ASSERT(params.query == QUERY_TYPE_IMAGE_LOD);
545 DE_ASSERT(params.shaderType == glu::SHADERTYPE_FRAGMENT);
546
547 {
548 const PlanarFormatDescription& formatDesc = getPlanarFormatDescription(params.format);
549 const UVec2 maxDivisor = getMaxPlaneDivisor(formatDesc);
550 vector<UVec2> testSizes;
551
552 testSizes.push_back(maxDivisor);
553 testSizes.push_back(maxDivisor * UVec2(2u, 1u));
554 testSizes.push_back(maxDivisor * UVec2(1u, 2u));
555 testSizes.push_back(maxDivisor * UVec2(4u, 123u));
556 testSizes.push_back(maxDivisor * UVec2(312u, 13u));
557 testSizes.push_back(maxDivisor * UVec2(841u, 917u));
558
559 testImages.resize(testSizes.size());
560
561 for (size_t ndx = 0; ndx < testSizes.size(); ++ndx)
562 testImages[ndx] = TestImageSp(new TestImage(vkd, device, context.getDefaultAllocator(), params.format, testSizes[ndx], params.flags));
563 }
564
565 {
566 using namespace drawutil;
567
568 struct LocalUtil
569 {
570 static DrawState getDrawState (UVec2 renderSize)
571 {
572 DrawState state(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, renderSize.x(), renderSize.y());
573 state.colorFormat = VK_FORMAT_R32G32_SFLOAT;
574 return state;
575 }
576
577 static vector<Vec4> getVertices (void)
578 {
579 vector<Vec4> vertices;
580
581 vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
582 vertices.push_back(Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
583 vertices.push_back(Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
584
585 vertices.push_back(Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
586 vertices.push_back(Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
587 vertices.push_back(Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
588
589 return vertices;
590 }
591
592 static VulkanProgram getProgram (Context& ctx, VkDescriptorSetLayout descriptorLayout, VkDescriptorSet descriptorSet)
593 {
594 VulkanProgram prog;
595
596 prog.shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, ctx.getBinaryCollection().get("vert")));
597 prog.shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, ctx.getBinaryCollection().get("frag")));
598
599 prog.descriptorSet = descriptorSet;
600 prog.descriptorSetLayout = descriptorLayout;
601
602 return prog;
603 }
604 };
605
606 const UVec2 renderSize (128, 256);
607 const vector<Vec4> vertices (LocalUtil::getVertices());
608 const DrawState drawState (LocalUtil::getDrawState(renderSize));
609 const DrawCallData drawCallData(vertices);
610 const VulkanProgram program (LocalUtil::getProgram(context, *descLayout, *descSet));
611
612 bool allOk = true;
613
614 context.getTestContext().getLog()
615 << TestLog::Message << "Rendering " << renderSize << " quad" << TestLog::EndMessage;
616
617 for (size_t imageNdx = 0; imageNdx < testImages.size(); ++imageNdx)
618 {
619 context.getTestContext().getLog()
620 << TestLog::Message << "Testing image size " << testImages[imageNdx]->getSize() << TestLog::EndMessage;
621
622 bindImage(vkd, device, *descSet, testImages[imageNdx]->getImageView(), *sampler);
623
624 VulkanDrawContext renderer (context, drawState, drawCallData, program);
625 renderer.draw();
626
627 {
628 // Only du/dx and dv/dy are non-zero
629 const Vec2 dtdp = testImages[imageNdx]->getSize().cast<float>() / renderSize.cast<float>();
630 const tcu::LodPrecision lodPrec (16, 4); // Pretty lax since we are not verifying LOD precision
631 const Vec2 lodBounds (tcu::computeLodBoundsFromDerivates(dtdp.x(), 0.0f, 0.0f, dtdp.y(), lodPrec));
632 tcu::ConstPixelBufferAccess resultImg (renderer.getColorPixels());
633 const int maxErrors = 5;
634 int numErrors = 0;
635
636 for (int y = 0; y < resultImg.getHeight(); ++y)
637 for (int x = 0; x < resultImg.getWidth(); ++x)
638 {
639 const Vec2 result = resultImg.getPixel(x, y).swizzle(0,1);
640 const bool levelOk = result.x() == 0.0f;
641 const bool lodOk = de::inRange(result.y(), lodBounds.x(), lodBounds.y());
642
643 if (!levelOk || !lodOk)
644 {
645 if (numErrors < maxErrors)
646 {
647 context.getTestContext().getLog()
648 << TestLog::Message << "ERROR: At (" << x << ", " << y << ")"
649 << ": got " << result
650 << ", expected (0, [" << lodBounds.x() << ", " << lodBounds.y() << "])"
651 << TestLog::EndMessage;
652 }
653 else if (numErrors == maxErrors)
654 context.getTestContext().getLog() << TestLog::Message << "..." << TestLog::EndMessage;
655
656 numErrors += 1;
657 }
658 }
659
660 allOk = allOk && (numErrors == 0);
661 }
662 }
663
664 if (allOk)
665 return tcu::TestStatus::pass("Queries passed");
666 else
667 return tcu::TestStatus::fail("Got invalid results");
668 }
669 }
670
initImageQueryPrograms(SourceCollections & dst,TestParameters params)671 void initImageQueryPrograms (SourceCollections& dst, TestParameters params)
672 {
673 const ShaderSpec spec = getShaderSpec(params);
674
675 generateSources(params.shaderType, spec, dst);
676 }
677
initImageQueryLodPrograms(SourceCollections & dst,TestParameters)678 void initImageQueryLodPrograms (SourceCollections& dst, TestParameters)
679 {
680 dst.glslSources.add("vert")
681 << glu::VertexSource("#version 450\n"
682 "layout(location = 0) in highp vec4 a_position;\n"
683 "layout(location = 0) out highp vec2 v_texCoord;\n"
684 "\n"
685 "void main (void)\n"
686 "{\n"
687 " gl_Position = a_position;\n"
688 " v_texCoord = a_position.xy * 0.5 - 0.5;\n"
689 "}\n");
690 dst.glslSources.add("frag")
691 << glu::FragmentSource("#version 450\n"
692 "layout(binding = 0, set = 0) uniform highp sampler2D u_image;\n"
693 "layout(location = 0) in highp vec2 v_texCoord;\n"
694 "layout(location = 0) out highp vec2 o_lod;\n"
695 "\n"
696 "void main (void)\n"
697 "{\n"
698 " o_lod = textureQueryLod(u_image, v_texCoord);\n"
699 "}\n");
700 }
701
addImageQueryCase(tcu::TestCaseGroup * group,const TestParameters & params)702 void addImageQueryCase (tcu::TestCaseGroup* group, const TestParameters& params)
703 {
704 std::string name = de::toLower(de::toString(params.format).substr(10));
705 const bool isLod = params.query == QUERY_TYPE_IMAGE_LOD;
706
707 if ((params.flags & VK_IMAGE_CREATE_DISJOINT_BIT_KHR) != 0)
708 name += "_disjoint";
709
710 addFunctionCaseWithPrograms(group,
711 name,
712 "",
713 isLod ? initImageQueryLodPrograms : initImageQueryPrograms,
714 isLod ? testImageQueryLod : testImageQuery,
715 params);
716 }
717
718 struct QueryGroupParams
719 {
720 QueryType query;
721 glu::ShaderType shaderType;
722
QueryGroupParamsvkt::ycbcr::__anon37eb4e340111::QueryGroupParams723 QueryGroupParams (QueryType query_, glu::ShaderType shaderType_)
724 : query (query_)
725 , shaderType(shaderType_)
726 {}
727
QueryGroupParamsvkt::ycbcr::__anon37eb4e340111::QueryGroupParams728 QueryGroupParams (void)
729 : query (QUERY_TYPE_LAST)
730 , shaderType(glu::SHADERTYPE_LAST)
731 {}
732 };
733
populateQueryInShaderGroup(tcu::TestCaseGroup * group,QueryGroupParams params)734 void populateQueryInShaderGroup (tcu::TestCaseGroup* group, QueryGroupParams params)
735 {
736 // "Reference" formats for testing
737 addImageQueryCase(group, TestParameters(params.query, VK_FORMAT_R8G8B8A8_UNORM, 0u, params.shaderType));
738
739 for (int formatNdx = VK_YCBCR_FORMAT_FIRST; formatNdx < VK_YCBCR_FORMAT_LAST; formatNdx++)
740 {
741 const VkFormat format = (VkFormat)formatNdx;
742
743 addImageQueryCase(group, TestParameters(params.query, format, 0u, params.shaderType));
744
745 if (getPlaneCount(format) > 1)
746 addImageQueryCase(group, TestParameters(params.query, format, (VkImageCreateFlags)VK_IMAGE_CREATE_DISJOINT_BIT_KHR, params.shaderType));
747 }
748 }
749
populateQueryGroup(tcu::TestCaseGroup * group,QueryType query)750 void populateQueryGroup (tcu::TestCaseGroup* group, QueryType query)
751 {
752 for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; ++shaderTypeNdx)
753 {
754 const glu::ShaderType shaderType = (glu::ShaderType)shaderTypeNdx;
755
756 if (query == QUERY_TYPE_IMAGE_LOD && shaderType != glu::SHADERTYPE_FRAGMENT)
757 continue;
758
759 addTestGroup(group, glu::getShaderTypeName(shaderType), "", populateQueryInShaderGroup, QueryGroupParams(query, shaderType));
760 }
761 }
762
populateImageQueryGroup(tcu::TestCaseGroup * group)763 void populateImageQueryGroup (tcu::TestCaseGroup* group)
764 {
765 addTestGroup(group, "size_lod", "OpImageQuerySizeLod", populateQueryGroup, QUERY_TYPE_IMAGE_SIZE_LOD);
766 addTestGroup(group, "lod", "OpImageQueryLod", populateQueryGroup, QUERY_TYPE_IMAGE_LOD);
767 addTestGroup(group, "levels", "OpImageQueryLevels", populateQueryGroup, QUERY_TYPE_IMAGE_LEVELS);
768 }
769
770 } // namespace
771
createImageQueryTests(tcu::TestContext & testCtx)772 tcu::TestCaseGroup* createImageQueryTests (tcu::TestContext& testCtx)
773 {
774 return createTestGroup(testCtx, "query", "Image Query Tests", populateImageQueryGroup);
775 }
776
777 } // ycbcr
778 } // vkt
779