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 Texture color conversion tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktYCbCrConversionTests.hpp"
25
26 #include "vktShaderExecutor.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29 #include "vktYCbCrUtil.hpp"
30
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkQueryUtil.hpp"
37
38 #include "tcuInterval.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuTexture.hpp"
41 #include "tcuTextureUtil.hpp"
42 #include "tcuVector.hpp"
43 #include "tcuVectorUtil.hpp"
44 #include "tcuFloatFormat.hpp"
45 #include "tcuFloat.hpp"
46
47 #include "deRandom.hpp"
48 #include "deSTLUtil.hpp"
49 #include "deSharedPtr.hpp"
50
51 #include "deMath.h"
52 #include "deFloat16.h"
53
54 #include <vector>
55 #include <iomanip>
56
57 // \todo When defined color conversion extension is not used and conversion is performed in the shader
58 // #define FAKE_COLOR_CONVERSION
59
60 using tcu::Vec2;
61 using tcu::Vec4;
62
63 using tcu::UVec2;
64 using tcu::UVec4;
65
66 using tcu::IVec2;
67 using tcu::IVec3;
68 using tcu::IVec4;
69
70 using tcu::TestLog;
71 using tcu::FloatFormat;
72
73 using std::vector;
74 using std::string;
75
76 using namespace vkt::shaderexecutor;
77
78 namespace vkt
79 {
80 namespace ycbcr
81 {
82 namespace
83 {
84
85 template<typename T>
makeSharedPtr(vk::Move<T> move)86 inline de::SharedPtr<vk::Unique<T> > makeSharedPtr(vk::Move<T> move)
87 {
88 return de::SharedPtr<vk::Unique<T> >(new vk::Unique<T>(move));
89 }
90
createShaderSpec(deUint32 samplerBinding,const std::vector<vk::VkSamplerYcbcrModelConversion> & colorModels)91 ShaderSpec createShaderSpec (deUint32 samplerBinding, const std::vector<vk::VkSamplerYcbcrModelConversion>& colorModels)
92 {
93 ShaderSpec spec;
94
95 spec.inputs.push_back(Symbol("uv", glu::VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_HIGHP)));
96 // shader with single sampler
97 if (colorModels.size()==1)
98 {
99 spec.globalDeclarations = "layout(set=" + de::toString((int)EXTRA_RESOURCES_DESCRIPTOR_SET_INDEX) + ", binding=" + de::toString(samplerBinding) + ") uniform highp sampler2D u_sampler;";
100
101 spec.outputs.push_back(Symbol("o_color", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
102
103 spec.source = "o_color = texture(u_sampler, uv);\n";
104 }
105 else // shader with array of samplers
106 {
107 spec.globalDeclarations = "layout(set=" + de::toString((int)EXTRA_RESOURCES_DESCRIPTOR_SET_INDEX) + ", binding=" + de::toString(samplerBinding) + ") uniform highp sampler2D u_sampler[" + de::toString(colorModels.size()) + "];";
108
109 for (int i = 0; i < (int)colorModels.size(); i++)
110 {
111 spec.outputs.push_back(Symbol(string("o_color") + de::toString(i), glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
112
113 spec.source += string("o_color") + de::toString(i) + " = texture(u_sampler[" + de::toString(i) + "], uv);\n";
114 }
115 }
116 return spec;
117 }
118
genTexCoords(std::vector<Vec2> & coords,const UVec2 & srcSize,const UVec2 & dstSize)119 void genTexCoords (std::vector<Vec2>& coords,
120 const UVec2& srcSize,
121 const UVec2& dstSize)
122 {
123 for (deUint32 y = 0; y < dstSize.y(); y++)
124 for (deUint32 x = 0; x < dstSize.x(); x++)
125 {
126 const float fx = (float)x;
127 const float fy = (float)y;
128
129 const float fw = (float)srcSize.x();
130 const float fh = (float)srcSize.y();
131
132 const float s = 1.5f * ((fx * 1.5f * fw + fx) / (1.5f * fw * 1.5f * fw)) - 0.25f;
133 const float t = 1.5f * ((fy * 1.5f * fh + fy) / (1.5f * fh * 1.5f * fh)) - 0.25f;
134
135 coords.push_back(Vec2(s, t));
136 }
137 }
138
genOneToOneTexCoords(std::vector<Vec2> & coords,const UVec2 & size)139 void genOneToOneTexCoords (std::vector<Vec2>& coords,
140 const UVec2& size)
141 {
142 for (deUint32 y = 0; y < size.y(); y++)
143 for (deUint32 x = 0; x < size.x(); x++)
144 {
145 const float s = ((float)x + 0.5f) / (float)size.x();
146 const float t = ((float)y + 0.5f) / (float)size.y();
147
148 coords.push_back(Vec2(s, t));
149 }
150 }
151
152 struct TestConfig
153 {
TestConfigvkt::ycbcr::__anon548eae410111::TestConfig154 TestConfig (glu::ShaderType shaderType_,
155 vk::VkFormat format_,
156 vk::VkImageTiling imageTiling_,
157 vk::VkFilter textureFilter_,
158 vk::VkSamplerAddressMode addressModeU_,
159 vk::VkSamplerAddressMode addressModeV_,
160
161 vk::VkFilter chromaFilter_,
162 vk::VkChromaLocation xChromaOffset_,
163 vk::VkChromaLocation yChromaOffset_,
164 bool explicitReconstruction_,
165 bool disjoint_,
166
167 vk::VkSamplerYcbcrRange colorRange_,
168 vk::VkSamplerYcbcrModelConversion colorModel_,
169 vk::VkComponentMapping componentMapping_,
170 const UVec2 srcSize_,
171 const UVec2 dstSize_,
172 deUint32 samplerBinding_)
173 : shaderType (shaderType_)
174 , format (format_)
175 , imageTiling (imageTiling_)
176 , textureFilter (textureFilter_)
177 , addressModeU (addressModeU_)
178 , addressModeV (addressModeV_)
179
180 , chromaFilter (chromaFilter_)
181 , xChromaOffset (xChromaOffset_)
182 , yChromaOffset (yChromaOffset_)
183 , explicitReconstruction (explicitReconstruction_)
184 , disjoint (disjoint_)
185
186 , colorRange (colorRange_)
187 , colorModel (colorModel_)
188 , componentMapping (componentMapping_)
189 , srcSize (srcSize_)
190 , dstSize (dstSize_)
191 , samplerBinding (samplerBinding_)
192 {
193 }
194
195 glu::ShaderType shaderType;
196 vk::VkFormat format;
197 vk::VkImageTiling imageTiling;
198 vk::VkFilter textureFilter;
199 vk::VkSamplerAddressMode addressModeU;
200 vk::VkSamplerAddressMode addressModeV;
201
202 vk::VkFilter chromaFilter;
203 vk::VkChromaLocation xChromaOffset;
204 vk::VkChromaLocation yChromaOffset;
205 bool explicitReconstruction;
206 bool disjoint;
207
208 vk::VkSamplerYcbcrRange colorRange;
209 vk::VkSamplerYcbcrModelConversion colorModel;
210 vk::VkComponentMapping componentMapping;
211 const UVec2 srcSize;
212 const UVec2 dstSize;
213 deUint32 samplerBinding;
214 };
215
createDescriptorSetLayout(const vk::DeviceInterface & vkd,vk::VkDevice device,const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler>>> & samplers,deUint32 samplerBinding)216 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vkd,
217 vk::VkDevice device,
218 const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler> > >& samplers,
219 deUint32 samplerBinding)
220 {
221 std::vector<vk::VkSampler> sampler;
222 for (size_t i = 0; i < samplers.size(); i++)
223 sampler.push_back(samplers[i]->get());
224 const vk::VkDescriptorSetLayoutBinding layoutBindings[] =
225 {
226 {
227 samplerBinding,
228 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
229 (deUint32)sampler.size(),
230 vk::VK_SHADER_STAGE_ALL,
231 sampler.data()
232 }
233 };
234 const vk::VkDescriptorSetLayoutCreateInfo layoutCreateInfo =
235 {
236 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
237 DE_NULL,
238
239 0u,
240 DE_LENGTH_OF_ARRAY(layoutBindings),
241 layoutBindings
242 };
243
244 return vk::createDescriptorSetLayout(vkd, device, &layoutCreateInfo);
245 }
246
createDescriptorPool(const vk::DeviceInterface & vkd,vk::VkDevice device,const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler>>> & samplers,const deUint32 combinedSamplerDescriptorCount)247 vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vkd,
248 vk::VkDevice device,
249 const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler> > >& samplers,
250 const deUint32 combinedSamplerDescriptorCount)
251 {
252 const vk::VkDescriptorPoolSize poolSizes[] =
253 {
254 { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, (deUint32)samplers.size() * combinedSamplerDescriptorCount }
255 };
256 const vk::VkDescriptorPoolCreateInfo descriptorPoolCreateInfo =
257 {
258 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
259 DE_NULL,
260 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
261
262 1u,
263 DE_LENGTH_OF_ARRAY(poolSizes),
264 poolSizes
265 };
266
267 return createDescriptorPool(vkd, device, &descriptorPoolCreateInfo);
268 }
269
createDescriptorSet(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDescriptorPool descriptorPool,vk::VkDescriptorSetLayout layout,const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler>>> & samplers,const std::vector<de::SharedPtr<vk::Unique<vk::VkImageView>>> & imageViews,deUint32 samplerBinding)270 vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vkd,
271 vk::VkDevice device,
272 vk::VkDescriptorPool descriptorPool,
273 vk::VkDescriptorSetLayout layout,
274 const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler> > >& samplers,
275 const std::vector<de::SharedPtr<vk::Unique<vk::VkImageView> > >& imageViews,
276 deUint32 samplerBinding)
277 {
278 const vk::VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
279 {
280 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
281 DE_NULL,
282
283 descriptorPool,
284 1u,
285 &layout
286 };
287 vk::Move<vk::VkDescriptorSet> descriptorSet (vk::allocateDescriptorSet(vkd, device, &descriptorSetAllocateInfo));
288 std::vector<vk::VkDescriptorImageInfo> imageInfo;
289 for (size_t i = 0; i < samplers.size(); i++)
290 {
291 const vk::VkDescriptorImageInfo ii =
292 {
293 samplers[i]->get(),
294 imageViews[i]->get(),
295 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
296 };
297 imageInfo.push_back(ii);
298 }
299
300 {
301 const vk::VkWriteDescriptorSet writes[] =
302 {
303 {
304 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
305 DE_NULL,
306
307 *descriptorSet,
308 samplerBinding,
309 0u,
310 (deUint32)imageInfo.size(),
311 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
312 imageInfo.data(),
313 DE_NULL,
314 DE_NULL
315 }
316 };
317
318 vkd.updateDescriptorSets(device, DE_LENGTH_OF_ARRAY(writes), writes, 0u, DE_NULL);
319 }
320
321 return descriptorSet;
322 }
323
createSampler(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFilter textureFilter,vk::VkSamplerAddressMode addressModeU,vk::VkSamplerAddressMode addressModeV,vk::VkSamplerYcbcrConversion conversion)324 vk::Move<vk::VkSampler> createSampler (const vk::DeviceInterface& vkd,
325 vk::VkDevice device,
326 vk::VkFilter textureFilter,
327 vk::VkSamplerAddressMode addressModeU,
328 vk::VkSamplerAddressMode addressModeV,
329 vk::VkSamplerYcbcrConversion conversion)
330 {
331 #if !defined(FAKE_COLOR_CONVERSION)
332 const vk::VkSamplerYcbcrConversionInfo samplerConversionInfo =
333 {
334 vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
335 DE_NULL,
336 conversion
337 };
338 #else
339 DE_UNREF(conversion);
340 #endif
341 const vk::VkSamplerCreateInfo createInfo =
342 {
343 vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
344 #if !defined(FAKE_COLOR_CONVERSION)
345 &samplerConversionInfo,
346 #else
347 DE_NULL,
348 #endif
349
350 0u,
351 textureFilter,
352 textureFilter,
353 vk::VK_SAMPLER_MIPMAP_MODE_NEAREST,
354 addressModeU,
355 addressModeV,
356 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
357 0.0f,
358 VK_FALSE,
359 1.0f,
360 VK_FALSE,
361 vk::VK_COMPARE_OP_ALWAYS,
362 0.0f,
363 0.0f,
364 vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
365 VK_FALSE,
366 };
367
368 return createSampler(vkd, device, &createInfo);
369 }
370
createImage(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFormat format,const UVec2 & size,bool disjoint,vk::VkImageTiling tiling)371 vk::Move<vk::VkImage> createImage (const vk::DeviceInterface& vkd,
372 vk::VkDevice device,
373 vk::VkFormat format,
374 const UVec2& size,
375 bool disjoint,
376 vk::VkImageTiling tiling)
377 {
378 const vk::VkImageCreateInfo createInfo =
379 {
380 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
381 DE_NULL,
382 disjoint ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlags)0u,
383
384 vk::VK_IMAGE_TYPE_2D,
385 format,
386 vk::makeExtent3D(size.x(), size.y(), 1u),
387 1u,
388 1u,
389 vk::VK_SAMPLE_COUNT_1_BIT,
390 tiling,
391 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | vk::VK_IMAGE_USAGE_SAMPLED_BIT,
392 vk::VK_SHARING_MODE_EXCLUSIVE,
393 0u,
394 (const deUint32*)DE_NULL,
395 vk::VK_IMAGE_LAYOUT_PREINITIALIZED,
396 };
397
398 return vk::createImage(vkd, device, &createInfo);
399 }
400
createImageView(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImage image,vk::VkFormat format,vk::VkSamplerYcbcrConversion conversion)401 vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface& vkd,
402 vk::VkDevice device,
403 vk::VkImage image,
404 vk::VkFormat format,
405 vk::VkSamplerYcbcrConversion conversion)
406 {
407 // Both mappings should be equivalent: alternate between the two for different formats.
408 const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
409 const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
410 const vk::VkComponentMapping& mapping = ((static_cast<int>(format) % 2 == 0) ? mappingA : mappingB);
411
412 #if !defined(FAKE_COLOR_CONVERSION)
413 const vk::VkSamplerYcbcrConversionInfo conversionInfo =
414 {
415 vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
416 DE_NULL,
417 conversion
418 };
419 #else
420 DE_UNREF(conversion);
421 #endif
422 const vk::VkImageViewCreateInfo viewInfo =
423 {
424 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
425 #if defined(FAKE_COLOR_CONVERSION)
426 DE_NULL,
427 #else
428 &conversionInfo,
429 #endif
430 (vk::VkImageViewCreateFlags)0,
431
432 image,
433 vk::VK_IMAGE_VIEW_TYPE_2D,
434 format,
435 mapping,
436 { vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },
437 };
438
439 return vk::createImageView(vkd, device, &viewInfo);
440 }
441
createConversion(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFormat format,vk::VkSamplerYcbcrModelConversion colorModel,vk::VkSamplerYcbcrRange colorRange,vk::VkChromaLocation xChromaOffset,vk::VkChromaLocation yChromaOffset,vk::VkFilter chromaFilter,const vk::VkComponentMapping & componentMapping,bool explicitReconstruction)442 vk::Move<vk::VkSamplerYcbcrConversion> createConversion (const vk::DeviceInterface& vkd,
443 vk::VkDevice device,
444 vk::VkFormat format,
445 vk::VkSamplerYcbcrModelConversion colorModel,
446 vk::VkSamplerYcbcrRange colorRange,
447 vk::VkChromaLocation xChromaOffset,
448 vk::VkChromaLocation yChromaOffset,
449 vk::VkFilter chromaFilter,
450 const vk::VkComponentMapping& componentMapping,
451 bool explicitReconstruction)
452 {
453 const vk::VkSamplerYcbcrConversionCreateInfo conversionInfo =
454 {
455 vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
456 DE_NULL,
457
458 format,
459 colorModel,
460 colorRange,
461 componentMapping,
462 xChromaOffset,
463 yChromaOffset,
464 chromaFilter,
465 explicitReconstruction ? VK_TRUE : VK_FALSE
466 };
467
468 return vk::createSamplerYcbcrConversion(vkd, device, &conversionInfo);
469 }
470
evalShader(Context & context,glu::ShaderType shaderType,const MultiPlaneImageData & imageData,const UVec2 & size,vk::VkFormat format,vk::VkImageTiling imageTiling,bool disjoint,vk::VkFilter textureFilter,vk::VkSamplerAddressMode addressModeU,vk::VkSamplerAddressMode addressModeV,const std::vector<vk::VkSamplerYcbcrModelConversion> & colorModels,vk::VkSamplerYcbcrRange colorRange,vk::VkChromaLocation xChromaOffset,vk::VkChromaLocation yChromaOffset,vk::VkFilter chromaFilter,const vk::VkComponentMapping & componentMapping,bool explicitReconstruction,const vector<Vec2> & sts,deUint32 samplerBinding,vector<vector<Vec4>> & results)471 void evalShader (Context& context,
472 glu::ShaderType shaderType,
473 const MultiPlaneImageData& imageData,
474 const UVec2& size,
475 vk::VkFormat format,
476 vk::VkImageTiling imageTiling,
477 bool disjoint,
478 vk::VkFilter textureFilter,
479 vk::VkSamplerAddressMode addressModeU,
480 vk::VkSamplerAddressMode addressModeV,
481 const std::vector<vk::VkSamplerYcbcrModelConversion>& colorModels,
482 vk::VkSamplerYcbcrRange colorRange,
483 vk::VkChromaLocation xChromaOffset,
484 vk::VkChromaLocation yChromaOffset,
485 vk::VkFilter chromaFilter,
486 const vk::VkComponentMapping& componentMapping,
487 bool explicitReconstruction,
488 const vector<Vec2>& sts,
489 deUint32 samplerBinding,
490 vector<vector<Vec4> >& results)
491 {
492 const vk::InstanceInterface& vk (context.getInstanceInterface());
493 const vk::DeviceInterface& vkd (context.getDeviceInterface());
494 const vk::VkDevice device (context.getDevice());
495 std::vector<de::SharedPtr<vk::Unique<vk::VkSamplerYcbcrConversion> > > conversions;
496 std::vector<de::SharedPtr<vk::Unique<vk::VkSampler> > > samplers;
497 #if !defined(FAKE_COLOR_CONVERSION)
498 for (int i = 0; i < (int)colorModels.size(); i++)
499 {
500 conversions.push_back(makeSharedPtr(createConversion(vkd, device, format, colorModels[i], colorRange, xChromaOffset, yChromaOffset, chromaFilter, componentMapping, explicitReconstruction)));
501 samplers.push_back(makeSharedPtr(createSampler(vkd, device, textureFilter, addressModeU, addressModeV, conversions[i]->get())));
502 }
503 #else
504 DE_UNREF(colorRange);
505 DE_UNREF(xChromaOffset);
506 DE_UNREF(yChromaOffset);
507 DE_UNREF(chromaFilter);
508 DE_UNREF(explicitReconstruction);
509 DE_UNREF(componentMapping);
510 samplers.push_back(makeSharedPtr(createSampler(vkd, device, textureFilter, addressModeU, addressModeV, (vk::VkSamplerYcbcrConversion)0u)));
511 #endif
512 const vk::Unique<vk::VkImage> image (createImage(vkd, device, format, size, disjoint, imageTiling));
513 const vk::MemoryRequirement memoryRequirement (imageTiling == vk::VK_IMAGE_TILING_OPTIMAL
514 ? vk::MemoryRequirement::Any
515 : vk::MemoryRequirement::HostVisible);
516 const vk::VkImageCreateFlags createFlags (disjoint ? vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlagBits)0u);
517 const vector<AllocationSp> imageMemory (allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *image, format, createFlags, memoryRequirement));
518 std::vector<de::SharedPtr<vk::Unique<vk::VkImageView > > > imageViews;
519 #if defined(FAKE_COLOR_CONVERSION)
520 imageViews.push_back(makeSharedPtr(createImageView(vkd, device, *image, format, (vk::VkSamplerYcbcrConversion)0)));
521 #else
522 for (int i = 0; i < (int)colorModels.size(); i++)
523 {
524 imageViews.push_back(makeSharedPtr(createImageView(vkd, device, *image, format, conversions[i]->get())));
525 }
526 #endif
527
528 deUint32 combinedSamplerDescriptorCount = 1;
529 {
530 const vk::VkPhysicalDeviceImageFormatInfo2 imageFormatInfo =
531 {
532 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, //VkStructureType sType;
533 DE_NULL, //const void* pNext;
534 format, //VkFormat format;
535 vk::VK_IMAGE_TYPE_2D, //VkImageType type;
536 imageTiling, //VkImageTiling tiling;
537 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT |
538 vk::VK_IMAGE_USAGE_SAMPLED_BIT, //VkImageUsageFlags usage;
539 disjoint ?
540 (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_DISJOINT_BIT :
541 (vk::VkImageCreateFlags)0u //VkImageCreateFlags flags;
542 };
543
544 vk::VkSamplerYcbcrConversionImageFormatProperties samplerYcbcrConversionImage = {};
545 samplerYcbcrConversionImage.sType = vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES;
546 samplerYcbcrConversionImage.pNext = DE_NULL;
547
548 vk::VkImageFormatProperties2 imageFormatProperties = {};
549 imageFormatProperties.sType = vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
550 imageFormatProperties.pNext = &samplerYcbcrConversionImage;
551
552 VK_CHECK(vk.getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &imageFormatInfo, &imageFormatProperties));
553 combinedSamplerDescriptorCount = samplerYcbcrConversionImage.combinedImageSamplerDescriptorCount;
554 }
555
556
557 const vk::Unique<vk::VkDescriptorSetLayout> layout (createDescriptorSetLayout(vkd, device, samplers, samplerBinding));
558 const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool(vkd, device, samplers, combinedSamplerDescriptorCount));
559 const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(vkd, device, *descriptorPool, *layout, samplers, imageViews, samplerBinding));
560
561 const ShaderSpec spec (createShaderSpec(samplerBinding, colorModels));
562 const de::UniquePtr<ShaderExecutor> executor (createExecutor(context, shaderType, spec, *layout));
563
564 if (imageTiling == vk::VK_IMAGE_TILING_OPTIMAL)
565 uploadImage(vkd, device, context.getUniversalQueueFamilyIndex(), context.getDefaultAllocator(), *image, imageData, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
566 else
567 fillImageMemory(vkd, device, context.getUniversalQueueFamilyIndex(), *image, imageMemory, imageData, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
568
569 for(int i=0; i<(int)results.size(); i++)
570 results[i].resize(sts.size());
571
572 {
573 const void* const inputs[] =
574 {
575 &sts[0]
576 };
577 vector<void*> outputs;
578 for (int i = 0; i < (int)results.size(); i++)
579 outputs.push_back((void*)results[i].data());
580
581 executor->execute((int)sts.size(), inputs, outputs.data(), *descriptorSet);
582 }
583 }
584
logTestCaseInfo(TestLog & log,const TestConfig & config)585 void logTestCaseInfo (TestLog& log, const TestConfig& config)
586 {
587 log << TestLog::Message << "ShaderType: " << config.shaderType << TestLog::EndMessage;
588 log << TestLog::Message << "Format: " << config.format << TestLog::EndMessage;
589 log << TestLog::Message << "ImageTiling: " << config.imageTiling << TestLog::EndMessage;
590 log << TestLog::Message << "TextureFilter: " << config.textureFilter << TestLog::EndMessage;
591 log << TestLog::Message << "AddressModeU: " << config.addressModeU << TestLog::EndMessage;
592 log << TestLog::Message << "AddressModeV: " << config.addressModeV << TestLog::EndMessage;
593 log << TestLog::Message << "ChromaFilter: " << config.chromaFilter << TestLog::EndMessage;
594 log << TestLog::Message << "XChromaOffset: " << config.xChromaOffset << TestLog::EndMessage;
595 log << TestLog::Message << "YChromaOffset: " << config.yChromaOffset << TestLog::EndMessage;
596 log << TestLog::Message << "ExplicitReconstruction: " << (config.explicitReconstruction ? "true" : "false") << TestLog::EndMessage;
597 log << TestLog::Message << "Disjoint: " << (config.disjoint ? "true" : "false") << TestLog::EndMessage;
598 log << TestLog::Message << "ColorRange: " << config.colorRange << TestLog::EndMessage;
599 if( config.colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST )
600 log << TestLog::Message << "ColorModel: " << config.colorModel << TestLog::EndMessage;
601 else
602 log << TestLog::Message << "ColorModel: array of samplers" << TestLog::EndMessage;
603 log << TestLog::Message << "ComponentMapping: " << config.componentMapping << TestLog::EndMessage;
604 }
605
checkSupport(Context & context,const TestConfig config)606 void checkSupport (Context& context, const TestConfig config)
607 {
608 #if !defined(FAKE_COLOR_CONVERSION)
609 if (!context.isDeviceFunctionalitySupported("VK_KHR_sampler_ycbcr_conversion"))
610 TCU_THROW(NotSupportedError, "Extension VK_KHR_sampler_ycbcr_conversion not supported");
611
612 try
613 {
614 const vk::VkFormatProperties properties (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), config.format));
615 const vk::VkFormatFeatureFlags features (config.imageTiling == vk::VK_IMAGE_TILING_OPTIMAL
616 ? properties.optimalTilingFeatures
617 : properties.linearTilingFeatures);
618
619 if ((features & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) == 0)
620 TCU_THROW(NotSupportedError, "Format doesn't support YCbCr conversions");
621
622 if ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) == 0)
623 TCU_THROW(NotSupportedError, "Format doesn't support sampling");
624
625 if (config.textureFilter == vk::VK_FILTER_LINEAR && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) == 0))
626 TCU_THROW(NotSupportedError, "Format doesn't support linear texture filtering");
627
628 if (config.chromaFilter == vk::VK_FILTER_LINEAR && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT) == 0))
629 TCU_THROW(NotSupportedError, "Format doesn't support YCbCr linear chroma reconstruction");
630
631 if (config.chromaFilter != config.textureFilter && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT) == 0))
632 TCU_THROW(NotSupportedError, "Format doesn't support different chroma and texture filters");
633
634 if (config.explicitReconstruction && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT) == 0))
635 TCU_THROW(NotSupportedError, "Format doesn't support explicit chroma reconstruction");
636
637 if (config.disjoint && ((features & vk::VK_FORMAT_FEATURE_DISJOINT_BIT) == 0))
638 TCU_THROW(NotSupportedError, "Format doesn't disjoint planes");
639
640 if (isXChromaSubsampled(config.format) && (config.xChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN) && ((features & vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT) == 0))
641 TCU_THROW(NotSupportedError, "Format doesn't support cosited chroma samples");
642
643 if (isXChromaSubsampled(config.format) && (config.xChromaOffset == vk::VK_CHROMA_LOCATION_MIDPOINT) && ((features & vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT) == 0))
644 TCU_THROW(NotSupportedError, "Format doesn't support midpoint chroma samples");
645
646 if (isYChromaSubsampled(config.format) && (config.yChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN) && ((features & vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT) == 0))
647 TCU_THROW(NotSupportedError, "Format doesn't support cosited chroma samples");
648
649 if (isYChromaSubsampled(config.format) && (config.yChromaOffset == vk::VK_CHROMA_LOCATION_MIDPOINT) && ((features & vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT) == 0))
650 TCU_THROW(NotSupportedError, "Format doesn't support midpoint chroma samples");
651 }
652 catch (const vk::Error& err)
653 {
654 if (err.getError() == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
655 TCU_THROW(NotSupportedError, "Format not supported");
656
657 throw;
658 }
659 #endif
660 }
661
textureConversionTest(Context & context,const TestConfig config)662 tcu::TestStatus textureConversionTest (Context& context, const TestConfig config)
663 {
664 const std::vector<FloatFormat> filteringPrecision (getPrecision(config.format));
665 const std::vector<FloatFormat> conversionPrecision (getPrecision(config.format));
666 const deUint32 subTexelPrecisionBits (vk::getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits.subTexelPrecisionBits);
667 const tcu::UVec4 bitDepth (getYCbCrBitDepth(config.format));
668 TestLog& log (context.getTestContext().getLog());
669 bool explicitReconstruction = config.explicitReconstruction;
670 const UVec2 srcSize = config.srcSize;
671 const UVec2 dstSize = config.dstSize;
672 bool isOk = true;
673
674 logTestCaseInfo(log, config);
675
676 #if !defined(FAKE_COLOR_CONVERSION)
677 try
678 {
679 const vk::VkFormatProperties properties (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), config.format));
680 const vk::VkFormatFeatureFlags features (config.imageTiling == vk::VK_IMAGE_TILING_OPTIMAL
681 ? properties.optimalTilingFeatures
682 : properties.linearTilingFeatures);
683
684 if ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT) != 0)
685 explicitReconstruction = true;
686
687 log << TestLog::Message << "FormatFeatures: " << vk::getFormatFeatureFlagsStr(features) << TestLog::EndMessage;
688 }
689 catch (const vk::Error& err)
690 {
691 if (err.getError() == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
692 TCU_THROW(NotSupportedError, "Format not supported");
693
694 throw;
695 }
696 #endif
697
698 {
699 const vk::PlanarFormatDescription planeInfo (vk::getPlanarFormatDescription(config.format));
700 MultiPlaneImageData src (config.format, srcSize);
701
702 deUint32 nullAccessData (0u);
703 ChannelAccess nullAccess (tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT, 1u, IVec3(srcSize.x(), srcSize.y(), 1), IVec3(0, 0, 0), &nullAccessData, 0u);
704 deUint32 nullAccessAlphaData (~0u);
705 ChannelAccess nullAccessAlpha (tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT, 1u, IVec3(srcSize.x(), srcSize.y(), 1), IVec3(0, 0, 0), &nullAccessAlphaData, 0u);
706 ChannelAccess rChannelAccess (planeInfo.hasChannelNdx(0) ? getChannelAccess(src, planeInfo, srcSize, 0) : nullAccess);
707 ChannelAccess gChannelAccess (planeInfo.hasChannelNdx(1) ? getChannelAccess(src, planeInfo, srcSize, 1) : nullAccess);
708 ChannelAccess bChannelAccess (planeInfo.hasChannelNdx(2) ? getChannelAccess(src, planeInfo, srcSize, 2) : nullAccess);
709 ChannelAccess aChannelAccess (planeInfo.hasChannelNdx(3) ? getChannelAccess(src, planeInfo, srcSize, 3) : nullAccessAlpha);
710 const bool implicitNearestCosited ((config.chromaFilter == vk::VK_FILTER_NEAREST && !config.explicitReconstruction) &&
711 (config.xChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN_KHR || config.yChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN_KHR));
712
713 vector<Vec2> sts;
714 vector<vector<Vec4> > results;
715 vector<vector<Vec4> > minBounds;
716 vector<vector<Vec4> > minMidpointBounds;
717 vector<vector<Vec4> > maxBounds;
718 vector<vector<Vec4> > maxMidpointBounds;
719 vector<vector<Vec4> > uvBounds;
720 vector<vector<IVec4> > ijBounds;
721
722 for (deUint32 planeNdx = 0; planeNdx < planeInfo.numPlanes; planeNdx++)
723 deMemset(src.getPlanePtr(planeNdx), 0u, src.getPlaneSize(planeNdx));
724
725 // \todo Limit values to only values that produce defined values using selected colorRange and colorModel? The verification code handles those cases already correctly.
726 if (planeInfo.hasChannelNdx(0))
727 {
728 for (int y = 0; y < rChannelAccess.getSize().y(); y++)
729 for (int x = 0; x < rChannelAccess.getSize().x(); x++)
730 rChannelAccess.setChannel(IVec3(x, y, 0), (float)x / (float)rChannelAccess.getSize().x());
731 }
732
733 if (planeInfo.hasChannelNdx(1))
734 {
735 for (int y = 0; y < gChannelAccess.getSize().y(); y++)
736 for (int x = 0; x < gChannelAccess.getSize().x(); x++)
737 gChannelAccess.setChannel(IVec3(x, y, 0), (float)y / (float)gChannelAccess.getSize().y());
738 }
739
740 if (planeInfo.hasChannelNdx(2))
741 {
742 for (int y = 0; y < bChannelAccess.getSize().y(); y++)
743 for (int x = 0; x < bChannelAccess.getSize().x(); x++)
744 bChannelAccess.setChannel(IVec3(x, y, 0), (float)(x + y) / (float)(bChannelAccess.getSize().x() + bChannelAccess.getSize().y()));
745 }
746
747 if (planeInfo.hasChannelNdx(3))
748 {
749 for (int y = 0; y < aChannelAccess.getSize().y(); y++)
750 for (int x = 0; x < aChannelAccess.getSize().x(); x++)
751 aChannelAccess.setChannel(IVec3(x, y, 0), (float)(x * y) / (float)(aChannelAccess.getSize().x() * aChannelAccess.getSize().y()));
752 }
753
754 if (dstSize.x() > srcSize.x() && dstSize.y() > srcSize.y())
755 genTexCoords(sts, srcSize, dstSize);
756 else
757 genOneToOneTexCoords(sts, dstSize);
758
759 std::vector< vk::VkSamplerYcbcrModelConversion> colorModels;
760 if (config.colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST)
761 {
762 colorModels.push_back(config.colorModel);
763 }
764 else
765 {
766 int ycbcrModelConverionCount = std::min( (int)vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST, 4 );
767 for (int i = 0; i < ycbcrModelConverionCount; i++)
768 {
769 colorModels.push_back((vk::VkSamplerYcbcrModelConversion)(vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY + i));
770 }
771 }
772
773 for (int i = 0; i < (int)colorModels.size(); i++)
774 {
775 vector<Vec4> minBound;
776 vector<Vec4> minMidpointBound;
777 vector<Vec4> maxBound;
778 vector<Vec4> maxMidpointBound;
779 vector<Vec4> uvBound;
780 vector<IVec4> ijBound;
781
782 calculateBounds(rChannelAccess, gChannelAccess, bChannelAccess, aChannelAccess, bitDepth, sts, filteringPrecision, conversionPrecision, subTexelPrecisionBits, config.textureFilter, colorModels[i], config.colorRange, config.chromaFilter, config.xChromaOffset, config.yChromaOffset, config.componentMapping, explicitReconstruction, config.addressModeU, config.addressModeV, minBound, maxBound, uvBound, ijBound);
783
784 if (implicitNearestCosited)
785 {
786 calculateBounds(rChannelAccess, gChannelAccess, bChannelAccess, aChannelAccess, bitDepth, sts, filteringPrecision, conversionPrecision, subTexelPrecisionBits, config.textureFilter, colorModels[i], config.colorRange, config.chromaFilter, vk::VK_CHROMA_LOCATION_MIDPOINT_KHR, vk::VK_CHROMA_LOCATION_MIDPOINT_KHR, config.componentMapping, explicitReconstruction, config.addressModeU, config.addressModeV, minMidpointBound, maxMidpointBound, uvBound, ijBound);
787 }
788 results.push_back (vector<Vec4>());
789 minBounds.push_back (minBound);
790 minMidpointBounds.push_back (minMidpointBound);
791 maxBounds.push_back (maxBound);
792 maxMidpointBounds.push_back (maxMidpointBound);
793 uvBounds.push_back (uvBound);
794 ijBounds.push_back (ijBound);
795 }
796
797 if (vk::isYCbCrFormat(config.format))
798 {
799 tcu::TextureLevel rImage (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), rChannelAccess.getSize().x(), rChannelAccess.getSize().y());
800 tcu::TextureLevel gImage (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), gChannelAccess.getSize().x(), gChannelAccess.getSize().y());
801 tcu::TextureLevel bImage (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), bChannelAccess.getSize().x(), bChannelAccess.getSize().y());
802 tcu::TextureLevel aImage (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), aChannelAccess.getSize().x(), aChannelAccess.getSize().y());
803
804 for (int y = 0; y < (int)rChannelAccess.getSize().y(); y++)
805 for (int x = 0; x < (int)rChannelAccess.getSize().x(); x++)
806 rImage.getAccess().setPixel(Vec4(rChannelAccess.getChannel(IVec3(x, y, 0))), x, y);
807
808 for (int y = 0; y < (int)gChannelAccess.getSize().y(); y++)
809 for (int x = 0; x < (int)gChannelAccess.getSize().x(); x++)
810 gImage.getAccess().setPixel(Vec4(gChannelAccess.getChannel(IVec3(x, y, 0))), x, y);
811
812 for (int y = 0; y < (int)bChannelAccess.getSize().y(); y++)
813 for (int x = 0; x < (int)bChannelAccess.getSize().x(); x++)
814 bImage.getAccess().setPixel(Vec4(bChannelAccess.getChannel(IVec3(x, y, 0))), x, y);
815
816 for (int y = 0; y < (int)aChannelAccess.getSize().y(); y++)
817 for (int x = 0; x < (int)aChannelAccess.getSize().x(); x++)
818 aImage.getAccess().setPixel(Vec4(aChannelAccess.getChannel(IVec3(x, y, 0))), x, y);
819
820 {
821 const Vec4 scale (1.0f);
822 const Vec4 bias (0.0f);
823
824 log << TestLog::Image("SourceImageR", "SourceImageR", rImage.getAccess(), scale, bias);
825 log << TestLog::Image("SourceImageG", "SourceImageG", gImage.getAccess(), scale, bias);
826 log << TestLog::Image("SourceImageB", "SourceImageB", bImage.getAccess(), scale, bias);
827 log << TestLog::Image("SourceImageA", "SourceImageA", aImage.getAccess(), scale, bias);
828 }
829 }
830 else
831 {
832 tcu::TextureLevel srcImage (vk::mapVkFormat(config.format), srcSize.x(), srcSize.y());
833
834 for (int y = 0; y < (int)srcSize.y(); y++)
835 for (int x = 0; x < (int)srcSize.x(); x++)
836 {
837 const IVec3 pos (x, y, 0);
838 srcImage.getAccess().setPixel(Vec4(rChannelAccess.getChannel(pos), gChannelAccess.getChannel(pos), bChannelAccess.getChannel(pos), aChannelAccess.getChannel(pos)), x, y);
839 }
840
841 log << TestLog::Image("SourceImage", "SourceImage", srcImage.getAccess());
842 }
843
844 evalShader(context, config.shaderType, src, srcSize, config.format, config.imageTiling, config.disjoint, config.textureFilter, config.addressModeU, config.addressModeV, colorModels, config.colorRange, config.xChromaOffset, config.yChromaOffset, config.chromaFilter, config.componentMapping, config.explicitReconstruction, sts, config.samplerBinding, results);
845
846 {
847 std::vector<tcu::TextureLevel> minImages;
848 std::vector<tcu::TextureLevel> maxImages;
849 std::vector<tcu::TextureLevel> minMidpointImages;
850 std::vector<tcu::TextureLevel> maxMidpointImages;
851 std::vector<tcu::TextureLevel> resImages;
852 for (int i = 0; i < (int)colorModels.size(); i++)
853 {
854 minImages.push_back (tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
855 maxImages.push_back (tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
856 minMidpointImages.push_back (tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
857 maxMidpointImages.push_back (tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
858 resImages.push_back (tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
859 }
860
861 for (int i = 0; i < (int)colorModels.size(); i++)
862 for (int y = 0; y < (int)(dstSize.y()); y++)
863 for (int x = 0; x < (int)(dstSize.x()); x++)
864 {
865 const int ndx = x + y * (int)(dstSize.x());
866 minImages[i].getAccess().setPixel(minBounds[i][ndx], x, y);
867 maxImages[i].getAccess().setPixel(maxBounds[i][ndx], x, y);
868 }
869
870 for (int i = 0; i < (int)colorModels.size(); i++)
871 for (int y = 0; y < (int)(dstSize.y()); y++)
872 for (int x = 0; x < (int)(dstSize.x()); x++)
873 {
874 const int ndx = x + y * (int)(dstSize.x());
875 resImages[i].getAccess().setPixel(results[i][ndx], x, y);
876 }
877
878 if (implicitNearestCosited)
879 {
880 for (int i = 0; i < (int)colorModels.size(); i++)
881 for (int y = 0; y < (int)(dstSize.y()); y++)
882 for (int x = 0; x < (int)(dstSize.x()); x++)
883 {
884 const int ndx = x + y * (int)(dstSize.x());
885 minMidpointImages[i].getAccess().setPixel(minMidpointBounds[i][ndx], x, y);
886 maxMidpointImages[i].getAccess().setPixel(maxMidpointBounds[i][ndx], x, y);
887 }
888 }
889
890 for (int i = 0; i < (int)colorModels.size(); i++)
891 {
892 const Vec4 scale (1.0f);
893 const Vec4 bias (0.0f);
894
895 log << TestLog::Image(string("MinBoundImage_") + de::toString(i), string("MinBoundImage_") + de::toString(i), minImages[i].getAccess(), scale, bias);
896 log << TestLog::Image(string("MaxBoundImage_") + de::toString(i), string("MaxBoundImage_") + de::toString(i), maxImages[i].getAccess(), scale, bias);
897
898 if (implicitNearestCosited)
899 {
900 log << TestLog::Image(string("MinMidpointBoundImage_") + de::toString(i), string("MinMidpointBoundImage_") + de::toString(i), minMidpointImages[i].getAccess(), scale, bias);
901 log << TestLog::Image(string("MaxMidpointBoundImage_") + de::toString(i), string("MaxMidpointBoundImage_") + de::toString(i), maxMidpointImages[i].getAccess(), scale, bias);
902 }
903
904 log << TestLog::Image(string("ResultImage_") + de::toString(i), string("ResultImage_") + de::toString(i), resImages[i].getAccess(), scale, bias);
905 }
906 }
907
908 size_t errorCount = 0;
909
910 for (int i = 0; i < (int)colorModels.size(); i++)
911 for (size_t ndx = 0; ndx < sts.size(); ndx++)
912 {
913 bool fail;
914 if (implicitNearestCosited)
915 {
916 fail = (tcu::boolAny(tcu::lessThan(results[i][ndx], minMidpointBounds[i][ndx])) || tcu::boolAny(tcu::greaterThan(results[i][ndx], maxMidpointBounds[i][ndx]))) &&
917 (tcu::boolAny(tcu::lessThan(results[i][ndx], minBounds[i][ndx])) || tcu::boolAny(tcu::greaterThan(results[i][ndx], maxBounds[i][ndx])));
918 }
919 else
920 {
921 fail = tcu::boolAny(tcu::lessThan(results[i][ndx], minBounds[i][ndx])) || tcu::boolAny(tcu::greaterThan(results[i][ndx], maxBounds[i][ndx]));
922 }
923
924 if (fail)
925 {
926 log << TestLog::Message << "Fail: " << i << " " << sts[ndx] << " " << results[i][ndx] << TestLog::EndMessage;
927 log << TestLog::Message << " Min : " << minBounds[i][ndx] << TestLog::EndMessage;
928 log << TestLog::Message << " Max : " << maxBounds[i][ndx] << TestLog::EndMessage;
929 log << TestLog::Message << " Threshold: " << (maxBounds[i][ndx] - minBounds[i][ndx]) << TestLog::EndMessage;
930 log << TestLog::Message << " UMin : " << uvBounds[i][ndx][0] << TestLog::EndMessage;
931 log << TestLog::Message << " UMax : " << uvBounds[i][ndx][1] << TestLog::EndMessage;
932 log << TestLog::Message << " VMin : " << uvBounds[i][ndx][2] << TestLog::EndMessage;
933 log << TestLog::Message << " VMax : " << uvBounds[i][ndx][3] << TestLog::EndMessage;
934 log << TestLog::Message << " IMin : " << ijBounds[i][ndx][0] << TestLog::EndMessage;
935 log << TestLog::Message << " IMax : " << ijBounds[i][ndx][1] << TestLog::EndMessage;
936 log << TestLog::Message << " JMin : " << ijBounds[i][ndx][2] << TestLog::EndMessage;
937 log << TestLog::Message << " JMax : " << ijBounds[i][ndx][3] << TestLog::EndMessage;
938
939 if (isXChromaSubsampled(config.format))
940 {
941 log << TestLog::Message << " LumaAlphaValues : " << TestLog::EndMessage;
942 log << TestLog::Message << " Offset : (" << ijBounds[i][ndx][0] << ", " << ijBounds[i][ndx][2] << ")" << TestLog::EndMessage;
943
944 for (deInt32 k = ijBounds[i][ndx][2]; k <= ijBounds[i][ndx][3] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0); k++)
945 {
946 const deInt32 wrappedK = wrap(config.addressModeV, k, gChannelAccess.getSize().y());
947 bool first = true;
948 std::ostringstream line;
949
950 for (deInt32 j = ijBounds[i][ndx][0]; j <= ijBounds[i][ndx][1] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0); j++)
951 {
952 const deInt32 wrappedJ = wrap(config.addressModeU, j, gChannelAccess.getSize().x());
953
954 if (!first)
955 {
956 line << ", ";
957 first = false;
958 }
959
960 line << "(" << std::setfill(' ') << std::setw(5) << gChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
961 << ", " << std::setfill(' ') << std::setw(5) << aChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0)) << ")";
962 }
963 log << TestLog::Message << " " << line.str() << TestLog::EndMessage;
964 }
965
966 {
967 const IVec2 chromaJRange (divFloor(ijBounds[i][ndx][0], 2) - 1, divFloor(ijBounds[i][ndx][1] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0), 2) + 1);
968 const IVec2 chromaKRange (isYChromaSubsampled(config.format)
969 ? IVec2(divFloor(ijBounds[i][ndx][2], 2) - 1, divFloor(ijBounds[i][ndx][3] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0), 2) + 1)
970 : IVec2(ijBounds[i][ndx][2], ijBounds[i][ndx][3] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0)));
971
972 log << TestLog::Message << " ChromaValues : " << TestLog::EndMessage;
973 log << TestLog::Message << " Offset : (" << chromaJRange[0] << ", " << chromaKRange[0] << ")" << TestLog::EndMessage;
974
975 for (deInt32 k = chromaKRange[0]; k <= chromaKRange[1]; k++)
976 {
977 const deInt32 wrappedK = wrap(config.addressModeV, k, rChannelAccess.getSize().y());
978 bool first = true;
979 std::ostringstream line;
980
981 for (deInt32 j = chromaJRange[0]; j <= chromaJRange[1]; j++)
982 {
983 const deInt32 wrappedJ = wrap(config.addressModeU, j, rChannelAccess.getSize().x());
984
985 if (!first)
986 {
987 line << ", ";
988 first = false;
989 }
990
991 line << "(" << std::setfill(' ') << std::setw(5) << rChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
992 << ", " << std::setfill(' ') << std::setw(5) << bChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0)) << ")";
993 }
994 log << TestLog::Message << " " << line.str() << TestLog::EndMessage;
995 }
996 }
997 }
998 else
999 {
1000 log << TestLog::Message << " Values : " << TestLog::EndMessage;
1001 log << TestLog::Message << " Offset : (" << ijBounds[i][ndx][0] << ", " << ijBounds[i][ndx][2] << ")" << TestLog::EndMessage;
1002
1003 for (deInt32 k = ijBounds[i][ndx][2]; k <= ijBounds[i][ndx][3] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0); k++)
1004 {
1005 const deInt32 wrappedK = wrap(config.addressModeV, k, rChannelAccess.getSize().y());
1006 bool first = true;
1007 std::ostringstream line;
1008
1009 for (deInt32 j = ijBounds[i][ndx][0]; j <= ijBounds[i][ndx][1] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0); j++)
1010 {
1011 const deInt32 wrappedJ = wrap(config.addressModeU, j, rChannelAccess.getSize().x());
1012
1013 if (!first)
1014 {
1015 line << ", ";
1016 first = false;
1017 }
1018
1019 line << "(" << std::setfill(' ') << std::setw(5) << rChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
1020 << ", " << std::setfill(' ') << std::setw(5) << gChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
1021 << ", " << std::setfill(' ') << std::setw(5) << bChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
1022 << ", " << std::setfill(' ') << std::setw(5) << aChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0)) << ")";
1023 }
1024 log << TestLog::Message << " " << line.str() << TestLog::EndMessage;
1025 }
1026 }
1027
1028 errorCount++;
1029 isOk = false;
1030
1031 if (errorCount > 30)
1032 {
1033 log << TestLog::Message << "Encountered " << errorCount << " errors. Omitting rest of the per result logs." << TestLog::EndMessage;
1034 break;
1035 }
1036 }
1037 }
1038 }
1039
1040 if (isOk)
1041 return tcu::TestStatus::pass("Pass");
1042 else
1043 return tcu::TestStatus::fail("Result comparison failed");
1044 }
1045
1046 #if defined(FAKE_COLOR_CONVERSION)
swizzleToCompName(const char * identity,vk::VkComponentSwizzle swizzle)1047 const char* swizzleToCompName (const char* identity, vk::VkComponentSwizzle swizzle)
1048 {
1049 switch (swizzle)
1050 {
1051 case vk::VK_COMPONENT_SWIZZLE_IDENTITY: return identity;
1052 case vk::VK_COMPONENT_SWIZZLE_R: return "r";
1053 case vk::VK_COMPONENT_SWIZZLE_G: return "g";
1054 case vk::VK_COMPONENT_SWIZZLE_B: return "b";
1055 case vk::VK_COMPONENT_SWIZZLE_A: return "a";
1056 default:
1057 DE_FATAL("Unsupported swizzle");
1058 return DE_NULL;
1059 }
1060 }
1061 #endif
1062
createTestShaders(vk::SourceCollections & dst,TestConfig config)1063 void createTestShaders (vk::SourceCollections& dst, TestConfig config)
1064 {
1065 std::vector< vk::VkSamplerYcbcrModelConversion> colorModels;
1066 if (config.colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST)
1067 {
1068 colorModels.push_back(config.colorModel);
1069 }
1070 else
1071 {
1072 int ycbcrModelConverionCount = std::min((int)vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST, 4);
1073 for (int i = 0; i < ycbcrModelConverionCount; i++)
1074 {
1075 colorModels.push_back((vk::VkSamplerYcbcrModelConversion)(vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY + i));
1076 }
1077 }
1078 #if !defined(FAKE_COLOR_CONVERSION)
1079 const ShaderSpec spec (createShaderSpec(config.samplerBinding, colorModels));
1080
1081 generateSources(config.shaderType, spec, dst);
1082 #else
1083 const tcu::UVec4 bits (getYCbCrBitDepth(config.format));
1084 ShaderSpec spec;
1085
1086 spec.globalDeclarations = "layout(set=" + de::toString((int)EXTRA_RESOURCES_DESCRIPTOR_SET_INDEX) + ", binding=" + de::toString(config.samplerBinding) + ") uniform highp sampler2D u_sampler;";
1087
1088 spec.inputs.push_back(Symbol("uv", glu::VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_HIGHP)));
1089 spec.outputs.push_back(Symbol("o_color", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
1090
1091 std::ostringstream source;
1092
1093 source << "highp vec4 inputColor = texture(u_sampler, uv);\n";
1094
1095 source << "highp float r = inputColor." << swizzleToCompName("r", config.componentMapping.r) << ";\n";
1096 source << "highp float g = inputColor." << swizzleToCompName("g", config.componentMapping.g) << ";\n";
1097 source << "highp float b = inputColor." << swizzleToCompName("b", config.componentMapping.b) << ";\n";
1098 source << "highp float a = inputColor." << swizzleToCompName("a", config.componentMapping.a) << ";\n";
1099
1100 switch (config.colorRange)
1101 {
1102 case vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL:
1103 source << "highp float cr = r - (float(" << (0x1u << (bits[0] - 0x1u)) << ") / float(" << ((0x1u << bits[0]) - 1u) << "));\n";
1104 source << "highp float y = g;\n";
1105 source << "highp float cb = b - (float(" << (0x1u << (bits[2] - 0x1u)) << ") / float(" << ((0x1u << bits[2]) - 1u) << "));\n";
1106 break;
1107
1108 case vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW:
1109 source << "highp float cr = (r * float(" << ((0x1u << bits[0]) - 1u) << ") - float(" << (128u * (0x1u << (bits[0] - 8))) << ")) / float(" << (224u * (0x1u << (bits[0] - 8))) << ");\n";
1110 source << "highp float y = (g * float(" << ((0x1u << bits[1]) - 1u) << ") - float(" << (16u * (0x1u << (bits[1] - 8))) << ")) / float(" << (219u * (0x1u << (bits[1] - 8))) << ");\n";
1111 source << "highp float cb = (b * float(" << ((0x1u << bits[2]) - 1u) << ") - float(" << (128u * (0x1u << (bits[2] - 8))) << ")) / float(" << (224u * (0x1u << (bits[2] - 8))) << ");\n";
1112 break;
1113
1114 default:
1115 DE_FATAL("Unknown color range");
1116 }
1117
1118 source << "highp vec4 color;\n";
1119
1120 switch (config.colorModel)
1121 {
1122 case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY:
1123 source << "color = vec4(r, g, b, a);\n";
1124 break;
1125
1126 case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY:
1127 source << "color = vec4(cr, y, cb, a);\n";
1128 break;
1129
1130 case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601:
1131 source << "color = vec4(y + 1.402 * cr, y - float(" << (0.202008 / 0.587) << ") * cb - float(" << (0.419198 / 0.587) << ") * cr, y + 1.772 * cb, a);\n";
1132 break;
1133
1134 case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709:
1135 source << "color = vec4(y + 1.5748 * cr, y - float(" << (0.13397432 / 0.7152) << ") * cb - float(" << (0.33480248 / 0.7152) << ") * cr, y + 1.8556 * cb, a);\n";
1136 break;
1137
1138 case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020:
1139 source << "color = vec4(y + 1.4746 * cr, (y - float(" << (0.11156702 / 0.6780) << ") * cb) - float(" << (0.38737742 / 0.6780) << ") * cr, y + 1.8814 * cb, a);\n";
1140 break;
1141
1142 default:
1143 DE_FATAL("Unknown color model");
1144 };
1145
1146 source << "o_color = color;\n";
1147
1148 spec.source = source.str();
1149 generateSources(config.shaderType, spec, dst);
1150 #endif
1151 }
1152
1153 struct RangeNamePair
1154 {
1155 const char* name;
1156 vk::VkSamplerYcbcrRange value;
1157 };
1158
1159
1160 struct ChromaLocationNamePair
1161 {
1162 const char* name;
1163 vk::VkChromaLocation value;
1164 };
1165
1166 // Alternate between swizzle_identity and their equivalents. Both should work.
getIdentitySwizzle(void)1167 const vk::VkComponentMapping& getIdentitySwizzle (void)
1168 {
1169 static bool alternate = false;
1170 static const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
1171 static const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
1172
1173 const vk::VkComponentMapping& mapping = (alternate ? mappingB : mappingA);
1174 alternate = (!alternate);
1175 return mapping;
1176 }
1177
1178 struct YCbCrConversionTestBuilder
1179 {
1180 const std::vector<vk::VkFormat> noChromaSubsampledFormats =
1181 {
1182 vk::VK_FORMAT_R4G4B4A4_UNORM_PACK16,
1183 vk::VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1184 vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
1185 vk::VK_FORMAT_B5G6R5_UNORM_PACK16,
1186 vk::VK_FORMAT_R5G5B5A1_UNORM_PACK16,
1187 vk::VK_FORMAT_B5G5R5A1_UNORM_PACK16,
1188 vk::VK_FORMAT_A1R5G5B5_UNORM_PACK16,
1189 vk::VK_FORMAT_R8G8B8_UNORM,
1190 vk::VK_FORMAT_B8G8R8_UNORM,
1191 vk::VK_FORMAT_R8G8B8A8_UNORM,
1192 vk::VK_FORMAT_B8G8R8A8_UNORM,
1193 vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1194 vk::VK_FORMAT_A2R10G10B10_UNORM_PACK32,
1195 vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1196 vk::VK_FORMAT_R16G16B16_UNORM,
1197 vk::VK_FORMAT_R16G16B16A16_UNORM,
1198 vk::VK_FORMAT_R10X6_UNORM_PACK16,
1199 vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
1200 vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
1201 vk::VK_FORMAT_R12X4_UNORM_PACK16,
1202 vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
1203 vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
1204 vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
1205 vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
1206 vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
1207 vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
1208 vk::VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT,
1209 vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT,
1210 vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT,
1211 vk::VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT,
1212 };
1213 const std::vector<vk::VkFormat> xChromaSubsampledFormats =
1214 {
1215 vk::VK_FORMAT_G8B8G8R8_422_UNORM,
1216 vk::VK_FORMAT_B8G8R8G8_422_UNORM,
1217 vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
1218 vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
1219
1220 vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
1221 vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
1222 vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
1223 vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
1224 vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
1225 vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
1226 vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
1227 vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
1228 vk::VK_FORMAT_G16B16G16R16_422_UNORM,
1229 vk::VK_FORMAT_B16G16R16G16_422_UNORM,
1230 vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
1231 vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
1232 };
1233 const std::vector<vk::VkFormat> xyChromaSubsampledFormats =
1234 {
1235 vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
1236 vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
1237 vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
1238 vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
1239 vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
1240 vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
1241 vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
1242 vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
1243 };
1244 struct ColorModelStruct
1245 {
1246 const char* const name;
1247 const vk::VkSamplerYcbcrModelConversion value;
1248 };
1249 const std::vector<ColorModelStruct> colorModels =
1250 {
1251 { "rgb_identity", vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY },
1252 { "ycbcr_identity", vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY },
1253 { "ycbcr_709", vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 },
1254 { "ycbcr_601", vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 },
1255 { "ycbcr_2020", vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 }
1256 };
1257 const std::vector<RangeNamePair> colorRanges =
1258 {
1259 { "itu_full", vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL },
1260 { "itu_narrow", vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW }
1261 };
1262 const std::vector<ChromaLocationNamePair> chromaLocations =
1263 {
1264 { "cosited", vk::VK_CHROMA_LOCATION_COSITED_EVEN },
1265 { "midpoint", vk::VK_CHROMA_LOCATION_MIDPOINT }
1266 };
1267 struct TextureFilterStruct
1268 {
1269 const char* const name;
1270 vk::VkFilter value;
1271 };
1272 const std::vector<TextureFilterStruct> textureFilters =
1273 {
1274 { "linear", vk::VK_FILTER_LINEAR },
1275 { "nearest", vk::VK_FILTER_NEAREST }
1276 };
1277 // Used by the chroma reconstruction tests
1278 const vk::VkSamplerYcbcrModelConversion defaultColorModel = vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
1279 const vk::VkSamplerYcbcrRange defaultColorRange = vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
1280 const vk::VkComponentMapping swappedChromaSwizzle =
1281 {
1282 vk::VK_COMPONENT_SWIZZLE_B,
1283 vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1284 vk::VK_COMPONENT_SWIZZLE_R,
1285 vk::VK_COMPONENT_SWIZZLE_IDENTITY
1286 };
1287 const std::vector<glu::ShaderType> shaderTypes =
1288 {
1289 glu::SHADERTYPE_VERTEX,
1290 glu::SHADERTYPE_FRAGMENT,
1291 glu::SHADERTYPE_COMPUTE
1292 };
1293 struct ImageTilingStruct
1294 {
1295 const char* name;
1296 vk::VkImageTiling value;
1297 };
1298 const std::vector<ImageTilingStruct> imageTilings =
1299 {
1300 { "tiling_linear", vk::VK_IMAGE_TILING_LINEAR },
1301 { "tiling_optimal", vk::VK_IMAGE_TILING_OPTIMAL }
1302 };
1303 struct SamplerBindingStruct
1304 {
1305 const char* name;
1306 deUint32 value;
1307 };
1308 const std::vector<SamplerBindingStruct> samplerBindings =
1309 {
1310 { "binding_0", 0 },
1311 { "binding_7", 7 },
1312 { "binding_15", 15 },
1313 { "binding_31", 31 }
1314 };
1315
buildTestsvkt::ycbcr::__anon548eae410111::YCbCrConversionTestBuilder1316 void buildTests(tcu::TestCaseGroup* testGroup)
1317 {
1318 tcu::TestContext& testCtx(testGroup->getTestContext());
1319 de::Random rng(1978765638u);
1320
1321 // Test formats without chroma reconstruction
1322 for (size_t formatNdx = 0; formatNdx < noChromaSubsampledFormats.size(); formatNdx++)
1323 {
1324 const vk::VkFormat format(noChromaSubsampledFormats[formatNdx]);
1325 const std::string formatName(de::toLower(std::string(getFormatName(format)).substr(10)));
1326 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str(), ("Tests for color conversion using format " + formatName).c_str()));
1327 const UVec2 srcSize(isXChromaSubsampled(format) ? 12 : 7,
1328 isYChromaSubsampled(format) ? 8 : 13);
1329 const UVec2 dstSize(srcSize.x() + srcSize.x() / 2,
1330 srcSize.y() + srcSize.y() / 2);
1331
1332 for (size_t modelNdx = 0; modelNdx < colorModels.size(); modelNdx++)
1333 {
1334 const char* const colorModelName(colorModels[modelNdx].name);
1335 const vk::VkSamplerYcbcrModelConversion colorModel(colorModels[modelNdx].value);
1336
1337 if (colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY && getYCbCrFormatChannelCount(format) < 3)
1338 continue;
1339
1340 de::MovePtr<tcu::TestCaseGroup> colorModelGroup(new tcu::TestCaseGroup(testCtx, colorModelName, ("Tests for color model " + string(colorModelName)).c_str()));
1341
1342 if (colorModel == vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY)
1343 {
1344 for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1345 {
1346 const char* const textureFilterName(textureFilters[textureFilterNdx].name);
1347 const vk::VkFilter textureFilter(textureFilters[textureFilterNdx].value);
1348
1349 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1350 {
1351 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1352 const char* const tilingName(imageTilings[tilingNdx].name);
1353 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1354 const vk::VkSamplerYcbcrRange colorRange(rng.choose<RangeNamePair>(begin(colorRanges), end(colorRanges)).value);
1355 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1356
1357 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1358 {
1359 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1360 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1361 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1362 textureFilter, chromaLocation, chromaLocation, false, false,
1363 colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1364
1365 addFunctionCaseWithPrograms(colorModelGroup.get(), std::string(textureFilterName) + "_" + tilingName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1366 }
1367 }
1368 }
1369 }
1370 else
1371 {
1372 for (size_t rangeNdx = 0; rangeNdx < colorRanges.size(); rangeNdx++)
1373 {
1374 const char* const colorRangeName(colorRanges[rangeNdx].name);
1375 const vk::VkSamplerYcbcrRange colorRange(colorRanges[rangeNdx].value);
1376
1377 // Narrow range doesn't really work with formats that have less than 8 bits
1378 if (colorRange == vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW)
1379 {
1380 const UVec4 bitDepth(getYCbCrBitDepth(format));
1381
1382 if (bitDepth[0] < 8 || bitDepth[1] < 8 || bitDepth[2] < 8)
1383 continue;
1384 }
1385
1386 de::MovePtr<tcu::TestCaseGroup> colorRangeGroup(new tcu::TestCaseGroup(testCtx, colorRangeName, ("Tests for color range " + string(colorRangeName)).c_str()));
1387
1388 for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1389 {
1390 const char* const textureFilterName(textureFilters[textureFilterNdx].name);
1391 const vk::VkFilter textureFilter(textureFilters[textureFilterNdx].value);
1392
1393 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1394 {
1395 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1396 const char* const tilingName(imageTilings[tilingNdx].name);
1397 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(shaderTypes.begin(), shaderTypes.end()));
1398 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(chromaLocations.begin(), chromaLocations.end()).value);
1399 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++) {
1400 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1401 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1402 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1403 textureFilter, chromaLocation, chromaLocation, false, false,
1404 colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1405
1406 addFunctionCaseWithPrograms(colorRangeGroup.get(), std::string(textureFilterName) + "_" + tilingName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1407 }
1408 }
1409 }
1410
1411 colorModelGroup->addChild(colorRangeGroup.release());
1412 }
1413 }
1414
1415 formatGroup->addChild(colorModelGroup.release());
1416 }
1417
1418 // Color conversion tests for array of samplers ( noChromaSubsampledFormats )
1419 if (getYCbCrFormatChannelCount(format) >= 3)
1420 buildArrayOfSamplersTests(format, srcSize, dstSize, formatGroup, testCtx, rng);
1421
1422 testGroup->addChild(formatGroup.release());
1423 }
1424
1425 // Test formats with x chroma reconstruction
1426 for (size_t formatNdx = 0; formatNdx < xChromaSubsampledFormats.size(); formatNdx++)
1427 {
1428 const vk::VkFormat format(xChromaSubsampledFormats[formatNdx]);
1429 const std::string formatName(de::toLower(std::string(getFormatName(format)).substr(10)));
1430 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str(), ("Tests for color conversion using format " + formatName).c_str()));
1431 const UVec2 srcSize(isXChromaSubsampled(format) ? 12 : 7,
1432 isYChromaSubsampled(format) ? 8 : 13);
1433 const UVec2 dstSize(srcSize.x() + srcSize.x() / 2,
1434 srcSize.y() + srcSize.y() / 2);
1435
1436 // Color conversion tests
1437 {
1438 de::MovePtr<tcu::TestCaseGroup> conversionGroup(new tcu::TestCaseGroup(testCtx, "color_conversion", ""));
1439
1440 for (size_t xChromaOffsetNdx = 0; xChromaOffsetNdx < chromaLocations.size(); xChromaOffsetNdx++)
1441 {
1442 const char* const xChromaOffsetName(chromaLocations[xChromaOffsetNdx].name);
1443 const vk::VkChromaLocation xChromaOffset(chromaLocations[xChromaOffsetNdx].value);
1444
1445 for (size_t modelNdx = 0; modelNdx < colorModels.size(); modelNdx++)
1446 {
1447 const char* const colorModelName(colorModels[modelNdx].name);
1448 const vk::VkSamplerYcbcrModelConversion colorModel(colorModels[modelNdx].value);
1449
1450 if (colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY && getYCbCrFormatChannelCount(format) < 3)
1451 continue;
1452
1453
1454 if (colorModel == vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY)
1455 {
1456 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1457 {
1458 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1459 const char* const tilingName(imageTilings[tilingNdx].name);
1460 const vk::VkSamplerYcbcrRange colorRange(rng.choose<RangeNamePair>(begin(colorRanges), end(colorRanges)).value);
1461 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1462 const vk::VkChromaLocation yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1463 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1464 {
1465 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1466 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1467 const TestConfig config(shaderType, format, tiling, vk::VK_FILTER_NEAREST, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1468 vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, false, false,
1469 colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1470
1471 addFunctionCaseWithPrograms(conversionGroup.get(), string(colorModelName) + "_" + tilingName + "_" + xChromaOffsetName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1472 }
1473 }
1474 }
1475 else
1476 {
1477 for (size_t rangeNdx = 0; rangeNdx < colorRanges.size(); rangeNdx++)
1478 {
1479 const char* const colorRangeName(colorRanges[rangeNdx].name);
1480 const vk::VkSamplerYcbcrRange colorRange(colorRanges[rangeNdx].value);
1481
1482 // Narrow range doesn't really work with formats that have less than 8 bits
1483 if (colorRange == vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW)
1484 {
1485 const UVec4 bitDepth(getYCbCrBitDepth(format));
1486
1487 if (bitDepth[0] < 8 || bitDepth[1] < 8 || bitDepth[2] < 8)
1488 continue;
1489 }
1490
1491 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1492 {
1493 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1494 const char* const tilingName(imageTilings[tilingNdx].name);
1495 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1496 const vk::VkChromaLocation yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1497 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1498 {
1499 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1500 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1501 const TestConfig config(shaderType, format, tiling, vk::VK_FILTER_NEAREST, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1502 vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, false, false,
1503 colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1504
1505 addFunctionCaseWithPrograms(conversionGroup.get(), string(colorModelName) + "_" + colorRangeName + "_" + tilingName + "_" + xChromaOffsetName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1506 }
1507 }
1508 }
1509 }
1510 }
1511 }
1512
1513 formatGroup->addChild(conversionGroup.release());
1514 }
1515
1516 // Color conversion tests for array of samplers ( xChromaSubsampledFormats )
1517 if (getYCbCrFormatChannelCount(format) >= 3)
1518 buildArrayOfSamplersTests(format, srcSize, dstSize, formatGroup, testCtx, rng);
1519
1520 // Chroma reconstruction tests
1521 {
1522 de::MovePtr<tcu::TestCaseGroup> reconstrucGroup(new tcu::TestCaseGroup(testCtx, "chroma_reconstruction", ""));
1523
1524 for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1525 {
1526 const char* const textureFilterName(textureFilters[textureFilterNdx].name);
1527 const vk::VkFilter textureFilter(textureFilters[textureFilterNdx].value);
1528 de::MovePtr<tcu::TestCaseGroup> textureFilterGroup(new tcu::TestCaseGroup(testCtx, textureFilterName, textureFilterName));
1529
1530 for (size_t explicitReconstructionNdx = 0; explicitReconstructionNdx < 2; explicitReconstructionNdx++)
1531 {
1532 const bool explicitReconstruction(explicitReconstructionNdx == 1);
1533
1534 for (size_t disjointNdx = 0; disjointNdx < 2; disjointNdx++)
1535 {
1536 const bool disjoint(disjointNdx == 1);
1537
1538 for (size_t xChromaOffsetNdx = 0; xChromaOffsetNdx < chromaLocations.size(); xChromaOffsetNdx++)
1539 {
1540 const vk::VkChromaLocation xChromaOffset(chromaLocations[xChromaOffsetNdx].value);
1541 const char* const xChromaOffsetName(chromaLocations[xChromaOffsetNdx].name);
1542
1543 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1544 {
1545 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1546 const char* const tilingName(imageTilings[tilingNdx].name);
1547
1548 {
1549 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1550 const vk::VkChromaLocation yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1551 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1552 vk::VK_FILTER_LINEAR, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1553 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1554
1555 addFunctionCaseWithPrograms(textureFilterGroup.get(), string(explicitReconstruction ? "explicit_linear_" : "default_linear_") + xChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1556 }
1557
1558 {
1559 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1560 const vk::VkChromaLocation yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1561 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1562 vk::VK_FILTER_LINEAR, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1563 defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1564
1565 addFunctionCaseWithPrograms(textureFilterGroup.get(), string(explicitReconstruction ? "explicit_linear_" : "default_linear_") + xChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1566 }
1567
1568 if (!explicitReconstruction)
1569 {
1570 {
1571 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1572 const vk::VkChromaLocation yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1573 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1574 vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1575 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1576
1577 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("default_nearest_") + xChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1578 }
1579
1580 {
1581 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1582 const vk::VkChromaLocation yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1583 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1584 vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1585 defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1586
1587 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("default_nearest_") + xChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1588 }
1589 }
1590 }
1591 }
1592
1593 if (explicitReconstruction)
1594 {
1595 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1596 {
1597 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1598 const char* const tilingName(imageTilings[tilingNdx].name);
1599 {
1600 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1601 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1602 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1603 vk::VK_FILTER_NEAREST, chromaLocation, chromaLocation, explicitReconstruction, disjoint,
1604 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1605
1606 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("explicit_nearest") + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1607 }
1608
1609 {
1610 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1611 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1612 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1613 vk::VK_FILTER_NEAREST, chromaLocation, chromaLocation, explicitReconstruction, disjoint,
1614 defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1615
1616 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("explicit_nearest") + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1617 }
1618 }
1619 }
1620 }
1621 }
1622
1623 reconstrucGroup->addChild(textureFilterGroup.release());
1624 }
1625
1626 formatGroup->addChild(reconstrucGroup.release());
1627 }
1628
1629 testGroup->addChild(formatGroup.release());
1630 }
1631
1632 // Test formats with xy chroma reconstruction
1633 for (size_t formatNdx = 0; formatNdx < xyChromaSubsampledFormats.size(); formatNdx++)
1634 {
1635 const vk::VkFormat format(xyChromaSubsampledFormats[formatNdx]);
1636 const std::string formatName(de::toLower(std::string(getFormatName(format)).substr(10)));
1637 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str(), ("Tests for color conversion using format " + formatName).c_str()));
1638 const UVec2 srcSize(isXChromaSubsampled(format) ? 12 : 7,
1639 isYChromaSubsampled(format) ? 8 : 13);
1640 const UVec2 dstSize(srcSize.x() + srcSize.x() / 2,
1641 srcSize.y() + srcSize.y() / 2);
1642
1643 // Color conversion tests
1644 {
1645 de::MovePtr<tcu::TestCaseGroup> conversionGroup(new tcu::TestCaseGroup(testCtx, "color_conversion", ""));
1646
1647 for (size_t chromaOffsetNdx = 0; chromaOffsetNdx < chromaLocations.size(); chromaOffsetNdx++)
1648 {
1649 const char* const chromaOffsetName(chromaLocations[chromaOffsetNdx].name);
1650 const vk::VkChromaLocation chromaOffset(chromaLocations[chromaOffsetNdx].value);
1651
1652 for (size_t modelNdx = 0; modelNdx < colorModels.size(); modelNdx++)
1653 {
1654 const char* const colorModelName(colorModels[modelNdx].name);
1655 const vk::VkSamplerYcbcrModelConversion colorModel(colorModels[modelNdx].value);
1656
1657 if (colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY && getYCbCrFormatChannelCount(format) < 3)
1658 continue;
1659
1660 if (colorModel == vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY)
1661 {
1662 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1663 {
1664 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1665 const char* const tilingName(imageTilings[tilingNdx].name);
1666 const vk::VkSamplerYcbcrRange colorRange(rng.choose<RangeNamePair>(begin(colorRanges), end(colorRanges)).value);
1667 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1668 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1669 {
1670 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1671 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1672 const TestConfig config(shaderType, format, tiling, vk::VK_FILTER_NEAREST, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1673 vk::VK_FILTER_NEAREST, chromaOffset, chromaOffset, false, false,
1674 colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1675
1676 addFunctionCaseWithPrograms(conversionGroup.get(), std::string(colorModelName) + "_" + tilingName + "_" + chromaOffsetName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1677 }
1678 }
1679 }
1680 else
1681 {
1682 for (size_t rangeNdx = 0; rangeNdx < colorRanges.size(); rangeNdx++)
1683 {
1684 const char* const colorRangeName(colorRanges[rangeNdx].name);
1685 const vk::VkSamplerYcbcrRange colorRange(colorRanges[rangeNdx].value);
1686
1687 // Narrow range doesn't really work with formats that have less than 8 bits
1688 if (colorRange == vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW)
1689 {
1690 const UVec4 bitDepth(getYCbCrBitDepth(format));
1691
1692 if (bitDepth[0] < 8 || bitDepth[1] < 8 || bitDepth[2] < 8)
1693 continue;
1694 }
1695
1696 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1697 {
1698 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1699 const char* const tilingName(imageTilings[tilingNdx].name);
1700 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1701 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1702 {
1703 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1704 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1705 const TestConfig config(shaderType, format, tiling, vk::VK_FILTER_NEAREST, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1706 vk::VK_FILTER_NEAREST, chromaOffset, chromaOffset, false, false,
1707 colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1708
1709 addFunctionCaseWithPrograms(conversionGroup.get(), string(colorModelName) + "_" + colorRangeName + "_" + tilingName + "_" + chromaOffsetName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1710 }
1711 }
1712 }
1713 }
1714 }
1715 }
1716
1717 formatGroup->addChild(conversionGroup.release());
1718 }
1719
1720 // Color conversion tests for array of samplers ( xyChromaSubsampledFormats )
1721 if (getYCbCrFormatChannelCount(format) >= 3)
1722 buildArrayOfSamplersTests(format, srcSize, dstSize, formatGroup, testCtx, rng);
1723
1724 // Chroma reconstruction tests
1725 {
1726 de::MovePtr<tcu::TestCaseGroup> reconstrucGroup(new tcu::TestCaseGroup(testCtx, "chroma_reconstruction", ""));
1727
1728 for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1729 {
1730 const char* const textureFilterName(textureFilters[textureFilterNdx].name);
1731 const vk::VkFilter textureFilter(textureFilters[textureFilterNdx].value);
1732 de::MovePtr<tcu::TestCaseGroup> textureFilterGroup(new tcu::TestCaseGroup(testCtx, textureFilterName, textureFilterName));
1733
1734 for (size_t explicitReconstructionNdx = 0; explicitReconstructionNdx < 2; explicitReconstructionNdx++)
1735 {
1736 const bool explicitReconstruction(explicitReconstructionNdx == 1);
1737
1738 for (size_t disjointNdx = 0; disjointNdx < 2; disjointNdx++)
1739 {
1740 const bool disjoint(disjointNdx == 1);
1741
1742 for (size_t xChromaOffsetNdx = 0; xChromaOffsetNdx < chromaLocations.size(); xChromaOffsetNdx++)
1743 for (size_t yChromaOffsetNdx = 0; yChromaOffsetNdx < chromaLocations.size(); yChromaOffsetNdx++)
1744 {
1745 const vk::VkChromaLocation xChromaOffset(chromaLocations[xChromaOffsetNdx].value);
1746 const char* const xChromaOffsetName(chromaLocations[xChromaOffsetNdx].name);
1747
1748 const vk::VkChromaLocation yChromaOffset(chromaLocations[yChromaOffsetNdx].value);
1749 const char* const yChromaOffsetName(chromaLocations[yChromaOffsetNdx].name);
1750
1751 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1752 {
1753 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1754 const char* const tilingName(imageTilings[tilingNdx].name);
1755 {
1756 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1757 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1758 vk::VK_FILTER_LINEAR, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1759 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1760
1761 addFunctionCaseWithPrograms(textureFilterGroup.get(), string(explicitReconstruction ? "explicit_linear_" : "default_linear_") + xChromaOffsetName + "_" + yChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1762 }
1763
1764 {
1765 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1766 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1767 vk::VK_FILTER_LINEAR, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1768 defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1769
1770 addFunctionCaseWithPrograms(textureFilterGroup.get(), string(explicitReconstruction ? "explicit_linear_" : "default_linear_") + xChromaOffsetName + "_" + yChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1771 }
1772
1773 if (!explicitReconstruction)
1774 {
1775 {
1776 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1777 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1778 vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1779 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1780
1781 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("default_nearest_") + xChromaOffsetName + "_" + yChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1782 }
1783
1784 {
1785 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1786 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1787 vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1788 defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1789
1790 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("default_nearest_") + xChromaOffsetName + "_" + yChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1791 }
1792 }
1793 }
1794 }
1795
1796 if (explicitReconstruction)
1797 {
1798 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1799 {
1800 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1801 const char* const tilingName(imageTilings[tilingNdx].name);
1802 {
1803 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1804 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1805 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1806 vk::VK_FILTER_NEAREST, chromaLocation, chromaLocation, explicitReconstruction, disjoint,
1807 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1808
1809 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("explicit_nearest") + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1810 }
1811
1812 {
1813 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1814 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1815 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1816 vk::VK_FILTER_NEAREST, chromaLocation, chromaLocation, explicitReconstruction, disjoint,
1817 defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1818
1819 addFunctionCaseWithPrograms(textureFilterGroup.get(), string("explicit_nearest") + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1820 }
1821 }
1822 }
1823 }
1824 }
1825
1826 reconstrucGroup->addChild(textureFilterGroup.release());
1827 }
1828
1829 formatGroup->addChild(reconstrucGroup.release());
1830 }
1831
1832 testGroup->addChild(formatGroup.release());
1833 }
1834
1835 {
1836 const UVec2 imageSizes[] =
1837 {
1838 UVec2(16, 16),
1839 UVec2(20, 12)
1840 };
1841
1842 de::MovePtr<tcu::TestCaseGroup> oneToOneGroup(new tcu::TestCaseGroup(testCtx, "one_to_one", "Ycbcr images sampled to a frame buffer of the same dimentions."));
1843
1844 const vk::VkFormat format(vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR);
1845 const vk::VkFilter filter(vk::VK_FILTER_NEAREST);
1846
1847 for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(imageSizes); sizeNdx++)
1848 {
1849 const UVec2 srcSize(imageSizes[sizeNdx]);
1850
1851 for (size_t xChromaOffsetNdx = 0; xChromaOffsetNdx < chromaLocations.size(); xChromaOffsetNdx++)
1852 {
1853 const vk::VkChromaLocation xChromaOffset(chromaLocations[xChromaOffsetNdx].value);
1854 const char* const xChromaOffsetName(chromaLocations[xChromaOffsetNdx].name);
1855
1856 for (size_t yChromaOffsetNdx = 0; yChromaOffsetNdx < chromaLocations.size(); yChromaOffsetNdx++)
1857 {
1858 const vk::VkChromaLocation yChromaOffset(chromaLocations[yChromaOffsetNdx].value);
1859 const char* const yChromaOffsetName(chromaLocations[yChromaOffsetNdx].name);
1860
1861 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1862 {
1863 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1864 const char* const tilingName(imageTilings[tilingNdx].name);
1865
1866 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1867
1868 const TestConfig config(shaderType, format, tiling, filter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1869 filter, xChromaOffset, yChromaOffset, false, false,
1870 defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, srcSize, 0);
1871 std::ostringstream testName;
1872 testName << string("implicit_nearest_") << srcSize.x() << "x" << srcSize.y() << "_" << tilingName << "_" << xChromaOffsetName << "_" << yChromaOffsetName;
1873
1874 addFunctionCaseWithPrograms(oneToOneGroup.get(), testName.str(), "", checkSupport, createTestShaders, textureConversionTest, config);
1875 }
1876 }
1877 }
1878 }
1879
1880 testGroup->addChild(oneToOneGroup.release());
1881 }
1882 }
1883
buildArrayOfSamplersTestsvkt::ycbcr::__anon548eae410111::YCbCrConversionTestBuilder1884 void buildArrayOfSamplersTests(const vk::VkFormat& format, const UVec2& srcSize, const UVec2& dstSize, de::MovePtr<tcu::TestCaseGroup>& formatGroup, tcu::TestContext& testCtx, de::Random& rng )
1885 {
1886 de::MovePtr<tcu::TestCaseGroup> samplerArrayGroup(new tcu::TestCaseGroup(testCtx, "sampler_array", "Tests for array of samplers"));
1887
1888 for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1889 {
1890 const char* const textureFilterName(textureFilters[textureFilterNdx].name);
1891 const vk::VkFilter textureFilter(textureFilters[textureFilterNdx].value);
1892
1893 for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1894 {
1895 const vk::VkImageTiling tiling(imageTilings[tilingNdx].value);
1896 const char* const tilingName(imageTilings[tilingNdx].name);
1897 const glu::ShaderType shaderType(rng.choose<glu::ShaderType>(shaderTypes.begin(), shaderTypes.end()));
1898 const vk::VkSamplerYcbcrRange colorRange(vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL);
1899 const vk::VkChromaLocation chromaLocation(rng.choose<ChromaLocationNamePair>(chromaLocations.begin(), chromaLocations.end()).value);
1900
1901 for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1902 {
1903 const deUint32 samplerBinding(samplerBindings[bindingNdx].value);
1904 string samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1905 // colorModel==VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST means that we want to create an array of samplers instead of a single sampler
1906 const TestConfig config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1907 textureFilter, chromaLocation, chromaLocation, false, false,
1908 colorRange, vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1909
1910 addFunctionCaseWithPrograms(samplerArrayGroup.get(), std::string(textureFilterName) + "_" + tilingName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1911 }
1912 }
1913 }
1914 formatGroup->addChild(samplerArrayGroup.release());
1915 }
1916 };
1917
initTests(tcu::TestCaseGroup * testGroup)1918 void initTests(tcu::TestCaseGroup* testGroup)
1919 {
1920 YCbCrConversionTestBuilder testBuilder;
1921 testBuilder.buildTests(testGroup);
1922 }
1923
1924 } // anonymous
1925
createConversionTests(tcu::TestContext & testCtx)1926 tcu::TestCaseGroup* createConversionTests (tcu::TestContext& testCtx)
1927 {
1928 return createTestGroup(testCtx, "conversion", "Sampler YCbCr Conversion Tests", initTests);
1929 }
1930
1931 } // ycbcr
1932 } // vkt
1933