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 SPIR-V Assembly Tests for the VK_KHR_16bit_storage 22 *//*--------------------------------------------------------------------*/ 23 24// VK_KHR_16bit_storage 25// 26// \todo [2017-02-08 antiagainst] Additional corner cases to check: 27// 28// * Test OpAccessChain with subword types 29// * For newly enabled types T: 30// * For composite types: vector, matrix, structures, array over T: 31// 1. Use OpAccessChain to form a pointer to a subword type. 32// 2. Load the subword value X16. 33// 3. Convert X16 to X32. 34// 4. Store X32 to BufferBlock. 35// 5. Host inspects X32. 36// * Test {StorageInputOutput16} 16-to-16: 37// * For newly enabled types T: 38// 1. Host creates X16 stream values of type T. 39// 2. Shaders have corresponding capability. 40// 3. For each viable shader stage: 41// 3a. Load X16 Input variable. 42// 3b. Store X16 to Output variable. 43// 4. Host inspects resulting values. 44// * Test {StorageInputOutput16} 16-to-16 one value to two: 45// Like the previous test, but write X16 to two different output variables. 46// (Checks that the 16-bit intermediate value can be used twice.) 47 48#include "vktSpvAsm16bitStorageTests.hpp" 49 50#include "tcuFloat.hpp" 51#include "tcuRGBA.hpp" 52#include "tcuStringTemplate.hpp" 53#include "tcuTestLog.hpp" 54#include "tcuVectorUtil.hpp" 55 56#include "vkDefs.hpp" 57#include "vkDeviceUtil.hpp" 58#include "vkMemUtil.hpp" 59#include "vkPlatform.hpp" 60#include "vkPrograms.hpp" 61#include "vkQueryUtil.hpp" 62#include "vkRef.hpp" 63#include "vkRefUtil.hpp" 64#include "vkStrUtil.hpp" 65#include "vkTypeUtil.hpp" 66 67#include "deRandom.hpp" 68#include "deStringUtil.hpp" 69#include "deUniquePtr.hpp" 70#include "deMath.h" 71 72#include "vktSpvAsmComputeShaderCase.hpp" 73#include "vktSpvAsmComputeShaderTestUtil.hpp" 74#include "vktSpvAsmGraphicsShaderTestUtil.hpp" 75#include "vktTestCaseUtil.hpp" 76#include "vktTestGroupUtil.hpp" 77 78#include <limits> 79#include <map> 80#include <string> 81#include <sstream> 82#include <utility> 83 84namespace vkt 85{ 86namespace SpirVAssembly 87{ 88 89using namespace vk; 90using std::map; 91using std::string; 92using std::vector; 93using tcu::IVec3; 94using tcu::IVec4; 95using tcu::RGBA; 96using tcu::TestLog; 97using tcu::TestStatus; 98using tcu::Vec4; 99using de::UniquePtr; 100using tcu::StringTemplate; 101using tcu::Vec4; 102 103namespace 104{ 105 106struct Capability 107{ 108 const char* name; 109 const char* cap; 110 const char* decor; 111 vk::VkDescriptorType dtype; 112}; 113 114static const Capability CAPABILITIES[] = 115{ 116 {"uniform_buffer_block", "StorageUniformBufferBlock16", "BufferBlock", VK_DESCRIPTOR_TYPE_STORAGE_BUFFER}, 117 {"uniform", "StorageUniform16", "Block", VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER}, 118}; 119 120VulkanFeatures get16BitStorageFeatures (const char* cap) 121{ 122 VulkanFeatures features; 123 if (string(cap) == "uniform_buffer_block") 124 features.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK; 125 else if (string(cap) == "uniform") 126 features.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM; 127 else 128 DE_ASSERT(false && "not supported"); 129 130 return features; 131} 132 133 134// Batch function to check arrays of 16-bit floats. 135// 136// For comparing 16-bit floats, we need to consider both RTZ and RTE. So we can only recalculate 137// the expected values here instead of get the expected values directly from the test case. 138// Thus we need original floats here but not expected outputs. 139template<RoundingModeFlags RoundingMode> 140bool graphicsCheck16BitFloats (const std::vector<Resource>& originalFloats, 141 const vector<AllocationSp>& outputAllocs, 142 const std::vector<Resource>& /* expectedOutputs */, 143 tcu::TestLog& log) 144{ 145 if (outputAllocs.size() != originalFloats.size()) 146 return false; 147 148 for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx) 149 { 150 vector<deUint8> originalBytes; 151 originalFloats[outputNdx].second->getBytes(originalBytes); 152 153 const deUint16* returned = static_cast<const deUint16*>(outputAllocs[outputNdx]->getHostPtr()); 154 const float* original = reinterpret_cast<const float*>(&originalBytes.front()); 155 const deUint32 count = static_cast<deUint32>(originalBytes.size() / sizeof(float)); 156 157 for (deUint32 numNdx = 0; numNdx < count; ++numNdx) 158 if (!compare16BitFloat(original[numNdx], returned[numNdx], RoundingMode, log)) 159 return false; 160 } 161 162 return true; 163} 164 165template<RoundingModeFlags RoundingMode> 166bool computeCheck16BitFloats (const std::vector<BufferSp>& originalFloats, 167 const vector<AllocationSp>& outputAllocs, 168 const std::vector<BufferSp>& /* expectedOutputs */, 169 tcu::TestLog& log) 170{ 171 if (outputAllocs.size() != originalFloats.size()) 172 return false; 173 174 for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx) 175 { 176 vector<deUint8> originalBytes; 177 originalFloats[outputNdx]->getBytes(originalBytes); 178 179 const deUint16* returned = static_cast<const deUint16*>(outputAllocs[outputNdx]->getHostPtr()); 180 const float* original = reinterpret_cast<const float*>(&originalBytes.front()); 181 const deUint32 count = static_cast<deUint32>(originalBytes.size() / sizeof(float)); 182 183 for (deUint32 numNdx = 0; numNdx < count; ++numNdx) 184 if (!compare16BitFloat(original[numNdx], returned[numNdx], RoundingMode, log)) 185 return false; 186 } 187 188 return true; 189} 190 191 192// Batch function to check arrays of 32-bit floats. 193// 194// For comparing 32-bit floats, we just need the expected value precomputed in the test case. 195// So we need expected outputs here but not original floats. 196bool check32BitFloats (const std::vector<Resource>& /* originalFloats */, 197 const std::vector<AllocationSp>& outputAllocs, 198 const std::vector<Resource>& expectedOutputs, 199 tcu::TestLog& log) 200{ 201 if (outputAllocs.size() != expectedOutputs.size()) 202 return false; 203 204 for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx) 205 { 206 vector<deUint8> expectedBytes; 207 expectedOutputs[outputNdx].second->getBytes(expectedBytes); 208 209 const float* returnedAsFloat = static_cast<const float*>(outputAllocs[outputNdx]->getHostPtr()); 210 const float* expectedAsFloat = reinterpret_cast<const float*>(&expectedBytes.front()); 211 const deUint32 count = static_cast<deUint32>(expectedBytes.size() / sizeof(float)); 212 213 for (deUint32 numNdx = 0; numNdx < count; ++numNdx) 214 if (!compare32BitFloat(expectedAsFloat[numNdx], returnedAsFloat[numNdx], log)) 215 return false; 216 } 217 218 return true; 219} 220 221// Overload for compute pipeline 222bool check32BitFloats (const std::vector<BufferSp>& /* originalFloats */, 223 const std::vector<AllocationSp>& outputAllocs, 224 const std::vector<BufferSp>& expectedOutputs, 225 tcu::TestLog& log) 226{ 227 if (outputAllocs.size() != expectedOutputs.size()) 228 return false; 229 230 for (deUint32 outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx) 231 { 232 vector<deUint8> expectedBytes; 233 expectedOutputs[outputNdx]->getBytes(expectedBytes); 234 235 const float* returnedAsFloat = static_cast<const float*>(outputAllocs[outputNdx]->getHostPtr()); 236 const float* expectedAsFloat = reinterpret_cast<const float*>(&expectedBytes.front()); 237 const deUint32 count = static_cast<deUint32>(expectedBytes.size() / sizeof(float)); 238 239 for (deUint32 numNdx = 0; numNdx < count; ++numNdx) 240 if (!compare32BitFloat(expectedAsFloat[numNdx], returnedAsFloat[numNdx], log)) 241 return false; 242 } 243 244 return true; 245} 246 247// Generate and return 32-bit integers. 248// 249// Expected count to be at least 16. 250vector<deInt32> getInt32s (de::Random& rnd, const deUint32 count) 251{ 252 vector<deInt32> data; 253 254 data.reserve(count); 255 256 // Make sure we have boundary numbers. 257 data.push_back(deInt32(0x00000000)); // 0 258 data.push_back(deInt32(0x00000001)); // 1 259 data.push_back(deInt32(0x0000002a)); // 42 260 data.push_back(deInt32(0x00007fff)); // 32767 261 data.push_back(deInt32(0x00008000)); // 32768 262 data.push_back(deInt32(0x0000ffff)); // 65535 263 data.push_back(deInt32(0x00010000)); // 65536 264 data.push_back(deInt32(0x7fffffff)); // 2147483647 265 data.push_back(deInt32(0x80000000)); // -2147483648 266 data.push_back(deInt32(0x80000001)); // -2147483647 267 data.push_back(deInt32(0xffff0000)); // -65536 268 data.push_back(deInt32(0xffff0001)); // -65535 269 data.push_back(deInt32(0xffff8000)); // -32768 270 data.push_back(deInt32(0xffff8001)); // -32767 271 data.push_back(deInt32(0xffffffd6)); // -42 272 data.push_back(deInt32(0xffffffff)); // -1 273 274 DE_ASSERT(count >= data.size()); 275 276 for (deUint32 numNdx = static_cast<deUint32>(data.size()); numNdx < count; ++numNdx) 277 data.push_back(static_cast<deInt32>(rnd.getUint32())); 278 279 return data; 280} 281 282// Generate and return 16-bit integers. 283// 284// Expected count to be at least 8. 285vector<deInt16> getInt16s (de::Random& rnd, const deUint32 count) 286{ 287 vector<deInt16> data; 288 289 data.reserve(count); 290 291 // Make sure we have boundary numbers. 292 data.push_back(deInt16(0x0000)); // 0 293 data.push_back(deInt16(0x0001)); // 1 294 data.push_back(deInt16(0x002a)); // 42 295 data.push_back(deInt16(0x7fff)); // 32767 296 data.push_back(deInt16(0x8000)); // -32868 297 data.push_back(deInt16(0x8001)); // -32767 298 data.push_back(deInt16(0xffd6)); // -42 299 data.push_back(deInt16(0xffff)); // -1 300 301 DE_ASSERT(count >= data.size()); 302 303 for (deUint32 numNdx = static_cast<deUint32>(data.size()); numNdx < count; ++numNdx) 304 data.push_back(static_cast<deInt16>(rnd.getUint16())); 305 306 return data; 307} 308 309// IEEE-754 floating point numbers: 310// +--------+------+----------+-------------+ 311// | binary | sign | exponent | significand | 312// +--------+------+----------+-------------+ 313// | 16-bit | 1 | 5 | 10 | 314// +--------+------+----------+-------------+ 315// | 32-bit | 1 | 8 | 23 | 316// +--------+------+----------+-------------+ 317// 318// 16-bit floats: 319// 320// 0 000 00 00 0000 0001 (0x0001: 2e-24: minimum positive denormalized) 321// 0 000 00 11 1111 1111 (0x03ff: 2e-14 - 2e-24: maximum positive denormalized) 322// 0 000 01 00 0000 0000 (0x0400: 2e-14: minimum positive normalized) 323// 324// 32-bit floats: 325// 326// 0 011 1110 1 001 0000 0000 0000 0000 0000 (0x3e900000: 0.28125: with exact match in 16-bit normalized) 327// 0 011 1000 1 000 0000 0011 0000 0000 0000 (0x38803000: exact half way within two 16-bit normalized; round to zero: 0x0401) 328// 1 011 1000 1 000 0000 0011 0000 0000 0000 (0xb8803000: exact half way within two 16-bit normalized; round to zero: 0x8402) 329// 0 011 1000 1 000 0000 1111 1111 0000 0000 (0x3880ff00: not exact half way within two 16-bit normalized; round to zero: 0x0403) 330// 1 011 1000 1 000 0000 1111 1111 0000 0000 (0xb880ff00: not exact half way within two 16-bit normalized; round to zero: 0x8404) 331 332 333// Generate and return 32-bit floats 334// 335// The first 24 number pairs are manually picked, while the rest are randomly generated. 336// Expected count to be at least 24 (numPicks). 337vector<float> getFloat32s (de::Random& rnd, deUint32 count) 338{ 339 vector<float> float32; 340 341 float32.reserve(count); 342 343 // Zero 344 float32.push_back(0.f); 345 float32.push_back(-0.f); 346 // Infinity 347 float32.push_back(std::numeric_limits<float>::infinity()); 348 float32.push_back(-std::numeric_limits<float>::infinity()); 349 // SNaN 350 float32.push_back(std::numeric_limits<float>::signaling_NaN()); 351 float32.push_back(-std::numeric_limits<float>::signaling_NaN()); 352 // QNaN 353 float32.push_back(std::numeric_limits<float>::quiet_NaN()); 354 float32.push_back(-std::numeric_limits<float>::quiet_NaN()); 355 356 // Denormalized 32-bit float matching 0 in 16-bit 357 float32.push_back(deFloatLdExp(1.f, -127)); 358 float32.push_back(-deFloatLdExp(1.f, -127)); 359 360 // Normalized 32-bit float matching 0 in 16-bit 361 float32.push_back(deFloatLdExp(1.f, -100)); 362 float32.push_back(-deFloatLdExp(1.f, -100)); 363 // Normalized 32-bit float with exact denormalized match in 16-bit 364 float32.push_back(deFloatLdExp(1.f, -24)); // 2e-24: minimum 16-bit positive denormalized 365 float32.push_back(-deFloatLdExp(1.f, -24)); // 2e-24: maximum 16-bit negative denormalized 366 // Normalized 32-bit float with exact normalized match in 16-bit 367 float32.push_back(deFloatLdExp(1.f, -14)); // 2e-14: minimum 16-bit positive normalized 368 float32.push_back(-deFloatLdExp(1.f, -14)); // 2e-14: maximum 16-bit negative normalized 369 // Normalized 32-bit float falling above half way within two 16-bit normalized 370 float32.push_back(bitwiseCast<float>(deUint32(0x3880ff00))); 371 float32.push_back(bitwiseCast<float>(deUint32(0xb880ff00))); 372 // Normalized 32-bit float falling exact half way within two 16-bit normalized 373 float32.push_back(bitwiseCast<float>(deUint32(0x38803000))); 374 float32.push_back(bitwiseCast<float>(deUint32(0xb8803000))); 375 // Some number 376 float32.push_back(0.28125f); 377 float32.push_back(-0.28125f); 378 // Normalized 32-bit float matching infinity in 16-bit 379 float32.push_back(deFloatLdExp(1.f, 100)); 380 float32.push_back(-deFloatLdExp(1.f, 100)); 381 382 const deUint32 numPicks = static_cast<deUint32>(float32.size()); 383 384 DE_ASSERT(count >= numPicks); 385 count -= numPicks; 386 387 for (deUint32 numNdx = 0; numNdx < count; ++numNdx) 388 float32.push_back(rnd.getFloat()); 389 390 return float32; 391} 392 393// IEEE-754 floating point numbers: 394// +--------+------+----------+-------------+ 395// | binary | sign | exponent | significand | 396// +--------+------+----------+-------------+ 397// | 16-bit | 1 | 5 | 10 | 398// +--------+------+----------+-------------+ 399// | 32-bit | 1 | 8 | 23 | 400// +--------+------+----------+-------------+ 401// 402// 16-bit floats: 403// 404// 0 000 00 00 0000 0001 (0x0001: 2e-24: minimum positive denormalized) 405// 0 000 00 11 1111 1111 (0x03ff: 2e-14 - 2e-24: maximum positive denormalized) 406// 0 000 01 00 0000 0000 (0x0400: 2e-14: minimum positive normalized) 407// 408// 0 000 00 00 0000 0000 (0x0000: +0) 409// 0 111 11 00 0000 0000 (0x7c00: +Inf) 410// 0 000 00 11 1111 0000 (0x03f0: +Denorm) 411// 0 000 01 00 0000 0001 (0x0401: +Norm) 412// 0 111 11 00 0000 1111 (0x7c0f: +SNaN) 413// 0 111 11 00 1111 0000 (0x7c0f: +QNaN) 414 415 416// Generate and return 16-bit floats and their corresponding 32-bit values. 417// 418// The first 14 number pairs are manually picked, while the rest are randomly generated. 419// Expected count to be at least 14 (numPicks). 420vector<deFloat16> getFloat16s (de::Random& rnd, deUint32 count) 421{ 422 vector<deFloat16> float16; 423 424 float16.reserve(count); 425 426 // Zero 427 float16.push_back(deUint16(0x0000)); 428 float16.push_back(deUint16(0x8000)); 429 // Infinity 430 float16.push_back(deUint16(0x7c00)); 431 float16.push_back(deUint16(0xfc00)); 432 // SNaN 433 float16.push_back(deUint16(0x7c0f)); 434 float16.push_back(deUint16(0xfc0f)); 435 // QNaN 436 float16.push_back(deUint16(0x7cf0)); 437 float16.push_back(deUint16(0xfcf0)); 438 439 // Denormalized 440 float16.push_back(deUint16(0x03f0)); 441 float16.push_back(deUint16(0x83f0)); 442 // Normalized 443 float16.push_back(deUint16(0x0401)); 444 float16.push_back(deUint16(0x8401)); 445 // Some normal number 446 float16.push_back(deUint16(0x14cb)); 447 float16.push_back(deUint16(0x94cb)); 448 449 const deUint32 numPicks = static_cast<deUint32>(float16.size()); 450 451 DE_ASSERT(count >= numPicks); 452 count -= numPicks; 453 454 for (deUint32 numIdx = 0; numIdx < count; ++numIdx) 455 float16.push_back(rnd.getUint16()); 456 457 return float16; 458} 459 460void addCompute16bitStorageUniform16To32Group (tcu::TestCaseGroup* group) 461{ 462 tcu::TestContext& testCtx = group->getTestContext(); 463 de::Random rnd (deStringHash(group->getName())); 464 const int numElements = 128; 465 466 const StringTemplate shaderTemplate ( 467 "OpCapability Shader\n" 468 "OpCapability ${capability}\n" 469 "OpExtension \"SPV_KHR_16bit_storage\"\n" 470 "OpMemoryModel Logical GLSL450\n" 471 "OpEntryPoint GLCompute %main \"main\" %id\n" 472 "OpExecutionMode %main LocalSize 1 1 1\n" 473 "OpDecorate %id BuiltIn GlobalInvocationId\n" 474 475 "${stride}" 476 477 "OpMemberDecorate %SSBO32 0 Offset 0\n" 478 "OpMemberDecorate %SSBO16 0 Offset 0\n" 479 "OpDecorate %SSBO32 BufferBlock\n" 480 "OpDecorate %SSBO16 ${storage}\n" 481 "OpDecorate %ssbo32 DescriptorSet 0\n" 482 "OpDecorate %ssbo16 DescriptorSet 0\n" 483 "OpDecorate %ssbo32 Binding 1\n" 484 "OpDecorate %ssbo16 Binding 0\n" 485 486 "${matrix_decor:opt}\n" 487 488 "%bool = OpTypeBool\n" 489 "%void = OpTypeVoid\n" 490 "%voidf = OpTypeFunction %void\n" 491 "%u32 = OpTypeInt 32 0\n" 492 "%i32 = OpTypeInt 32 1\n" 493 "%f32 = OpTypeFloat 32\n" 494 "%uvec3 = OpTypeVector %u32 3\n" 495 "%fvec3 = OpTypeVector %f32 3\n" 496 "%uvec3ptr = OpTypePointer Input %uvec3\n" 497 "%i32ptr = OpTypePointer Uniform %i32\n" 498 "%f32ptr = OpTypePointer Uniform %f32\n" 499 500 "%zero = OpConstant %i32 0\n" 501 "%c_i32_1 = OpConstant %i32 1\n" 502 "%c_i32_2 = OpConstant %i32 2\n" 503 "%c_i32_3 = OpConstant %i32 3\n" 504 "%c_i32_16 = OpConstant %i32 16\n" 505 "%c_i32_32 = OpConstant %i32 32\n" 506 "%c_i32_64 = OpConstant %i32 64\n" 507 "%c_i32_128 = OpConstant %i32 128\n" 508 509 "%i32arr = OpTypeArray %i32 %c_i32_128\n" 510 "%f32arr = OpTypeArray %f32 %c_i32_128\n" 511 512 "${types}\n" 513 "${matrix_types:opt}\n" 514 515 "%SSBO32 = OpTypeStruct %${matrix_prefix:opt}${base32}arr\n" 516 "%SSBO16 = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n" 517 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 518 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n" 519 "%ssbo32 = OpVariable %up_SSBO32 Uniform\n" 520 "%ssbo16 = OpVariable %up_SSBO16 Uniform\n" 521 522 "%id = OpVariable %uvec3ptr Input\n" 523 524 "%main = OpFunction %void None %voidf\n" 525 "%label = OpLabel\n" 526 "%idval = OpLoad %uvec3 %id\n" 527 "%x = OpCompositeExtract %u32 %idval 0\n" 528 "%inloc = OpAccessChain %${base16}ptr %ssbo16 %zero %x ${index0:opt}\n" 529 "%val16 = OpLoad %${base16} %inloc\n" 530 "%val32 = ${convert} %${base32} %val16\n" 531 "%outloc = OpAccessChain %${base32}ptr %ssbo32 %zero %x ${index0:opt}\n" 532 " OpStore %outloc %val32\n" 533 "${matrix_store:opt}\n" 534 " OpReturn\n" 535 " OpFunctionEnd\n"); 536 537 { // floats 538 const char floatTypes[] = 539 "%f16 = OpTypeFloat 16\n" 540 "%f16ptr = OpTypePointer Uniform %f16\n" 541 "%f16arr = OpTypeArray %f16 %c_i32_128\n" 542 "%v2f16 = OpTypeVector %f16 2\n" 543 "%v2f32 = OpTypeVector %f32 2\n" 544 "%v2f16ptr = OpTypePointer Uniform %v2f16\n" 545 "%v2f32ptr = OpTypePointer Uniform %v2f32\n" 546 "%v2f16arr = OpTypeArray %v2f16 %c_i32_64\n" 547 "%v2f32arr = OpTypeArray %v2f32 %c_i32_64\n"; 548 549 struct CompositeType 550 { 551 const char* name; 552 const char* base32; 553 const char* base16; 554 const char* stride; 555 unsigned count; 556 }; 557 558 const CompositeType cTypes[] = 559 { 560 {"scalar", "f32", "f16", "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n", numElements}, 561 {"vector", "v2f32", "v2f16", "OpDecorate %v2f32arr ArrayStride 8\nOpDecorate %v2f16arr ArrayStride 4\n", numElements / 2}, 562 {"matrix", "v2f32", "v2f16", "OpDecorate %m4v2f32arr ArrayStride 32\nOpDecorate %m4v2f16arr ArrayStride 16\n", numElements / 8}, 563 }; 564 565 vector<deFloat16> float16Data = getFloat16s(rnd, numElements); 566 vector<float> float32Data; 567 568 float32Data.reserve(numElements); 569 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx) 570 float32Data.push_back(deFloat16To32(float16Data[numIdx])); 571 572 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx) 573 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx) 574 { 575 ComputeShaderSpec spec; 576 map<string, string> specs; 577 string testName = string(CAPABILITIES[capIdx].name) + "_" + cTypes[tyIdx].name + "_float"; 578 579 specs["capability"] = CAPABILITIES[capIdx].cap; 580 specs["storage"] = CAPABILITIES[capIdx].decor; 581 specs["stride"] = cTypes[tyIdx].stride; 582 specs["base32"] = cTypes[tyIdx].base32; 583 specs["base16"] = cTypes[tyIdx].base16; 584 specs["types"] = floatTypes; 585 specs["convert"] = "OpFConvert"; 586 587 if (strcmp(cTypes[tyIdx].name, "matrix") == 0) 588 { 589 specs["index0"] = "%zero"; 590 specs["matrix_prefix"] = "m4"; 591 specs["matrix_types"] = 592 "%m4v2f16 = OpTypeMatrix %v2f16 4\n" 593 "%m4v2f32 = OpTypeMatrix %v2f32 4\n" 594 "%m4v2f16arr = OpTypeArray %m4v2f16 %c_i32_16\n" 595 "%m4v2f32arr = OpTypeArray %m4v2f32 %c_i32_16\n"; 596 specs["matrix_decor"] = 597 "OpMemberDecorate %SSBO32 0 ColMajor\n" 598 "OpMemberDecorate %SSBO32 0 MatrixStride 8\n" 599 "OpMemberDecorate %SSBO16 0 ColMajor\n" 600 "OpMemberDecorate %SSBO16 0 MatrixStride 4\n"; 601 specs["matrix_store"] = 602 "%inloc_1 = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_1\n" 603 "%val16_1 = OpLoad %v2f16 %inloc_1\n" 604 "%val32_1 = OpFConvert %v2f32 %val16_1\n" 605 "%outloc_1 = OpAccessChain %v2f32ptr %ssbo32 %zero %x %c_i32_1\n" 606 " OpStore %outloc_1 %val32_1\n" 607 608 "%inloc_2 = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_2\n" 609 "%val16_2 = OpLoad %v2f16 %inloc_2\n" 610 "%val32_2 = OpFConvert %v2f32 %val16_2\n" 611 "%outloc_2 = OpAccessChain %v2f32ptr %ssbo32 %zero %x %c_i32_2\n" 612 " OpStore %outloc_2 %val32_2\n" 613 614 "%inloc_3 = OpAccessChain %v2f16ptr %ssbo16 %zero %x %c_i32_3\n" 615 "%val16_3 = OpLoad %v2f16 %inloc_3\n" 616 "%val32_3 = OpFConvert %v2f32 %val16_3\n" 617 "%outloc_3 = OpAccessChain %v2f32ptr %ssbo32 %zero %x %c_i32_3\n" 618 " OpStore %outloc_3 %val32_3\n"; 619 } 620 621 spec.assembly = shaderTemplate.specialize(specs); 622 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1); 623 spec.verifyIO = check32BitFloats; 624 spec.inputTypes[0] = CAPABILITIES[capIdx].dtype; 625 626 spec.inputs.push_back(BufferSp(new Float16Buffer(float16Data))); 627 spec.outputs.push_back(BufferSp(new Float32Buffer(float32Data))); 628 spec.extensions.push_back("VK_KHR_16bit_storage"); 629 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name); 630 631 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec)); 632 } 633 } 634 635 { // Integers 636 const char sintTypes[] = 637 "%i16 = OpTypeInt 16 1\n" 638 "%i16ptr = OpTypePointer Uniform %i16\n" 639 "%i16arr = OpTypeArray %i16 %c_i32_128\n" 640 "%v4i16 = OpTypeVector %i16 4\n" 641 "%v4i32 = OpTypeVector %i32 4\n" 642 "%v4i16ptr = OpTypePointer Uniform %v4i16\n" 643 "%v4i32ptr = OpTypePointer Uniform %v4i32\n" 644 "%v4i16arr = OpTypeArray %v4i16 %c_i32_32\n" 645 "%v4i32arr = OpTypeArray %v4i32 %c_i32_32\n"; 646 647 const char uintTypes[] = 648 "%u16 = OpTypeInt 16 0\n" 649 "%u16ptr = OpTypePointer Uniform %u16\n" 650 "%u32ptr = OpTypePointer Uniform %u32\n" 651 "%u16arr = OpTypeArray %u16 %c_i32_128\n" 652 "%u32arr = OpTypeArray %u32 %c_i32_128\n" 653 "%v4u16 = OpTypeVector %u16 4\n" 654 "%v4u32 = OpTypeVector %u32 4\n" 655 "%v4u16ptr = OpTypePointer Uniform %v4u16\n" 656 "%v4u32ptr = OpTypePointer Uniform %v4u32\n" 657 "%v4u16arr = OpTypeArray %v4u16 %c_i32_32\n" 658 "%v4u32arr = OpTypeArray %v4u32 %c_i32_32\n"; 659 660 struct CompositeType 661 { 662 const char* name; 663 bool isSigned; 664 const char* types; 665 const char* base32; 666 const char* base16; 667 const char* opcode; 668 const char* stride; 669 unsigned count; 670 }; 671 672 const CompositeType cTypes[] = 673 { 674 {"scalar_sint", true, sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n", numElements}, 675 {"scalar_uint", false, uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n", numElements}, 676 {"vector_sint", true, sintTypes, "v4i32", "v4i16", "OpSConvert", "OpDecorate %v4i32arr ArrayStride 16\nOpDecorate %v4i16arr ArrayStride 8\n", numElements / 4}, 677 {"vector_uint", false, uintTypes, "v4u32", "v4u16", "OpUConvert", "OpDecorate %v4u32arr ArrayStride 16\nOpDecorate %v4u16arr ArrayStride 8\n", numElements / 4}, 678 }; 679 680 vector<deInt16> inputs = getInt16s(rnd, numElements); 681 vector<deInt32> sOutputs; 682 vector<deInt32> uOutputs; 683 const deUint16 signBitMask = 0x8000; 684 const deUint32 signExtendMask = 0xffff0000; 685 686 sOutputs.reserve(inputs.size()); 687 uOutputs.reserve(inputs.size()); 688 689 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx) 690 { 691 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx])); 692 if (inputs[numNdx] & signBitMask) 693 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask)); 694 else 695 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx])); 696 } 697 698 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx) 699 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx) 700 { 701 ComputeShaderSpec spec; 702 map<string, string> specs; 703 string testName = string(CAPABILITIES[capIdx].name) + "_" + cTypes[tyIdx].name; 704 705 specs["capability"] = CAPABILITIES[capIdx].cap; 706 specs["storage"] = CAPABILITIES[capIdx].decor; 707 specs["stride"] = cTypes[tyIdx].stride; 708 specs["base32"] = cTypes[tyIdx].base32; 709 specs["base16"] = cTypes[tyIdx].base16; 710 specs["types"] = cTypes[tyIdx].types; 711 specs["convert"] = cTypes[tyIdx].opcode; 712 713 spec.assembly = shaderTemplate.specialize(specs); 714 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1); 715 spec.inputTypes[0] = CAPABILITIES[capIdx].dtype; 716 717 spec.inputs.push_back(BufferSp(new Int16Buffer(inputs))); 718 if (cTypes[tyIdx].isSigned) 719 spec.outputs.push_back(BufferSp(new Int32Buffer(sOutputs))); 720 else 721 spec.outputs.push_back(BufferSp(new Int32Buffer(uOutputs))); 722 spec.extensions.push_back("VK_KHR_16bit_storage"); 723 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name); 724 725 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec)); 726 } 727 } 728} 729 730void addCompute16bitStoragePushConstant16To32Group (tcu::TestCaseGroup* group) 731{ 732 tcu::TestContext& testCtx = group->getTestContext(); 733 de::Random rnd (deStringHash(group->getName())); 734 const int numElements = 64; 735 736 const StringTemplate shaderTemplate ( 737 "OpCapability Shader\n" 738 "OpCapability StoragePushConstant16\n" 739 "OpExtension \"SPV_KHR_16bit_storage\"\n" 740 "OpMemoryModel Logical GLSL450\n" 741 "OpEntryPoint GLCompute %main \"main\" %id\n" 742 "OpExecutionMode %main LocalSize 1 1 1\n" 743 "OpDecorate %id BuiltIn GlobalInvocationId\n" 744 745 "${stride}" 746 747 "OpDecorate %PC16 Block\n" 748 "OpMemberDecorate %PC16 0 Offset 0\n" 749 "OpMemberDecorate %SSBO32 0 Offset 0\n" 750 "OpDecorate %SSBO32 BufferBlock\n" 751 "OpDecorate %ssbo32 DescriptorSet 0\n" 752 "OpDecorate %ssbo32 Binding 0\n" 753 754 "${matrix_decor:opt}\n" 755 756 "%bool = OpTypeBool\n" 757 "%void = OpTypeVoid\n" 758 "%voidf = OpTypeFunction %void\n" 759 "%u32 = OpTypeInt 32 0\n" 760 "%i32 = OpTypeInt 32 1\n" 761 "%f32 = OpTypeFloat 32\n" 762 "%uvec3 = OpTypeVector %u32 3\n" 763 "%fvec3 = OpTypeVector %f32 3\n" 764 "%uvec3ptr = OpTypePointer Input %uvec3\n" 765 "%i32ptr = OpTypePointer Uniform %i32\n" 766 "%f32ptr = OpTypePointer Uniform %f32\n" 767 768 "%zero = OpConstant %i32 0\n" 769 "%c_i32_1 = OpConstant %i32 1\n" 770 "%c_i32_8 = OpConstant %i32 8\n" 771 "%c_i32_16 = OpConstant %i32 16\n" 772 "%c_i32_32 = OpConstant %i32 32\n" 773 "%c_i32_64 = OpConstant %i32 64\n" 774 775 "%i32arr = OpTypeArray %i32 %c_i32_64\n" 776 "%f32arr = OpTypeArray %f32 %c_i32_64\n" 777 778 "${types}\n" 779 "${matrix_types:opt}\n" 780 781 "%PC16 = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n" 782 "%pp_PC16 = OpTypePointer PushConstant %PC16\n" 783 "%pc16 = OpVariable %pp_PC16 PushConstant\n" 784 "%SSBO32 = OpTypeStruct %${matrix_prefix:opt}${base32}arr\n" 785 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 786 "%ssbo32 = OpVariable %up_SSBO32 Uniform\n" 787 788 "%id = OpVariable %uvec3ptr Input\n" 789 790 "%main = OpFunction %void None %voidf\n" 791 "%label = OpLabel\n" 792 "%idval = OpLoad %uvec3 %id\n" 793 "%x = OpCompositeExtract %u32 %idval 0\n" 794 "%inloc = OpAccessChain %${base16}ptr %pc16 %zero %x ${index0:opt}\n" 795 "%val16 = OpLoad %${base16} %inloc\n" 796 "%val32 = ${convert} %${base32} %val16\n" 797 "%outloc = OpAccessChain %${base32}ptr %ssbo32 %zero %x ${index0:opt}\n" 798 " OpStore %outloc %val32\n" 799 "${matrix_store:opt}\n" 800 " OpReturn\n" 801 " OpFunctionEnd\n"); 802 803 { // floats 804 const char floatTypes[] = 805 "%f16 = OpTypeFloat 16\n" 806 "%f16ptr = OpTypePointer PushConstant %f16\n" 807 "%f16arr = OpTypeArray %f16 %c_i32_64\n" 808 "%v4f16 = OpTypeVector %f16 4\n" 809 "%v4f32 = OpTypeVector %f32 4\n" 810 "%v4f16ptr = OpTypePointer PushConstant %v4f16\n" 811 "%v4f32ptr = OpTypePointer Uniform %v4f32\n" 812 "%v4f16arr = OpTypeArray %v4f16 %c_i32_16\n" 813 "%v4f32arr = OpTypeArray %v4f32 %c_i32_16\n"; 814 815 struct CompositeType 816 { 817 const char* name; 818 const char* base32; 819 const char* base16; 820 const char* stride; 821 unsigned count; 822 }; 823 824 const CompositeType cTypes[] = 825 { 826 {"scalar", "f32", "f16", "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n", numElements}, 827 {"vector", "v4f32", "v4f16", "OpDecorate %v4f32arr ArrayStride 16\nOpDecorate %v4f16arr ArrayStride 8\n", numElements / 4}, 828 {"matrix", "v4f32", "v4f16", "OpDecorate %m2v4f32arr ArrayStride 32\nOpDecorate %m2v4f16arr ArrayStride 16\n", numElements / 8}, 829 }; 830 831 vector<deFloat16> float16Data = getFloat16s(rnd, numElements); 832 vector<float> float32Data; 833 834 float32Data.reserve(numElements); 835 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx) 836 float32Data.push_back(deFloat16To32(float16Data[numIdx])); 837 838 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx) 839 { 840 ComputeShaderSpec spec; 841 map<string, string> specs; 842 string testName = string(cTypes[tyIdx].name) + "_float"; 843 844 specs["stride"] = cTypes[tyIdx].stride; 845 specs["base32"] = cTypes[tyIdx].base32; 846 specs["base16"] = cTypes[tyIdx].base16; 847 specs["types"] = floatTypes; 848 specs["convert"] = "OpFConvert"; 849 850 if (strcmp(cTypes[tyIdx].name, "matrix") == 0) 851 { 852 specs["index0"] = "%zero"; 853 specs["matrix_prefix"] = "m2"; 854 specs["matrix_types"] = 855 "%m2v4f16 = OpTypeMatrix %v4f16 2\n" 856 "%m2v4f32 = OpTypeMatrix %v4f32 2\n" 857 "%m2v4f16arr = OpTypeArray %m2v4f16 %c_i32_8\n" 858 "%m2v4f32arr = OpTypeArray %m2v4f32 %c_i32_8\n"; 859 specs["matrix_decor"] = 860 "OpMemberDecorate %SSBO32 0 ColMajor\n" 861 "OpMemberDecorate %SSBO32 0 MatrixStride 16\n" 862 "OpMemberDecorate %PC16 0 ColMajor\n" 863 "OpMemberDecorate %PC16 0 MatrixStride 8\n"; 864 specs["matrix_store"] = 865 "%inloc_1 = OpAccessChain %v4f16ptr %pc16 %zero %x %c_i32_1\n" 866 "%val16_1 = OpLoad %v4f16 %inloc_1\n" 867 "%val32_1 = OpFConvert %v4f32 %val16_1\n" 868 "%outloc_1 = OpAccessChain %v4f32ptr %ssbo32 %zero %x %c_i32_1\n" 869 " OpStore %outloc_1 %val32_1\n"; 870 } 871 872 spec.assembly = shaderTemplate.specialize(specs); 873 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1); 874 spec.verifyIO = check32BitFloats; 875 spec.pushConstants = BufferSp(new Float16Buffer(float16Data)); 876 877 spec.outputs.push_back(BufferSp(new Float32Buffer(float32Data))); 878 spec.extensions.push_back("VK_KHR_16bit_storage"); 879 spec.requestedVulkanFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT; 880 881 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec)); 882 } 883 } 884 { // integers 885 const char sintTypes[] = 886 "%i16 = OpTypeInt 16 1\n" 887 "%i16ptr = OpTypePointer PushConstant %i16\n" 888 "%i16arr = OpTypeArray %i16 %c_i32_64\n" 889 "%v2i16 = OpTypeVector %i16 2\n" 890 "%v2i32 = OpTypeVector %i32 2\n" 891 "%v2i16ptr = OpTypePointer PushConstant %v2i16\n" 892 "%v2i32ptr = OpTypePointer Uniform %v2i32\n" 893 "%v2i16arr = OpTypeArray %v2i16 %c_i32_32\n" 894 "%v2i32arr = OpTypeArray %v2i32 %c_i32_32\n"; 895 896 const char uintTypes[] = 897 "%u16 = OpTypeInt 16 0\n" 898 "%u16ptr = OpTypePointer PushConstant %u16\n" 899 "%u32ptr = OpTypePointer Uniform %u32\n" 900 "%u16arr = OpTypeArray %u16 %c_i32_64\n" 901 "%u32arr = OpTypeArray %u32 %c_i32_64\n" 902 "%v2u16 = OpTypeVector %u16 2\n" 903 "%v2u32 = OpTypeVector %u32 2\n" 904 "%v2u16ptr = OpTypePointer PushConstant %v2u16\n" 905 "%v2u32ptr = OpTypePointer Uniform %v2u32\n" 906 "%v2u16arr = OpTypeArray %v2u16 %c_i32_32\n" 907 "%v2u32arr = OpTypeArray %v2u32 %c_i32_32\n"; 908 909 struct CompositeType 910 { 911 const char* name; 912 bool isSigned; 913 const char* types; 914 const char* base32; 915 const char* base16; 916 const char* opcode; 917 const char* stride; 918 unsigned count; 919 }; 920 921 const CompositeType cTypes[] = 922 { 923 {"scalar_sint", true, sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n", numElements}, 924 {"scalar_uint", false, uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n", numElements}, 925 {"vector_sint", true, sintTypes, "v2i32", "v2i16", "OpSConvert", "OpDecorate %v2i32arr ArrayStride 8\nOpDecorate %v2i16arr ArrayStride 4\n", numElements / 2}, 926 {"vector_uint", false, uintTypes, "v2u32", "v2u16", "OpUConvert", "OpDecorate %v2u32arr ArrayStride 8\nOpDecorate %v2u16arr ArrayStride 4\n", numElements / 2}, 927 }; 928 929 vector<deInt16> inputs = getInt16s(rnd, numElements); 930 vector<deInt32> sOutputs; 931 vector<deInt32> uOutputs; 932 const deUint16 signBitMask = 0x8000; 933 const deUint32 signExtendMask = 0xffff0000; 934 935 sOutputs.reserve(inputs.size()); 936 uOutputs.reserve(inputs.size()); 937 938 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx) 939 { 940 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx])); 941 if (inputs[numNdx] & signBitMask) 942 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask)); 943 else 944 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx])); 945 } 946 947 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx) 948 { 949 ComputeShaderSpec spec; 950 map<string, string> specs; 951 const char* testName = cTypes[tyIdx].name; 952 953 specs["stride"] = cTypes[tyIdx].stride; 954 specs["base32"] = cTypes[tyIdx].base32; 955 specs["base16"] = cTypes[tyIdx].base16; 956 specs["types"] = cTypes[tyIdx].types; 957 specs["convert"] = cTypes[tyIdx].opcode; 958 959 spec.assembly = shaderTemplate.specialize(specs); 960 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1); 961 spec.pushConstants = BufferSp(new Int16Buffer(inputs)); 962 963 if (cTypes[tyIdx].isSigned) 964 spec.outputs.push_back(BufferSp(new Int32Buffer(sOutputs))); 965 else 966 spec.outputs.push_back(BufferSp(new Int32Buffer(uOutputs))); 967 spec.extensions.push_back("VK_KHR_16bit_storage"); 968 spec.requestedVulkanFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT; 969 970 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName, testName, spec)); 971 } 972 } 973} 974 975void addGraphics16BitStorageUniformInt32To16Group (tcu::TestCaseGroup* testGroup) 976{ 977 de::Random rnd (deStringHash(testGroup->getName())); 978 map<string, string> fragments; 979 const deUint32 numDataPoints = 256; 980 RGBA defaultColors[4]; 981 GraphicsResources resources; 982 vector<string> extensions; 983 const StringTemplate capabilities ("OpCapability ${cap}\n"); 984 // inputs and outputs are declared to be vectors of signed integers. 985 // However, depending on the test, they may be interpreted as unsiged 986 // integers. That won't be a problem as long as we passed the bits 987 // in faithfully to the pipeline. 988 vector<deInt32> inputs = getInt32s(rnd, numDataPoints); 989 vector<deInt16> outputs; 990 991 outputs.reserve(inputs.size()); 992 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx) 993 outputs.push_back(static_cast<deInt16>(0xffff & inputs[numNdx])); 994 995 resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Int32Buffer(inputs)))); 996 resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Int16Buffer(outputs)))); 997 998 extensions.push_back("VK_KHR_16bit_storage"); 999 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\""; 1000 1001 getDefaultColors(defaultColors); 1002 1003 struct IntegerFacts 1004 { 1005 const char* name; 1006 const char* type32; 1007 const char* type16; 1008 const char* opcode; 1009 const char* isSigned; 1010 }; 1011 1012 const IntegerFacts intFacts[] = 1013 { 1014 {"sint", "%i32", "%i16", "OpSConvert", "1"}, 1015 {"uint", "%u32", "%u16", "OpUConvert", "0"}, 1016 }; 1017 1018 const StringTemplate scalarPreMain( 1019 "${itype16} = OpTypeInt 16 ${signed}\n" 1020 "%c_i32_256 = OpConstant %i32 256\n" 1021 " %up_i32 = OpTypePointer Uniform ${itype32}\n" 1022 " %up_i16 = OpTypePointer Uniform ${itype16}\n" 1023 " %ra_i32 = OpTypeArray ${itype32} %c_i32_256\n" 1024 " %ra_i16 = OpTypeArray ${itype16} %c_i32_256\n" 1025 " %SSBO32 = OpTypeStruct %ra_i32\n" 1026 " %SSBO16 = OpTypeStruct %ra_i16\n" 1027 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 1028 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n" 1029 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 1030 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n"); 1031 1032 const StringTemplate scalarDecoration( 1033 "OpDecorate %ra_i32 ArrayStride 4\n" 1034 "OpDecorate %ra_i16 ArrayStride 2\n" 1035 "OpMemberDecorate %SSBO32 0 Offset 0\n" 1036 "OpMemberDecorate %SSBO16 0 Offset 0\n" 1037 "OpDecorate %SSBO32 ${indecor}\n" 1038 "OpDecorate %SSBO16 BufferBlock\n" 1039 "OpDecorate %ssbo32 DescriptorSet 0\n" 1040 "OpDecorate %ssbo16 DescriptorSet 0\n" 1041 "OpDecorate %ssbo32 Binding 0\n" 1042 "OpDecorate %ssbo16 Binding 1\n"); 1043 1044 const StringTemplate scalarTestFunc( 1045 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 1046 " %param = OpFunctionParameter %v4f32\n" 1047 1048 "%entry = OpLabel\n" 1049 " %i = OpVariable %fp_i32 Function\n" 1050 " OpStore %i %c_i32_0\n" 1051 " OpBranch %loop\n" 1052 1053 " %loop = OpLabel\n" 1054 " %15 = OpLoad %i32 %i\n" 1055 " %lt = OpSLessThan %bool %15 %c_i32_256\n" 1056 " OpLoopMerge %merge %inc None\n" 1057 " OpBranchConditional %lt %write %merge\n" 1058 1059 "%write = OpLabel\n" 1060 " %30 = OpLoad %i32 %i\n" 1061 " %src = OpAccessChain %up_i32 %ssbo32 %c_i32_0 %30\n" 1062 "%val32 = OpLoad ${itype32} %src\n" 1063 "%val16 = ${convert} ${itype16} %val32\n" 1064 " %dst = OpAccessChain %up_i16 %ssbo16 %c_i32_0 %30\n" 1065 " OpStore %dst %val16\n" 1066 " OpBranch %inc\n" 1067 1068 " %inc = OpLabel\n" 1069 " %37 = OpLoad %i32 %i\n" 1070 " %39 = OpIAdd %i32 %37 %c_i32_1\n" 1071 " OpStore %i %39\n" 1072 " OpBranch %loop\n" 1073 1074 "%merge = OpLabel\n" 1075 " OpReturnValue %param\n" 1076 1077 "OpFunctionEnd\n"); 1078 1079 const StringTemplate vecPreMain( 1080 "${itype16} = OpTypeInt 16 ${signed}\n" 1081 " %c_i32_64 = OpConstant %i32 64\n" 1082 "%v4itype32 = OpTypeVector ${itype32} 4\n" 1083 "%v4itype16 = OpTypeVector ${itype16} 4\n" 1084 " %up_v4i32 = OpTypePointer Uniform %v4itype32\n" 1085 " %up_v4i16 = OpTypePointer Uniform %v4itype16\n" 1086 " %ra_v4i32 = OpTypeArray %v4itype32 %c_i32_64\n" 1087 " %ra_v4i16 = OpTypeArray %v4itype16 %c_i32_64\n" 1088 " %SSBO32 = OpTypeStruct %ra_v4i32\n" 1089 " %SSBO16 = OpTypeStruct %ra_v4i16\n" 1090 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 1091 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n" 1092 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 1093 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n"); 1094 1095 const StringTemplate vecDecoration( 1096 "OpDecorate %ra_v4i32 ArrayStride 16\n" 1097 "OpDecorate %ra_v4i16 ArrayStride 8\n" 1098 "OpMemberDecorate %SSBO32 0 Offset 0\n" 1099 "OpMemberDecorate %SSBO16 0 Offset 0\n" 1100 "OpDecorate %SSBO32 ${indecor}\n" 1101 "OpDecorate %SSBO16 BufferBlock\n" 1102 "OpDecorate %ssbo32 DescriptorSet 0\n" 1103 "OpDecorate %ssbo16 DescriptorSet 0\n" 1104 "OpDecorate %ssbo32 Binding 0\n" 1105 "OpDecorate %ssbo16 Binding 1\n"); 1106 1107 const StringTemplate vecTestFunc( 1108 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 1109 " %param = OpFunctionParameter %v4f32\n" 1110 1111 "%entry = OpLabel\n" 1112 " %i = OpVariable %fp_i32 Function\n" 1113 " OpStore %i %c_i32_0\n" 1114 " OpBranch %loop\n" 1115 1116 " %loop = OpLabel\n" 1117 " %15 = OpLoad %i32 %i\n" 1118 " %lt = OpSLessThan %bool %15 %c_i32_64\n" 1119 " OpLoopMerge %merge %inc None\n" 1120 " OpBranchConditional %lt %write %merge\n" 1121 1122 "%write = OpLabel\n" 1123 " %30 = OpLoad %i32 %i\n" 1124 " %src = OpAccessChain %up_v4i32 %ssbo32 %c_i32_0 %30\n" 1125 "%val32 = OpLoad %v4itype32 %src\n" 1126 "%val16 = ${convert} %v4itype16 %val32\n" 1127 " %dst = OpAccessChain %up_v4i16 %ssbo16 %c_i32_0 %30\n" 1128 " OpStore %dst %val16\n" 1129 " OpBranch %inc\n" 1130 1131 " %inc = OpLabel\n" 1132 " %37 = OpLoad %i32 %i\n" 1133 " %39 = OpIAdd %i32 %37 %c_i32_1\n" 1134 " OpStore %i %39\n" 1135 " OpBranch %loop\n" 1136 1137 "%merge = OpLabel\n" 1138 " OpReturnValue %param\n" 1139 1140 "OpFunctionEnd\n"); 1141 1142 struct Category 1143 { 1144 const char* name; 1145 const StringTemplate& preMain; 1146 const StringTemplate& decoration; 1147 const StringTemplate& testFunction; 1148 }; 1149 1150 const Category categories[] = 1151 { 1152 {"scalar", scalarPreMain, scalarDecoration, scalarTestFunc}, 1153 {"vector", vecPreMain, vecDecoration, vecTestFunc}, 1154 }; 1155 1156 for (deUint32 catIdx = 0; catIdx < DE_LENGTH_OF_ARRAY(categories); ++catIdx) 1157 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx) 1158 for (deUint32 factIdx = 0; factIdx < DE_LENGTH_OF_ARRAY(intFacts); ++factIdx) 1159 { 1160 map<string, string> specs; 1161 string name = string(CAPABILITIES[capIdx].name) + "_" + categories[catIdx].name + "_" + intFacts[factIdx].name; 1162 1163 specs["cap"] = CAPABILITIES[capIdx].cap; 1164 specs["indecor"] = CAPABILITIES[capIdx].decor; 1165 specs["itype32"] = intFacts[factIdx].type32; 1166 specs["itype16"] = intFacts[factIdx].type16; 1167 specs["signed"] = intFacts[factIdx].isSigned; 1168 specs["convert"] = intFacts[factIdx].opcode; 1169 1170 fragments["pre_main"] = categories[catIdx].preMain.specialize(specs); 1171 fragments["testfun"] = categories[catIdx].testFunction.specialize(specs); 1172 fragments["capability"] = capabilities.specialize(specs); 1173 fragments["decoration"] = categories[catIdx].decoration.specialize(specs); 1174 1175 resources.inputs.back().first = CAPABILITIES[capIdx].dtype; 1176 1177 createTestsForAllStages(name, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name)); 1178 } 1179} 1180 1181void addCompute16bitStorageUniform32To16Group (tcu::TestCaseGroup* group) 1182{ 1183 tcu::TestContext& testCtx = group->getTestContext(); 1184 de::Random rnd (deStringHash(group->getName())); 1185 const int numElements = 128; 1186 1187 const StringTemplate shaderTemplate ( 1188 "OpCapability Shader\n" 1189 "OpCapability ${capability}\n" 1190 "OpExtension \"SPV_KHR_16bit_storage\"\n" 1191 "OpMemoryModel Logical GLSL450\n" 1192 "OpEntryPoint GLCompute %main \"main\" %id\n" 1193 "OpExecutionMode %main LocalSize 1 1 1\n" 1194 "OpDecorate %id BuiltIn GlobalInvocationId\n" 1195 1196 "${stride}" 1197 1198 "OpMemberDecorate %SSBO32 0 Offset 0\n" 1199 "OpMemberDecorate %SSBO16 0 Offset 0\n" 1200 "OpDecorate %SSBO32 ${storage}\n" 1201 "OpDecorate %SSBO16 BufferBlock\n" 1202 "OpDecorate %ssbo32 DescriptorSet 0\n" 1203 "OpDecorate %ssbo16 DescriptorSet 0\n" 1204 "OpDecorate %ssbo32 Binding 0\n" 1205 "OpDecorate %ssbo16 Binding 1\n" 1206 1207 "${matrix_decor:opt}\n" 1208 1209 "${rounding:opt}\n" 1210 1211 "%bool = OpTypeBool\n" 1212 "%void = OpTypeVoid\n" 1213 "%voidf = OpTypeFunction %void\n" 1214 "%u32 = OpTypeInt 32 0\n" 1215 "%i32 = OpTypeInt 32 1\n" 1216 "%f32 = OpTypeFloat 32\n" 1217 "%uvec3 = OpTypeVector %u32 3\n" 1218 "%fvec3 = OpTypeVector %f32 3\n" 1219 "%uvec3ptr = OpTypePointer Input %uvec3\n" 1220 "%i32ptr = OpTypePointer Uniform %i32\n" 1221 "%f32ptr = OpTypePointer Uniform %f32\n" 1222 1223 "%zero = OpConstant %i32 0\n" 1224 "%c_i32_1 = OpConstant %i32 1\n" 1225 "%c_i32_16 = OpConstant %i32 16\n" 1226 "%c_i32_32 = OpConstant %i32 32\n" 1227 "%c_i32_64 = OpConstant %i32 64\n" 1228 "%c_i32_128 = OpConstant %i32 128\n" 1229 1230 "%i32arr = OpTypeArray %i32 %c_i32_128\n" 1231 "%f32arr = OpTypeArray %f32 %c_i32_128\n" 1232 1233 "${types}\n" 1234 "${matrix_types:opt}\n" 1235 1236 "%SSBO32 = OpTypeStruct %${matrix_prefix:opt}${base32}arr\n" 1237 "%SSBO16 = OpTypeStruct %${matrix_prefix:opt}${base16}arr\n" 1238 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 1239 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n" 1240 "%ssbo32 = OpVariable %up_SSBO32 Uniform\n" 1241 "%ssbo16 = OpVariable %up_SSBO16 Uniform\n" 1242 1243 "%id = OpVariable %uvec3ptr Input\n" 1244 1245 "%main = OpFunction %void None %voidf\n" 1246 "%label = OpLabel\n" 1247 "%idval = OpLoad %uvec3 %id\n" 1248 "%x = OpCompositeExtract %u32 %idval 0\n" 1249 "%inloc = OpAccessChain %${base32}ptr %ssbo32 %zero %x ${index0:opt}\n" 1250 "%val32 = OpLoad %${base32} %inloc\n" 1251 "%val16 = ${convert} %${base16} %val32\n" 1252 "%outloc = OpAccessChain %${base16}ptr %ssbo16 %zero %x ${index0:opt}\n" 1253 " OpStore %outloc %val16\n" 1254 "${matrix_store:opt}\n" 1255 " OpReturn\n" 1256 " OpFunctionEnd\n"); 1257 1258 { // Floats 1259 const char floatTypes[] = 1260 "%f16 = OpTypeFloat 16\n" 1261 "%f16ptr = OpTypePointer Uniform %f16\n" 1262 "%f16arr = OpTypeArray %f16 %c_i32_128\n" 1263 "%v4f16 = OpTypeVector %f16 4\n" 1264 "%v4f32 = OpTypeVector %f32 4\n" 1265 "%v4f16ptr = OpTypePointer Uniform %v4f16\n" 1266 "%v4f32ptr = OpTypePointer Uniform %v4f32\n" 1267 "%v4f16arr = OpTypeArray %v4f16 %c_i32_32\n" 1268 "%v4f32arr = OpTypeArray %v4f32 %c_i32_32\n"; 1269 1270 struct RndMode 1271 { 1272 const char* name; 1273 const char* decor; 1274 ComputeVerifyIOFunc func; 1275 }; 1276 1277 const RndMode rndModes[] = 1278 { 1279 {"rtz", "OpDecorate %val16 FPRoundingMode RTZ", computeCheck16BitFloats<ROUNDINGMODE_RTZ>}, 1280 {"rte", "OpDecorate %val16 FPRoundingMode RTE", computeCheck16BitFloats<ROUNDINGMODE_RTE>}, 1281 {"unspecified_rnd_mode", "", computeCheck16BitFloats<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>}, 1282 }; 1283 1284 struct CompositeType 1285 { 1286 const char* name; 1287 const char* base32; 1288 const char* base16; 1289 const char* stride; 1290 unsigned count; 1291 }; 1292 1293 const CompositeType cTypes[] = 1294 { 1295 {"scalar", "f32", "f16", "OpDecorate %f32arr ArrayStride 4\nOpDecorate %f16arr ArrayStride 2\n", numElements}, 1296 {"vector", "v4f32", "v4f16", "OpDecorate %v4f32arr ArrayStride 16\nOpDecorate %v4f16arr ArrayStride 8\n", numElements / 4}, 1297 {"matrix", "v4f32", "v4f16", "OpDecorate %m2v4f32arr ArrayStride 32\nOpDecorate %m2v4f16arr ArrayStride 16\n", numElements / 8}, 1298 }; 1299 1300 vector<float> float32Data = getFloat32s(rnd, numElements); 1301 vector<deFloat16> float16DummyData (numElements, 0); 1302 1303 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx) 1304 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx) 1305 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx) 1306 { 1307 ComputeShaderSpec spec; 1308 map<string, string> specs; 1309 string testName = string(CAPABILITIES[capIdx].name) + "_" + cTypes[tyIdx].name + "_float_" + rndModes[rndModeIdx].name; 1310 1311 specs["capability"] = CAPABILITIES[capIdx].cap; 1312 specs["storage"] = CAPABILITIES[capIdx].decor; 1313 specs["stride"] = cTypes[tyIdx].stride; 1314 specs["base32"] = cTypes[tyIdx].base32; 1315 specs["base16"] = cTypes[tyIdx].base16; 1316 specs["rounding"] = rndModes[rndModeIdx].decor; 1317 specs["types"] = floatTypes; 1318 specs["convert"] = "OpFConvert"; 1319 1320 if (strcmp(cTypes[tyIdx].name, "matrix") == 0) 1321 { 1322 if (strcmp(rndModes[rndModeIdx].name, "rtz") == 0) 1323 specs["rounding"] += "\nOpDecorate %val16_1 FPRoundingMode RTZ\n"; 1324 else if (strcmp(rndModes[rndModeIdx].name, "rte") == 0) 1325 specs["rounding"] += "\nOpDecorate %val16_1 FPRoundingMode RTE\n"; 1326 1327 specs["index0"] = "%zero"; 1328 specs["matrix_prefix"] = "m2"; 1329 specs["matrix_types"] = 1330 "%m2v4f16 = OpTypeMatrix %v4f16 2\n" 1331 "%m2v4f32 = OpTypeMatrix %v4f32 2\n" 1332 "%m2v4f16arr = OpTypeArray %m2v4f16 %c_i32_16\n" 1333 "%m2v4f32arr = OpTypeArray %m2v4f32 %c_i32_16\n"; 1334 specs["matrix_decor"] = 1335 "OpMemberDecorate %SSBO32 0 ColMajor\n" 1336 "OpMemberDecorate %SSBO32 0 MatrixStride 16\n" 1337 "OpMemberDecorate %SSBO16 0 ColMajor\n" 1338 "OpMemberDecorate %SSBO16 0 MatrixStride 8\n"; 1339 specs["matrix_store"] = 1340 "%inloc_1 = OpAccessChain %v4f32ptr %ssbo32 %zero %x %c_i32_1\n" 1341 "%val32_1 = OpLoad %v4f32 %inloc_1\n" 1342 "%val16_1 = OpFConvert %v4f16 %val32_1\n" 1343 "%outloc_1 = OpAccessChain %v4f16ptr %ssbo16 %zero %x %c_i32_1\n" 1344 " OpStore %outloc_1 %val16_1\n"; 1345 } 1346 1347 spec.assembly = shaderTemplate.specialize(specs); 1348 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1); 1349 spec.verifyIO = rndModes[rndModeIdx].func; 1350 spec.inputTypes[0] = CAPABILITIES[capIdx].dtype; 1351 1352 spec.inputs.push_back(BufferSp(new Float32Buffer(float32Data))); 1353 // We provided a custom verifyIO in the above in which inputs will be used for checking. 1354 // So put dummy data in the expected values. 1355 spec.outputs.push_back(BufferSp(new Float16Buffer(float16DummyData))); 1356 spec.extensions.push_back("VK_KHR_16bit_storage"); 1357 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name); 1358 1359 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec)); 1360 } 1361 } 1362 1363 { // Integers 1364 const char sintTypes[] = 1365 "%i16 = OpTypeInt 16 1\n" 1366 "%i16ptr = OpTypePointer Uniform %i16\n" 1367 "%i16arr = OpTypeArray %i16 %c_i32_128\n" 1368 "%v2i16 = OpTypeVector %i16 2\n" 1369 "%v2i32 = OpTypeVector %i32 2\n" 1370 "%v2i16ptr = OpTypePointer Uniform %v2i16\n" 1371 "%v2i32ptr = OpTypePointer Uniform %v2i32\n" 1372 "%v2i16arr = OpTypeArray %v2i16 %c_i32_64\n" 1373 "%v2i32arr = OpTypeArray %v2i32 %c_i32_64\n"; 1374 1375 const char uintTypes[] = 1376 "%u16 = OpTypeInt 16 0\n" 1377 "%u16ptr = OpTypePointer Uniform %u16\n" 1378 "%u32ptr = OpTypePointer Uniform %u32\n" 1379 "%u16arr = OpTypeArray %u16 %c_i32_128\n" 1380 "%u32arr = OpTypeArray %u32 %c_i32_128\n" 1381 "%v2u16 = OpTypeVector %u16 2\n" 1382 "%v2u32 = OpTypeVector %u32 2\n" 1383 "%v2u16ptr = OpTypePointer Uniform %v2u16\n" 1384 "%v2u32ptr = OpTypePointer Uniform %v2u32\n" 1385 "%v2u16arr = OpTypeArray %v2u16 %c_i32_64\n" 1386 "%v2u32arr = OpTypeArray %v2u32 %c_i32_64\n"; 1387 1388 struct CompositeType 1389 { 1390 const char* name; 1391 const char* types; 1392 const char* base32; 1393 const char* base16; 1394 const char* opcode; 1395 const char* stride; 1396 unsigned count; 1397 }; 1398 1399 const CompositeType cTypes[] = 1400 { 1401 {"scalar_sint", sintTypes, "i32", "i16", "OpSConvert", "OpDecorate %i32arr ArrayStride 4\nOpDecorate %i16arr ArrayStride 2\n", numElements}, 1402 {"scalar_uint", uintTypes, "u32", "u16", "OpUConvert", "OpDecorate %u32arr ArrayStride 4\nOpDecorate %u16arr ArrayStride 2\n", numElements}, 1403 {"vector_sint", sintTypes, "v2i32", "v2i16", "OpSConvert", "OpDecorate %v2i32arr ArrayStride 8\nOpDecorate %v2i16arr ArrayStride 4\n", numElements / 2}, 1404 {"vector_uint", uintTypes, "v2u32", "v2u16", "OpUConvert", "OpDecorate %v2u32arr ArrayStride 8\nOpDecorate %v2u16arr ArrayStride 4\n", numElements / 2}, 1405 }; 1406 1407 vector<deInt32> inputs = getInt32s(rnd, numElements); 1408 vector<deInt16> outputs; 1409 1410 outputs.reserve(inputs.size()); 1411 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx) 1412 outputs.push_back(static_cast<deInt16>(0xffff & inputs[numNdx])); 1413 1414 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx) 1415 for (deUint32 tyIdx = 0; tyIdx < DE_LENGTH_OF_ARRAY(cTypes); ++tyIdx) 1416 { 1417 ComputeShaderSpec spec; 1418 map<string, string> specs; 1419 string testName = string(CAPABILITIES[capIdx].name) + "_" + cTypes[tyIdx].name; 1420 1421 specs["capability"] = CAPABILITIES[capIdx].cap; 1422 specs["storage"] = CAPABILITIES[capIdx].decor; 1423 specs["stride"] = cTypes[tyIdx].stride; 1424 specs["base32"] = cTypes[tyIdx].base32; 1425 specs["base16"] = cTypes[tyIdx].base16; 1426 specs["types"] = cTypes[tyIdx].types; 1427 specs["convert"] = cTypes[tyIdx].opcode; 1428 1429 spec.assembly = shaderTemplate.specialize(specs); 1430 spec.numWorkGroups = IVec3(cTypes[tyIdx].count, 1, 1); 1431 spec.inputTypes[0] = CAPABILITIES[capIdx].dtype; 1432 1433 spec.inputs.push_back(BufferSp(new Int32Buffer(inputs))); 1434 spec.outputs.push_back(BufferSp(new Int16Buffer(outputs))); 1435 spec.extensions.push_back("VK_KHR_16bit_storage"); 1436 spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name); 1437 1438 group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec)); 1439 } 1440 } 1441} 1442 1443void addGraphics16BitStorageUniformFloat32To16Group (tcu::TestCaseGroup* testGroup) 1444{ 1445 de::Random rnd (deStringHash(testGroup->getName())); 1446 map<string, string> fragments; 1447 GraphicsResources resources; 1448 vector<string> extensions; 1449 const deUint32 numDataPoints = 256; 1450 RGBA defaultColors[4]; 1451 vector<float> float32Data = getFloat32s(rnd, numDataPoints); 1452 vector<deFloat16> float16DummyData (numDataPoints, 0); 1453 const StringTemplate capabilities ("OpCapability ${cap}\n"); 1454 1455 resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(float32Data)))); 1456 // We use a custom verifyIO to check the result via computing directly from inputs; the contents in outputs do not matter. 1457 resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float16Buffer(float16DummyData)))); 1458 1459 extensions.push_back("VK_KHR_16bit_storage"); 1460 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\""; 1461 1462 struct RndMode 1463 { 1464 const char* name; 1465 const char* decor; 1466 GraphicsVerifyIOFunc f; 1467 }; 1468 1469 getDefaultColors(defaultColors); 1470 1471 { // scalar cases 1472 fragments["pre_main"] = 1473 " %f16 = OpTypeFloat 16\n" 1474 "%c_i32_256 = OpConstant %i32 256\n" 1475 " %up_f32 = OpTypePointer Uniform %f32\n" 1476 " %up_f16 = OpTypePointer Uniform %f16\n" 1477 " %ra_f32 = OpTypeArray %f32 %c_i32_256\n" 1478 " %ra_f16 = OpTypeArray %f16 %c_i32_256\n" 1479 " %SSBO32 = OpTypeStruct %ra_f32\n" 1480 " %SSBO16 = OpTypeStruct %ra_f16\n" 1481 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 1482 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n" 1483 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 1484 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n"; 1485 1486 const StringTemplate decoration ( 1487 "OpDecorate %ra_f32 ArrayStride 4\n" 1488 "OpDecorate %ra_f16 ArrayStride 2\n" 1489 "OpMemberDecorate %SSBO32 0 Offset 0\n" 1490 "OpMemberDecorate %SSBO16 0 Offset 0\n" 1491 "OpDecorate %SSBO32 ${indecor}\n" 1492 "OpDecorate %SSBO16 BufferBlock\n" 1493 "OpDecorate %ssbo32 DescriptorSet 0\n" 1494 "OpDecorate %ssbo16 DescriptorSet 0\n" 1495 "OpDecorate %ssbo32 Binding 0\n" 1496 "OpDecorate %ssbo16 Binding 1\n" 1497 "${rounddecor}\n"); 1498 1499 fragments["testfun"] = 1500 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 1501 " %param = OpFunctionParameter %v4f32\n" 1502 1503 "%entry = OpLabel\n" 1504 " %i = OpVariable %fp_i32 Function\n" 1505 " OpStore %i %c_i32_0\n" 1506 " OpBranch %loop\n" 1507 1508 " %loop = OpLabel\n" 1509 " %15 = OpLoad %i32 %i\n" 1510 " %lt = OpSLessThan %bool %15 %c_i32_256\n" 1511 " OpLoopMerge %merge %inc None\n" 1512 " OpBranchConditional %lt %write %merge\n" 1513 1514 "%write = OpLabel\n" 1515 " %30 = OpLoad %i32 %i\n" 1516 " %src = OpAccessChain %up_f32 %ssbo32 %c_i32_0 %30\n" 1517 "%val32 = OpLoad %f32 %src\n" 1518 "%val16 = OpFConvert %f16 %val32\n" 1519 " %dst = OpAccessChain %up_f16 %ssbo16 %c_i32_0 %30\n" 1520 " OpStore %dst %val16\n" 1521 " OpBranch %inc\n" 1522 1523 " %inc = OpLabel\n" 1524 " %37 = OpLoad %i32 %i\n" 1525 " %39 = OpIAdd %i32 %37 %c_i32_1\n" 1526 " OpStore %i %39\n" 1527 " OpBranch %loop\n" 1528 1529 "%merge = OpLabel\n" 1530 " OpReturnValue %param\n" 1531 1532 "OpFunctionEnd\n"; 1533 1534 const RndMode rndModes[] = 1535 { 1536 {"rtz", "OpDecorate %val16 FPRoundingMode RTZ", graphicsCheck16BitFloats<ROUNDINGMODE_RTZ>}, 1537 {"rte", "OpDecorate %val16 FPRoundingMode RTE", graphicsCheck16BitFloats<ROUNDINGMODE_RTE>}, 1538 {"unspecified_rnd_mode", "", graphicsCheck16BitFloats<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>}, 1539 }; 1540 1541 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx) 1542 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx) 1543 { 1544 map<string, string> specs; 1545 string testName = string(CAPABILITIES[capIdx].name) + "_scalar_float_" + rndModes[rndModeIdx].name; 1546 1547 specs["cap"] = CAPABILITIES[capIdx].cap; 1548 specs["indecor"] = CAPABILITIES[capIdx].decor; 1549 specs["rounddecor"] = rndModes[rndModeIdx].decor; 1550 1551 fragments["capability"] = capabilities.specialize(specs); 1552 fragments["decoration"] = decoration.specialize(specs); 1553 1554 resources.inputs.back().first = CAPABILITIES[capIdx].dtype; 1555 resources.verifyIO = rndModes[rndModeIdx].f; 1556 1557 1558 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name)); 1559 } 1560 } 1561 1562 { // vector cases 1563 fragments["pre_main"] = 1564 " %f16 = OpTypeFloat 16\n" 1565 " %c_i32_64 = OpConstant %i32 64\n" 1566 " %v4f16 = OpTypeVector %f16 4\n" 1567 " %up_v4f32 = OpTypePointer Uniform %v4f32\n" 1568 " %up_v4f16 = OpTypePointer Uniform %v4f16\n" 1569 " %ra_v4f32 = OpTypeArray %v4f32 %c_i32_64\n" 1570 " %ra_v4f16 = OpTypeArray %v4f16 %c_i32_64\n" 1571 " %SSBO32 = OpTypeStruct %ra_v4f32\n" 1572 " %SSBO16 = OpTypeStruct %ra_v4f16\n" 1573 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 1574 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n" 1575 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 1576 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n"; 1577 1578 const StringTemplate decoration ( 1579 "OpDecorate %ra_v4f32 ArrayStride 16\n" 1580 "OpDecorate %ra_v4f16 ArrayStride 8\n" 1581 "OpMemberDecorate %SSBO32 0 Offset 0\n" 1582 "OpMemberDecorate %SSBO16 0 Offset 0\n" 1583 "OpDecorate %SSBO32 ${indecor}\n" 1584 "OpDecorate %SSBO16 BufferBlock\n" 1585 "OpDecorate %ssbo32 DescriptorSet 0\n" 1586 "OpDecorate %ssbo16 DescriptorSet 0\n" 1587 "OpDecorate %ssbo32 Binding 0\n" 1588 "OpDecorate %ssbo16 Binding 1\n" 1589 "${rounddecor}\n"); 1590 1591 // ssbo16[] <- convert ssbo32[] to 16bit float 1592 fragments["testfun"] = 1593 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 1594 " %param = OpFunctionParameter %v4f32\n" 1595 1596 "%entry = OpLabel\n" 1597 " %i = OpVariable %fp_i32 Function\n" 1598 " OpStore %i %c_i32_0\n" 1599 " OpBranch %loop\n" 1600 1601 " %loop = OpLabel\n" 1602 " %15 = OpLoad %i32 %i\n" 1603 " %lt = OpSLessThan %bool %15 %c_i32_64\n" 1604 " OpLoopMerge %merge %inc None\n" 1605 " OpBranchConditional %lt %write %merge\n" 1606 1607 "%write = OpLabel\n" 1608 " %30 = OpLoad %i32 %i\n" 1609 " %src = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30\n" 1610 "%val32 = OpLoad %v4f32 %src\n" 1611 "%val16 = OpFConvert %v4f16 %val32\n" 1612 " %dst = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30\n" 1613 " OpStore %dst %val16\n" 1614 " OpBranch %inc\n" 1615 1616 " %inc = OpLabel\n" 1617 " %37 = OpLoad %i32 %i\n" 1618 " %39 = OpIAdd %i32 %37 %c_i32_1\n" 1619 " OpStore %i %39\n" 1620 " OpBranch %loop\n" 1621 1622 "%merge = OpLabel\n" 1623 " OpReturnValue %param\n" 1624 1625 "OpFunctionEnd\n"; 1626 1627 const RndMode rndModes[] = 1628 { 1629 {"rtz", "OpDecorate %val16 FPRoundingMode RTZ", graphicsCheck16BitFloats<ROUNDINGMODE_RTZ>}, 1630 {"rte", "OpDecorate %val16 FPRoundingMode RTE", graphicsCheck16BitFloats<ROUNDINGMODE_RTE>}, 1631 {"unspecified_rnd_mode", "", graphicsCheck16BitFloats<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>}, 1632 }; 1633 1634 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx) 1635 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx) 1636 { 1637 map<string, string> specs; 1638 string testName = string(CAPABILITIES[capIdx].name) + "_vector_float_" + rndModes[rndModeIdx].name; 1639 1640 specs["cap"] = CAPABILITIES[capIdx].cap; 1641 specs["indecor"] = CAPABILITIES[capIdx].decor; 1642 specs["rounddecor"] = rndModes[rndModeIdx].decor; 1643 1644 fragments["capability"] = capabilities.specialize(specs); 1645 fragments["decoration"] = decoration.specialize(specs); 1646 1647 resources.inputs.back().first = CAPABILITIES[capIdx].dtype; 1648 resources.verifyIO = rndModes[rndModeIdx].f; 1649 1650 1651 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name)); 1652 } 1653 } 1654 1655 { // matrix cases 1656 fragments["pre_main"] = 1657 " %f16 = OpTypeFloat 16\n" 1658 " %c_i32_16 = OpConstant %i32 16\n" 1659 " %v4f16 = OpTypeVector %f16 4\n" 1660 " %m4x4f32 = OpTypeMatrix %v4f32 4\n" 1661 " %m4x4f16 = OpTypeMatrix %v4f16 4\n" 1662 " %up_v4f32 = OpTypePointer Uniform %v4f32\n" 1663 " %up_v4f16 = OpTypePointer Uniform %v4f16\n" 1664 "%a16m4x4f32 = OpTypeArray %m4x4f32 %c_i32_16\n" 1665 "%a16m4x4f16 = OpTypeArray %m4x4f16 %c_i32_16\n" 1666 " %SSBO32 = OpTypeStruct %a16m4x4f32\n" 1667 " %SSBO16 = OpTypeStruct %a16m4x4f16\n" 1668 " %up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 1669 " %up_SSBO16 = OpTypePointer Uniform %SSBO16\n" 1670 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 1671 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n"; 1672 1673 const StringTemplate decoration ( 1674 "OpDecorate %a16m4x4f32 ArrayStride 64\n" 1675 "OpDecorate %a16m4x4f16 ArrayStride 32\n" 1676 "OpMemberDecorate %SSBO32 0 Offset 0\n" 1677 "OpMemberDecorate %SSBO32 0 ColMajor\n" 1678 "OpMemberDecorate %SSBO32 0 MatrixStride 16\n" 1679 "OpMemberDecorate %SSBO16 0 Offset 0\n" 1680 "OpMemberDecorate %SSBO16 0 ColMajor\n" 1681 "OpMemberDecorate %SSBO16 0 MatrixStride 8\n" 1682 "OpDecorate %SSBO32 ${indecor}\n" 1683 "OpDecorate %SSBO16 BufferBlock\n" 1684 "OpDecorate %ssbo32 DescriptorSet 0\n" 1685 "OpDecorate %ssbo16 DescriptorSet 0\n" 1686 "OpDecorate %ssbo32 Binding 0\n" 1687 "OpDecorate %ssbo16 Binding 1\n" 1688 "${rounddecor}\n"); 1689 1690 fragments["testfun"] = 1691 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 1692 " %param = OpFunctionParameter %v4f32\n" 1693 1694 "%entry = OpLabel\n" 1695 " %i = OpVariable %fp_i32 Function\n" 1696 " OpStore %i %c_i32_0\n" 1697 " OpBranch %loop\n" 1698 1699 " %loop = OpLabel\n" 1700 " %15 = OpLoad %i32 %i\n" 1701 " %lt = OpSLessThan %bool %15 %c_i32_16\n" 1702 " OpLoopMerge %merge %inc None\n" 1703 " OpBranchConditional %lt %write %merge\n" 1704 1705 " %write = OpLabel\n" 1706 " %30 = OpLoad %i32 %i\n" 1707 " %src_0 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_0\n" 1708 " %src_1 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_1\n" 1709 " %src_2 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_2\n" 1710 " %src_3 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_3\n" 1711 "%val32_0 = OpLoad %v4f32 %src_0\n" 1712 "%val32_1 = OpLoad %v4f32 %src_1\n" 1713 "%val32_2 = OpLoad %v4f32 %src_2\n" 1714 "%val32_3 = OpLoad %v4f32 %src_3\n" 1715 "%val16_0 = OpFConvert %v4f16 %val32_0\n" 1716 "%val16_1 = OpFConvert %v4f16 %val32_1\n" 1717 "%val16_2 = OpFConvert %v4f16 %val32_2\n" 1718 "%val16_3 = OpFConvert %v4f16 %val32_3\n" 1719 " %dst_0 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_0\n" 1720 " %dst_1 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_1\n" 1721 " %dst_2 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_2\n" 1722 " %dst_3 = OpAccessChain %up_v4f16 %ssbo16 %c_i32_0 %30 %c_i32_3\n" 1723 " OpStore %dst_0 %val16_0\n" 1724 " OpStore %dst_1 %val16_1\n" 1725 " OpStore %dst_2 %val16_2\n" 1726 " OpStore %dst_3 %val16_3\n" 1727 " OpBranch %inc\n" 1728 1729 " %inc = OpLabel\n" 1730 " %37 = OpLoad %i32 %i\n" 1731 " %39 = OpIAdd %i32 %37 %c_i32_1\n" 1732 " OpStore %i %39\n" 1733 " OpBranch %loop\n" 1734 1735 "%merge = OpLabel\n" 1736 " OpReturnValue %param\n" 1737 1738 "OpFunctionEnd\n"; 1739 1740 const RndMode rndModes[] = 1741 { 1742 {"rte", "OpDecorate %val16_0 FPRoundingMode RTE\nOpDecorate %val16_1 FPRoundingMode RTE\nOpDecorate %val16_2 FPRoundingMode RTE\nOpDecorate %val16_3 FPRoundingMode RTE", graphicsCheck16BitFloats<ROUNDINGMODE_RTE>}, 1743 {"rtz", "OpDecorate %val16_0 FPRoundingMode RTZ\nOpDecorate %val16_1 FPRoundingMode RTZ\nOpDecorate %val16_2 FPRoundingMode RTZ\nOpDecorate %val16_3 FPRoundingMode RTZ", graphicsCheck16BitFloats<ROUNDINGMODE_RTZ>}, 1744 {"unspecified_rnd_mode", "", graphicsCheck16BitFloats<RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)>}, 1745 }; 1746 1747 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx) 1748 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx) 1749 { 1750 map<string, string> specs; 1751 string testName = string(CAPABILITIES[capIdx].name) + "_matrix_float_" + rndModes[rndModeIdx].name; 1752 1753 specs["cap"] = CAPABILITIES[capIdx].cap; 1754 specs["indecor"] = CAPABILITIES[capIdx].decor; 1755 specs["rounddecor"] = rndModes[rndModeIdx].decor; 1756 1757 fragments["capability"] = capabilities.specialize(specs); 1758 fragments["decoration"] = decoration.specialize(specs); 1759 1760 resources.inputs.back().first = CAPABILITIES[capIdx].dtype; 1761 resources.verifyIO = rndModes[rndModeIdx].f; 1762 1763 1764 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name)); 1765 } 1766 } 1767} 1768 1769void addGraphics16BitStorageInputOutputFloat32To16Group (tcu::TestCaseGroup* testGroup) 1770{ 1771 de::Random rnd (deStringHash(testGroup->getName())); 1772 RGBA defaultColors[4]; 1773 vector<string> extensions; 1774 map<string, string> fragments = passthruFragments(); 1775 const deUint32 numDataPoints = 64; 1776 vector<float> float32Data = getFloat32s(rnd, numDataPoints); 1777 1778 extensions.push_back("VK_KHR_16bit_storage"); 1779 1780 fragments["capability"] = "OpCapability StorageInputOutput16\n"; 1781 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n"; 1782 1783 getDefaultColors(defaultColors); 1784 1785 struct RndMode 1786 { 1787 const char* name; 1788 const char* decor; 1789 RoundingModeFlags flags; 1790 }; 1791 1792 const RndMode rndModes[] = 1793 { 1794 {"rtz", "OpDecorate %ret FPRoundingMode RTZ", ROUNDINGMODE_RTZ}, 1795 {"rte", "OpDecorate %ret FPRoundingMode RTE", ROUNDINGMODE_RTE}, 1796 {"unspecified_rnd_mode", "", RoundingModeFlags(ROUNDINGMODE_RTE | ROUNDINGMODE_RTZ)}, 1797 }; 1798 1799 struct Case 1800 { 1801 const char* name; 1802 const char* interfaceOpFunc; 1803 const char* preMain; 1804 const char* inputType; 1805 const char* outputType; 1806 deUint32 numPerCase; 1807 deUint32 numElements; 1808 }; 1809 1810 const Case cases[] = 1811 { 1812 { // Scalar cases 1813 "scalar", 1814 1815 "%interface_op_func = OpFunction %f16 None %f16_f32_function\n" 1816 " %io_param1 = OpFunctionParameter %f32\n" 1817 " %entry = OpLabel\n" 1818 " %ret = OpFConvert %f16 %io_param1\n" 1819 " OpReturnValue %ret\n" 1820 " OpFunctionEnd\n", 1821 1822 " %f16 = OpTypeFloat 16\n" 1823 " %op_f16 = OpTypePointer Output %f16\n" 1824 " %a3f16 = OpTypeArray %f16 %c_i32_3\n" 1825 " %op_a3f16 = OpTypePointer Output %a3f16\n" 1826 "%f16_f32_function = OpTypeFunction %f16 %f32\n" 1827 " %a3f32 = OpTypeArray %f32 %c_i32_3\n" 1828 " %ip_a3f32 = OpTypePointer Input %a3f32\n", 1829 1830 "f32", 1831 "f16", 1832 4, 1833 1, 1834 }, 1835 { // Vector cases 1836 "vector", 1837 1838 "%interface_op_func = OpFunction %v2f16 None %v2f16_v2f32_function\n" 1839 " %io_param1 = OpFunctionParameter %v2f32\n" 1840 " %entry = OpLabel\n" 1841 " %ret = OpFConvert %v2f16 %io_param1\n" 1842 " OpReturnValue %ret\n" 1843 " OpFunctionEnd\n", 1844 1845 " %f16 = OpTypeFloat 16\n" 1846 " %v2f16 = OpTypeVector %f16 2\n" 1847 " %op_v2f16 = OpTypePointer Output %v2f16\n" 1848 " %a3v2f16 = OpTypeArray %v2f16 %c_i32_3\n" 1849 " %op_a3v2f16 = OpTypePointer Output %a3v2f16\n" 1850 "%v2f16_v2f32_function = OpTypeFunction %v2f16 %v2f32\n" 1851 " %a3v2f32 = OpTypeArray %v2f32 %c_i32_3\n" 1852 " %ip_a3v2f32 = OpTypePointer Input %a3v2f32\n", 1853 1854 "v2f32", 1855 "v2f16", 1856 2 * 4, 1857 2, 1858 } 1859 }; 1860 1861 VulkanFeatures requiredFeatures; 1862 requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT; 1863 1864 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx) 1865 for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx) 1866 { 1867 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc; 1868 fragments["pre_main"] = cases[caseIdx].preMain; 1869 fragments["decoration"] = rndModes[rndModeIdx].decor; 1870 1871 fragments["input_type"] = cases[caseIdx].inputType; 1872 fragments["output_type"] = cases[caseIdx].outputType; 1873 1874 GraphicsInterfaces interfaces; 1875 const deUint32 numPerCase = cases[caseIdx].numPerCase; 1876 vector<float> subInputs (numPerCase); 1877 vector<deFloat16> subOutputs (numPerCase); 1878 1879 // The pipeline need this to call compare16BitFloat() when checking the result. 1880 interfaces.setRoundingMode(rndModes[rndModeIdx].flags); 1881 1882 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx) 1883 { 1884 string testName = string(cases[caseIdx].name) + numberToString(caseNdx) + "_" + rndModes[rndModeIdx].name; 1885 1886 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx) 1887 { 1888 subInputs[numNdx] = float32Data[caseNdx * numPerCase + numNdx]; 1889 // We derive the expected result from inputs directly in the graphics pipeline. 1890 subOutputs[numNdx] = 0; 1891 } 1892 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT32), BufferSp(new Float32Buffer(subInputs))), 1893 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subOutputs)))); 1894 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures); 1895 } 1896 } 1897} 1898 1899void addGraphics16BitStorageInputOutputFloat16To32Group (tcu::TestCaseGroup* testGroup) 1900{ 1901 de::Random rnd (deStringHash(testGroup->getName())); 1902 RGBA defaultColors[4]; 1903 vector<string> extensions; 1904 map<string, string> fragments = passthruFragments(); 1905 const deUint32 numDataPoints = 64; 1906 vector<deFloat16> float16Data (getFloat16s(rnd, numDataPoints)); 1907 vector<float> float32Data; 1908 1909 float32Data.reserve(numDataPoints); 1910 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx) 1911 float32Data.push_back(deFloat16To32(float16Data[numIdx])); 1912 1913 extensions.push_back("VK_KHR_16bit_storage"); 1914 1915 fragments["capability"] = "OpCapability StorageInputOutput16\n"; 1916 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n"; 1917 1918 getDefaultColors(defaultColors); 1919 1920 struct Case 1921 { 1922 const char* name; 1923 const char* interfaceOpFunc; 1924 const char* preMain; 1925 const char* inputType; 1926 const char* outputType; 1927 deUint32 numPerCase; 1928 deUint32 numElements; 1929 }; 1930 1931 Case cases[] = 1932 { 1933 { // Scalar cases 1934 "scalar", 1935 1936 "%interface_op_func = OpFunction %f32 None %f32_f16_function\n" 1937 " %io_param1 = OpFunctionParameter %f16\n" 1938 " %entry = OpLabel\n" 1939 " %ret = OpFConvert %f32 %io_param1\n" 1940 " OpReturnValue %ret\n" 1941 " OpFunctionEnd\n", 1942 1943 " %f16 = OpTypeFloat 16\n" 1944 " %ip_f16 = OpTypePointer Input %f16\n" 1945 " %a3f16 = OpTypeArray %f16 %c_i32_3\n" 1946 " %ip_a3f16 = OpTypePointer Input %a3f16\n" 1947 "%f32_f16_function = OpTypeFunction %f32 %f16\n" 1948 " %a3f32 = OpTypeArray %f32 %c_i32_3\n" 1949 " %op_a3f32 = OpTypePointer Output %a3f32\n", 1950 1951 "f16", 1952 "f32", 1953 4, 1954 1, 1955 }, 1956 { // Vector cases 1957 "vector", 1958 1959 "%interface_op_func = OpFunction %v2f32 None %v2f32_v2f16_function\n" 1960 " %io_param1 = OpFunctionParameter %v2f16\n" 1961 " %entry = OpLabel\n" 1962 " %ret = OpFConvert %v2f32 %io_param1\n" 1963 " OpReturnValue %ret\n" 1964 " OpFunctionEnd\n", 1965 1966 " %f16 = OpTypeFloat 16\n" 1967 " %v2f16 = OpTypeVector %f16 2\n" 1968 " %ip_v2f16 = OpTypePointer Input %v2f16\n" 1969 " %a3v2f16 = OpTypeArray %v2f16 %c_i32_3\n" 1970 " %ip_a3v2f16 = OpTypePointer Input %a3v2f16\n" 1971 "%v2f32_v2f16_function = OpTypeFunction %v2f32 %v2f16\n" 1972 " %a3v2f32 = OpTypeArray %v2f32 %c_i32_3\n" 1973 " %op_a3v2f32 = OpTypePointer Output %a3v2f32\n", 1974 1975 "v2f16", 1976 "v2f32", 1977 2 * 4, 1978 2, 1979 } 1980 }; 1981 1982 VulkanFeatures requiredFeatures; 1983 requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT; 1984 1985 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx) 1986 { 1987 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc; 1988 fragments["pre_main"] = cases[caseIdx].preMain; 1989 1990 fragments["input_type"] = cases[caseIdx].inputType; 1991 fragments["output_type"] = cases[caseIdx].outputType; 1992 1993 GraphicsInterfaces interfaces; 1994 const deUint32 numPerCase = cases[caseIdx].numPerCase; 1995 vector<deFloat16> subInputs (numPerCase); 1996 vector<float> subOutputs (numPerCase); 1997 1998 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx) 1999 { 2000 string testName = string(cases[caseIdx].name) + numberToString(caseNdx); 2001 2002 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx) 2003 { 2004 subInputs[numNdx] = float16Data[caseNdx * numPerCase + numNdx]; 2005 subOutputs[numNdx] = float32Data[caseNdx * numPerCase + numNdx]; 2006 } 2007 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subInputs))), 2008 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT32), BufferSp(new Float32Buffer(subOutputs)))); 2009 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures); 2010 } 2011 } 2012} 2013 2014void addGraphics16BitStorageInputOutputInt32To16Group (tcu::TestCaseGroup* testGroup) 2015{ 2016 de::Random rnd (deStringHash(testGroup->getName())); 2017 RGBA defaultColors[4]; 2018 vector<string> extensions; 2019 map<string, string> fragments = passthruFragments(); 2020 const deUint32 numDataPoints = 64; 2021 // inputs and outputs are declared to be vectors of signed integers. 2022 // However, depending on the test, they may be interpreted as unsiged 2023 // integers. That won't be a problem as long as we passed the bits 2024 // in faithfully to the pipeline. 2025 vector<deInt32> inputs = getInt32s(rnd, numDataPoints); 2026 vector<deInt16> outputs; 2027 2028 outputs.reserve(inputs.size()); 2029 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx) 2030 outputs.push_back(static_cast<deInt16>(0xffff & inputs[numNdx])); 2031 2032 extensions.push_back("VK_KHR_16bit_storage"); 2033 2034 fragments["capability"] = "OpCapability StorageInputOutput16\n"; 2035 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n"; 2036 2037 getDefaultColors(defaultColors); 2038 2039 const StringTemplate scalarInterfaceOpFunc( 2040 "%interface_op_func = OpFunction %${type16} None %${type16}_${type32}_function\n" 2041 " %io_param1 = OpFunctionParameter %${type32}\n" 2042 " %entry = OpLabel\n" 2043 " %ret = ${convert} %${type16} %io_param1\n" 2044 " OpReturnValue %ret\n" 2045 " OpFunctionEnd\n"); 2046 2047 const StringTemplate scalarPreMain( 2048 " %${type16} = OpTypeInt 16 ${signed}\n" 2049 " %op_${type16} = OpTypePointer Output %${type16}\n" 2050 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n" 2051 " %op_a3${type16} = OpTypePointer Output %a3${type16}\n" 2052 "%${type16}_${type32}_function = OpTypeFunction %${type16} %${type32}\n" 2053 " %a3${type32} = OpTypeArray %${type32} %c_i32_3\n" 2054 " %ip_a3${type32} = OpTypePointer Input %a3${type32}\n"); 2055 2056 const StringTemplate vecInterfaceOpFunc( 2057 "%interface_op_func = OpFunction %${type16} None %${type16}_${type32}_function\n" 2058 " %io_param1 = OpFunctionParameter %${type32}\n" 2059 " %entry = OpLabel\n" 2060 " %ret = ${convert} %${type16} %io_param1\n" 2061 " OpReturnValue %ret\n" 2062 " OpFunctionEnd\n"); 2063 2064 const StringTemplate vecPreMain( 2065 " %i16 = OpTypeInt 16 1\n" 2066 " %u16 = OpTypeInt 16 0\n" 2067 " %v4i16 = OpTypeVector %i16 4\n" 2068 " %v4u16 = OpTypeVector %u16 4\n" 2069 " %op_${type16} = OpTypePointer Output %${type16}\n" 2070 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n" 2071 " %op_a3${type16} = OpTypePointer Output %a3${type16}\n" 2072 "%${type16}_${type32}_function = OpTypeFunction %${type16} %${type32}\n" 2073 " %a3${type32} = OpTypeArray %${type32} %c_i32_3\n" 2074 " %ip_a3${type32} = OpTypePointer Input %a3${type32}\n"); 2075 2076 struct Case 2077 { 2078 const char* name; 2079 const StringTemplate& interfaceOpFunc; 2080 const StringTemplate& preMain; 2081 const char* type32; 2082 const char* type16; 2083 const char* sign; 2084 const char* opcode; 2085 deUint32 numPerCase; 2086 deUint32 numElements; 2087 }; 2088 2089 Case cases[] = 2090 { 2091 {"scalar_sint", scalarInterfaceOpFunc, scalarPreMain, "i32", "i16", "1", "OpSConvert", 4, 1}, 2092 {"scalar_uint", scalarInterfaceOpFunc, scalarPreMain, "u32", "u16", "0", "OpUConvert", 4, 1}, 2093 {"vector_sint", vecInterfaceOpFunc, vecPreMain, "v4i32", "v4i16", "1", "OpSConvert", 4 * 4, 4}, 2094 {"vector_uint", vecInterfaceOpFunc, vecPreMain, "v4u32", "v4u16", "0", "OpUConvert", 4 * 4, 4}, 2095 }; 2096 2097 VulkanFeatures requiredFeatures; 2098 requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT; 2099 2100 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx) 2101 { 2102 map<string, string> specs; 2103 2104 specs["type32"] = cases[caseIdx].type32; 2105 specs["type16"] = cases[caseIdx].type16; 2106 specs["signed"] = cases[caseIdx].sign; 2107 specs["convert"] = cases[caseIdx].opcode; 2108 2109 fragments["pre_main"] = cases[caseIdx].preMain.specialize(specs); 2110 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc.specialize(specs); 2111 fragments["input_type"] = cases[caseIdx].type32; 2112 fragments["output_type"] = cases[caseIdx].type16; 2113 2114 GraphicsInterfaces interfaces; 2115 const deUint32 numPerCase = cases[caseIdx].numPerCase; 2116 vector<deInt32> subInputs (numPerCase); 2117 vector<deInt16> subOutputs (numPerCase); 2118 2119 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx) 2120 { 2121 string testName = string(cases[caseIdx].name) + numberToString(caseNdx); 2122 2123 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx) 2124 { 2125 subInputs[numNdx] = inputs[caseNdx * numPerCase + numNdx]; 2126 subOutputs[numNdx] = outputs[caseNdx * numPerCase + numNdx]; 2127 } 2128 if (strcmp(cases[caseIdx].sign, "1") == 0) 2129 { 2130 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT32), BufferSp(new Int32Buffer(subInputs))), 2131 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT16), BufferSp(new Int16Buffer(subOutputs)))); 2132 } 2133 else 2134 { 2135 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT32), BufferSp(new Int32Buffer(subInputs))), 2136 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT16), BufferSp(new Int16Buffer(subOutputs)))); 2137 } 2138 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures); 2139 } 2140 } 2141} 2142 2143void addGraphics16BitStorageInputOutputInt16To32Group (tcu::TestCaseGroup* testGroup) 2144{ 2145 de::Random rnd (deStringHash(testGroup->getName())); 2146 RGBA defaultColors[4]; 2147 vector<string> extensions; 2148 map<string, string> fragments = passthruFragments(); 2149 const deUint32 numDataPoints = 64; 2150 // inputs and outputs are declared to be vectors of signed integers. 2151 // However, depending on the test, they may be interpreted as unsiged 2152 // integers. That won't be a problem as long as we passed the bits 2153 // in faithfully to the pipeline. 2154 vector<deInt16> inputs = getInt16s(rnd, numDataPoints); 2155 vector<deInt32> sOutputs; 2156 vector<deInt32> uOutputs; 2157 const deUint16 signBitMask = 0x8000; 2158 const deUint32 signExtendMask = 0xffff0000; 2159 2160 sOutputs.reserve(inputs.size()); 2161 uOutputs.reserve(inputs.size()); 2162 2163 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx) 2164 { 2165 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx])); 2166 if (inputs[numNdx] & signBitMask) 2167 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask)); 2168 else 2169 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx])); 2170 } 2171 2172 extensions.push_back("VK_KHR_16bit_storage"); 2173 2174 fragments["capability"] = "OpCapability StorageInputOutput16\n"; 2175 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"\n"; 2176 2177 getDefaultColors(defaultColors); 2178 2179 const StringTemplate scalarIfOpFunc ( 2180 "%interface_op_func = OpFunction %${type32} None %${type32}_${type16}_function\n" 2181 " %io_param1 = OpFunctionParameter %${type16}\n" 2182 " %entry = OpLabel\n" 2183 " %ret = ${convert} %${type32} %io_param1\n" 2184 " OpReturnValue %ret\n" 2185 " OpFunctionEnd\n"); 2186 2187 const StringTemplate scalarPreMain ( 2188 " %${type16} = OpTypeInt 16 ${signed}\n" 2189 " %ip_${type16} = OpTypePointer Input %${type16}\n" 2190 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n" 2191 " %ip_a3${type16} = OpTypePointer Input %a3${type16}\n" 2192 "%${type32}_${type16}_function = OpTypeFunction %${type32} %${type16}\n" 2193 " %a3${type32} = OpTypeArray %${type32} %c_i32_3\n" 2194 " %op_a3${type32} = OpTypePointer Output %a3${type32}\n"); 2195 2196 const StringTemplate vecIfOpFunc ( 2197 "%interface_op_func = OpFunction %${type32} None %${type32}_${type16}_function\n" 2198 " %io_param1 = OpFunctionParameter %${type16}\n" 2199 " %entry = OpLabel\n" 2200 " %ret = ${convert} %${type32} %io_param1\n" 2201 " OpReturnValue %ret\n" 2202 " OpFunctionEnd\n"); 2203 2204 const StringTemplate vecPreMain ( 2205 " %i16 = OpTypeInt 16 1\n" 2206 " %u16 = OpTypeInt 16 0\n" 2207 " %v4i16 = OpTypeVector %i16 4\n" 2208 " %v4u16 = OpTypeVector %u16 4\n" 2209 " %ip_${type16} = OpTypePointer Input %${type16}\n" 2210 " %a3${type16} = OpTypeArray %${type16} %c_i32_3\n" 2211 " %ip_a3${type16} = OpTypePointer Input %a3${type16}\n" 2212 "%${type32}_${type16}_function = OpTypeFunction %${type32} %${type16}\n" 2213 " %a3${type32} = OpTypeArray %${type32} %c_i32_3\n" 2214 " %op_a3${type32} = OpTypePointer Output %a3${type32}\n"); 2215 2216 struct Case 2217 { 2218 const char* name; 2219 const StringTemplate& interfaceOpFunc; 2220 const StringTemplate& preMain; 2221 const char* type32; 2222 const char* type16; 2223 const char* sign; 2224 const char* opcode; 2225 deUint32 numPerCase; 2226 deUint32 numElements; 2227 }; 2228 2229 Case cases[] = 2230 { 2231 {"scalar_sint", scalarIfOpFunc, scalarPreMain, "i32", "i16", "1", "OpSConvert", 4, 1}, 2232 {"scalar_uint", scalarIfOpFunc, scalarPreMain, "u32", "u16", "0", "OpUConvert", 4, 1}, 2233 {"vector_sint", vecIfOpFunc, vecPreMain, "v4i32", "v4i16", "1", "OpSConvert", 4 * 4, 4}, 2234 {"vector_uint", vecIfOpFunc, vecPreMain, "v4u32", "v4u16", "0", "OpUConvert", 4 * 4, 4}, 2235 }; 2236 2237 VulkanFeatures requiredFeatures; 2238 requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT; 2239 2240 for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx) 2241 { 2242 map<string, string> specs; 2243 2244 specs["type32"] = cases[caseIdx].type32; 2245 specs["type16"] = cases[caseIdx].type16; 2246 specs["signed"] = cases[caseIdx].sign; 2247 specs["convert"] = cases[caseIdx].opcode; 2248 2249 fragments["pre_main"] = cases[caseIdx].preMain.specialize(specs); 2250 fragments["interface_op_func"] = cases[caseIdx].interfaceOpFunc.specialize(specs); 2251 fragments["input_type"] = cases[caseIdx].type16; 2252 fragments["output_type"] = cases[caseIdx].type32; 2253 2254 GraphicsInterfaces interfaces; 2255 const deUint32 numPerCase = cases[caseIdx].numPerCase; 2256 vector<deInt16> subInputs (numPerCase); 2257 vector<deInt32> subOutputs (numPerCase); 2258 2259 for (deUint32 caseNdx = 0; caseNdx < numDataPoints / numPerCase; ++caseNdx) 2260 { 2261 string testName = string(cases[caseIdx].name) + numberToString(caseNdx); 2262 2263 for (deUint32 numNdx = 0; numNdx < numPerCase; ++numNdx) 2264 { 2265 subInputs[numNdx] = inputs[caseNdx * numPerCase + numNdx]; 2266 if (cases[caseIdx].sign[0] == '1') 2267 subOutputs[numNdx] = sOutputs[caseNdx * numPerCase + numNdx]; 2268 else 2269 subOutputs[numNdx] = uOutputs[caseNdx * numPerCase + numNdx]; 2270 } 2271 if (strcmp(cases[caseIdx].sign, "1") == 0) 2272 { 2273 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT16), BufferSp(new Int16Buffer(subInputs))), 2274 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_INT32), BufferSp(new Int32Buffer(subOutputs)))); 2275 } 2276 else 2277 { 2278 interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT16), BufferSp(new Int16Buffer(subInputs))), 2279 std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT32), BufferSp(new Int32Buffer(subOutputs)))); 2280 } 2281 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures); 2282 } 2283 } 2284} 2285 2286void addGraphics16BitStoragePushConstantFloat16To32Group (tcu::TestCaseGroup* testGroup) 2287{ 2288 de::Random rnd (deStringHash(testGroup->getName())); 2289 map<string, string> fragments; 2290 RGBA defaultColors[4]; 2291 vector<string> extensions; 2292 GraphicsResources resources; 2293 PushConstants pcs; 2294 const deUint32 numDataPoints = 64; 2295 vector<deFloat16> float16Data (getFloat16s(rnd, numDataPoints)); 2296 vector<float> float32Data; 2297 VulkanFeatures requiredFeatures; 2298 2299 float32Data.reserve(numDataPoints); 2300 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx) 2301 float32Data.push_back(deFloat16To32(float16Data[numIdx])); 2302 2303 extensions.push_back("VK_KHR_16bit_storage"); 2304 requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT; 2305 2306 fragments["capability"] = "OpCapability StoragePushConstant16\n"; 2307 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\""; 2308 2309 pcs.setPushConstant(BufferSp(new Float16Buffer(float16Data))); 2310 resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(float32Data)))); 2311 resources.verifyIO = check32BitFloats; 2312 2313 getDefaultColors(defaultColors); 2314 2315 const StringTemplate testFun ( 2316 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 2317 " %param = OpFunctionParameter %v4f32\n" 2318 2319 "%entry = OpLabel\n" 2320 " %i = OpVariable %fp_i32 Function\n" 2321 " OpStore %i %c_i32_0\n" 2322 " OpBranch %loop\n" 2323 2324 " %loop = OpLabel\n" 2325 " %15 = OpLoad %i32 %i\n" 2326 " %lt = OpSLessThan %bool %15 ${count}\n" 2327 " OpLoopMerge %merge %inc None\n" 2328 " OpBranchConditional %lt %write %merge\n" 2329 2330 "%write = OpLabel\n" 2331 " %30 = OpLoad %i32 %i\n" 2332 " %src = OpAccessChain ${pp_type16} %pc16 %c_i32_0 %30 ${index0:opt}\n" 2333 "%val16 = OpLoad ${f_type16} %src\n" 2334 "%val32 = OpFConvert ${f_type32} %val16\n" 2335 " %dst = OpAccessChain ${up_type32} %ssbo32 %c_i32_0 %30 ${index0:opt}\n" 2336 " OpStore %dst %val32\n" 2337 2338 "${store:opt}\n" 2339 2340 " OpBranch %inc\n" 2341 2342 " %inc = OpLabel\n" 2343 " %37 = OpLoad %i32 %i\n" 2344 " %39 = OpIAdd %i32 %37 %c_i32_1\n" 2345 " OpStore %i %39\n" 2346 " OpBranch %loop\n" 2347 2348 "%merge = OpLabel\n" 2349 " OpReturnValue %param\n" 2350 2351 "OpFunctionEnd\n"); 2352 2353 { // Scalar cases 2354 fragments["pre_main"] = 2355 " %f16 = OpTypeFloat 16\n" 2356 " %c_i32_64 = OpConstant %i32 64\n" // Should be the same as numDataPoints 2357 " %a64f16 = OpTypeArray %f16 %c_i32_64\n" 2358 " %a64f32 = OpTypeArray %f32 %c_i32_64\n" 2359 " %pp_f16 = OpTypePointer PushConstant %f16\n" 2360 " %up_f32 = OpTypePointer Uniform %f32\n" 2361 " %SSBO32 = OpTypeStruct %a64f32\n" 2362 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 2363 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 2364 " %PC16 = OpTypeStruct %a64f16\n" 2365 " %pp_PC16 = OpTypePointer PushConstant %PC16\n" 2366 " %pc16 = OpVariable %pp_PC16 PushConstant\n"; 2367 2368 fragments["decoration"] = 2369 "OpDecorate %a64f16 ArrayStride 2\n" 2370 "OpDecorate %a64f32 ArrayStride 4\n" 2371 "OpDecorate %SSBO32 BufferBlock\n" 2372 "OpMemberDecorate %SSBO32 0 Offset 0\n" 2373 "OpDecorate %PC16 Block\n" 2374 "OpMemberDecorate %PC16 0 Offset 0\n" 2375 "OpDecorate %ssbo32 DescriptorSet 0\n" 2376 "OpDecorate %ssbo32 Binding 0\n"; 2377 2378 map<string, string> specs; 2379 2380 specs["count"] = "%c_i32_64"; 2381 specs["pp_type16"] = "%pp_f16"; 2382 specs["f_type16"] = "%f16"; 2383 specs["f_type32"] = "%f32"; 2384 specs["up_type32"] = "%up_f32"; 2385 2386 fragments["testfun"] = testFun.specialize(specs); 2387 2388 createTestsForAllStages("scalar", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures); 2389 } 2390 2391 { // Vector cases 2392 fragments["pre_main"] = 2393 " %f16 = OpTypeFloat 16\n" 2394 " %v4f16 = OpTypeVector %f16 4\n" 2395 " %c_i32_16 = OpConstant %i32 16\n" 2396 " %a16v4f16 = OpTypeArray %v4f16 %c_i32_16\n" 2397 " %a16v4f32 = OpTypeArray %v4f32 %c_i32_16\n" 2398 " %pp_v4f16 = OpTypePointer PushConstant %v4f16\n" 2399 " %up_v4f32 = OpTypePointer Uniform %v4f32\n" 2400 " %SSBO32 = OpTypeStruct %a16v4f32\n" 2401 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 2402 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 2403 " %PC16 = OpTypeStruct %a16v4f16\n" 2404 " %pp_PC16 = OpTypePointer PushConstant %PC16\n" 2405 " %pc16 = OpVariable %pp_PC16 PushConstant\n"; 2406 2407 fragments["decoration"] = 2408 "OpDecorate %a16v4f16 ArrayStride 8\n" 2409 "OpDecorate %a16v4f32 ArrayStride 16\n" 2410 "OpDecorate %SSBO32 BufferBlock\n" 2411 "OpMemberDecorate %SSBO32 0 Offset 0\n" 2412 "OpDecorate %PC16 Block\n" 2413 "OpMemberDecorate %PC16 0 Offset 0\n" 2414 "OpDecorate %ssbo32 DescriptorSet 0\n" 2415 "OpDecorate %ssbo32 Binding 0\n"; 2416 2417 map<string, string> specs; 2418 2419 specs["count"] = "%c_i32_16"; 2420 specs["pp_type16"] = "%pp_v4f16"; 2421 specs["f_type16"] = "%v4f16"; 2422 specs["f_type32"] = "%v4f32"; 2423 specs["up_type32"] = "%up_v4f32"; 2424 2425 fragments["testfun"] = testFun.specialize(specs); 2426 2427 createTestsForAllStages("vector", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures); 2428 } 2429 2430 { // Matrix cases 2431 fragments["pre_main"] = 2432 " %c_i32_8 = OpConstant %i32 8\n" 2433 " %f16 = OpTypeFloat 16\n" 2434 " %v4f16 = OpTypeVector %f16 4\n" 2435 " %m2v4f16 = OpTypeMatrix %v4f16 2\n" 2436 " %m2v4f32 = OpTypeMatrix %v4f32 2\n" 2437 "%a8m2v4f16 = OpTypeArray %m2v4f16 %c_i32_8\n" 2438 "%a8m2v4f32 = OpTypeArray %m2v4f32 %c_i32_8\n" 2439 " %pp_v4f16 = OpTypePointer PushConstant %v4f16\n" 2440 " %up_v4f32 = OpTypePointer Uniform %v4f32\n" 2441 " %SSBO32 = OpTypeStruct %a8m2v4f32\n" 2442 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 2443 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 2444 " %PC16 = OpTypeStruct %a8m2v4f16\n" 2445 " %pp_PC16 = OpTypePointer PushConstant %PC16\n" 2446 " %pc16 = OpVariable %pp_PC16 PushConstant\n"; 2447 2448 fragments["decoration"] = 2449 "OpDecorate %a8m2v4f16 ArrayStride 16\n" 2450 "OpDecorate %a8m2v4f32 ArrayStride 32\n" 2451 "OpDecorate %SSBO32 BufferBlock\n" 2452 "OpMemberDecorate %SSBO32 0 Offset 0\n" 2453 "OpMemberDecorate %SSBO32 0 ColMajor\n" 2454 "OpMemberDecorate %SSBO32 0 MatrixStride 16\n" 2455 "OpDecorate %PC16 Block\n" 2456 "OpMemberDecorate %PC16 0 Offset 0\n" 2457 "OpMemberDecorate %PC16 0 ColMajor\n" 2458 "OpMemberDecorate %PC16 0 MatrixStride 8\n" 2459 "OpDecorate %ssbo32 DescriptorSet 0\n" 2460 "OpDecorate %ssbo32 Binding 0\n"; 2461 2462 map<string, string> specs; 2463 2464 specs["count"] = "%c_i32_8"; 2465 specs["pp_type16"] = "%pp_v4f16"; 2466 specs["up_type32"] = "%up_v4f32"; 2467 specs["f_type16"] = "%v4f16"; 2468 specs["f_type32"] = "%v4f32"; 2469 specs["index0"] = "%c_i32_0"; 2470 specs["store"] = 2471 " %src_1 = OpAccessChain %pp_v4f16 %pc16 %c_i32_0 %30 %c_i32_1\n" 2472 "%val16_1 = OpLoad %v4f16 %src_1\n" 2473 "%val32_1 = OpFConvert %v4f32 %val16_1\n" 2474 " %dst_1 = OpAccessChain %up_v4f32 %ssbo32 %c_i32_0 %30 %c_i32_1\n" 2475 " OpStore %dst_1 %val32_1\n"; 2476 2477 fragments["testfun"] = testFun.specialize(specs); 2478 2479 createTestsForAllStages("matrix", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures); 2480 } 2481} 2482 2483void addGraphics16BitStoragePushConstantInt16To32Group (tcu::TestCaseGroup* testGroup) 2484{ 2485 de::Random rnd (deStringHash(testGroup->getName())); 2486 map<string, string> fragments; 2487 RGBA defaultColors[4]; 2488 const deUint32 numDataPoints = 64; 2489 vector<deInt16> inputs = getInt16s(rnd, numDataPoints); 2490 vector<deInt32> sOutputs; 2491 vector<deInt32> uOutputs; 2492 PushConstants pcs; 2493 GraphicsResources resources; 2494 vector<string> extensions; 2495 const deUint16 signBitMask = 0x8000; 2496 const deUint32 signExtendMask = 0xffff0000; 2497 VulkanFeatures requiredFeatures; 2498 2499 sOutputs.reserve(inputs.size()); 2500 uOutputs.reserve(inputs.size()); 2501 2502 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx) 2503 { 2504 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx])); 2505 if (inputs[numNdx] & signBitMask) 2506 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask)); 2507 else 2508 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx])); 2509 } 2510 2511 extensions.push_back("VK_KHR_16bit_storage"); 2512 requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT; 2513 2514 fragments["capability"] = "OpCapability StoragePushConstant16\n"; 2515 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\""; 2516 2517 pcs.setPushConstant(BufferSp(new Int16Buffer(inputs))); 2518 2519 getDefaultColors(defaultColors); 2520 2521 const StringTemplate testFun ( 2522 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 2523 " %param = OpFunctionParameter %v4f32\n" 2524 2525 "%entry = OpLabel\n" 2526 " %i = OpVariable %fp_i32 Function\n" 2527 " OpStore %i %c_i32_0\n" 2528 " OpBranch %loop\n" 2529 2530 " %loop = OpLabel\n" 2531 " %15 = OpLoad %i32 %i\n" 2532 " %lt = OpSLessThan %bool %15 %c_i32_${count}\n" 2533 " OpLoopMerge %merge %inc None\n" 2534 " OpBranchConditional %lt %write %merge\n" 2535 2536 "%write = OpLabel\n" 2537 " %30 = OpLoad %i32 %i\n" 2538 " %src = OpAccessChain %pp_${type16} %pc16 %c_i32_0 %30\n" 2539 "%val16 = OpLoad %${type16} %src\n" 2540 "%val32 = ${convert} %${type32} %val16\n" 2541 " %dst = OpAccessChain %up_${type32} %ssbo32 %c_i32_0 %30\n" 2542 " OpStore %dst %val32\n" 2543 " OpBranch %inc\n" 2544 2545 " %inc = OpLabel\n" 2546 " %37 = OpLoad %i32 %i\n" 2547 " %39 = OpIAdd %i32 %37 %c_i32_1\n" 2548 " OpStore %i %39\n" 2549 " OpBranch %loop\n" 2550 2551 "%merge = OpLabel\n" 2552 " OpReturnValue %param\n" 2553 2554 "OpFunctionEnd\n"); 2555 2556 { // Scalar cases 2557 const StringTemplate preMain ( 2558 " %${type16} = OpTypeInt 16 ${signed}\n" 2559 " %c_i32_${count} = OpConstant %i32 ${count}\n" // Should be the same as numDataPoints 2560 "%a${count}${type16} = OpTypeArray %${type16} %c_i32_${count}\n" 2561 "%a${count}${type32} = OpTypeArray %${type32} %c_i32_${count}\n" 2562 " %pp_${type16} = OpTypePointer PushConstant %${type16}\n" 2563 " %up_${type32} = OpTypePointer Uniform %${type32}\n" 2564 " %SSBO32 = OpTypeStruct %a${count}${type32}\n" 2565 " %up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 2566 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 2567 " %PC16 = OpTypeStruct %a${count}${type16}\n" 2568 " %pp_PC16 = OpTypePointer PushConstant %PC16\n" 2569 " %pc16 = OpVariable %pp_PC16 PushConstant\n"); 2570 2571 const StringTemplate decoration ( 2572 "OpDecorate %a${count}${type16} ArrayStride 2\n" 2573 "OpDecorate %a${count}${type32} ArrayStride 4\n" 2574 "OpDecorate %SSBO32 BufferBlock\n" 2575 "OpMemberDecorate %SSBO32 0 Offset 0\n" 2576 "OpDecorate %PC16 Block\n" 2577 "OpMemberDecorate %PC16 0 Offset 0\n" 2578 "OpDecorate %ssbo32 DescriptorSet 0\n" 2579 "OpDecorate %ssbo32 Binding 0\n"); 2580 2581 { // signed int 2582 map<string, string> specs; 2583 2584 specs["type16"] = "i16"; 2585 specs["type32"] = "i32"; 2586 specs["signed"] = "1"; 2587 specs["count"] = "64"; 2588 specs["convert"] = "OpSConvert"; 2589 2590 fragments["testfun"] = testFun.specialize(specs); 2591 fragments["pre_main"] = preMain.specialize(specs); 2592 fragments["decoration"] = decoration.specialize(specs); 2593 2594 resources.outputs.clear(); 2595 resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Int32Buffer(sOutputs)))); 2596 createTestsForAllStages("sint_scalar", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures); 2597 } 2598 { // signed int 2599 map<string, string> specs; 2600 2601 specs["type16"] = "u16"; 2602 specs["type32"] = "u32"; 2603 specs["signed"] = "0"; 2604 specs["count"] = "64"; 2605 specs["convert"] = "OpUConvert"; 2606 2607 fragments["testfun"] = testFun.specialize(specs); 2608 fragments["pre_main"] = preMain.specialize(specs); 2609 fragments["decoration"] = decoration.specialize(specs); 2610 2611 resources.outputs.clear(); 2612 resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Int32Buffer(uOutputs)))); 2613 createTestsForAllStages("uint_scalar", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures); 2614 } 2615 } 2616 2617 { // Vector cases 2618 const StringTemplate preMain ( 2619 " %${base_type16} = OpTypeInt 16 ${signed}\n" 2620 " %${type16} = OpTypeVector %${base_type16} 2\n" 2621 " %c_i32_${count} = OpConstant %i32 ${count}\n" 2622 "%a${count}${type16} = OpTypeArray %${type16} %c_i32_${count}\n" 2623 "%a${count}${type32} = OpTypeArray %${type32} %c_i32_${count}\n" 2624 " %pp_${type16} = OpTypePointer PushConstant %${type16}\n" 2625 " %up_${type32} = OpTypePointer Uniform %${type32}\n" 2626 " %SSBO32 = OpTypeStruct %a${count}${type32}\n" 2627 " %up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 2628 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 2629 " %PC16 = OpTypeStruct %a${count}${type16}\n" 2630 " %pp_PC16 = OpTypePointer PushConstant %PC16\n" 2631 " %pc16 = OpVariable %pp_PC16 PushConstant\n"); 2632 2633 const StringTemplate decoration ( 2634 "OpDecorate %a${count}${type16} ArrayStride 4\n" 2635 "OpDecorate %a${count}${type32} ArrayStride 8\n" 2636 "OpDecorate %SSBO32 BufferBlock\n" 2637 "OpMemberDecorate %SSBO32 0 Offset 0\n" 2638 "OpDecorate %PC16 Block\n" 2639 "OpMemberDecorate %PC16 0 Offset 0\n" 2640 "OpDecorate %ssbo32 DescriptorSet 0\n" 2641 "OpDecorate %ssbo32 Binding 0\n"); 2642 2643 { // signed int 2644 map<string, string> specs; 2645 2646 specs["base_type16"] = "i16"; 2647 specs["type16"] = "v2i16"; 2648 specs["type32"] = "v2i32"; 2649 specs["signed"] = "1"; 2650 specs["count"] = "32"; // 64 / 2 2651 specs["convert"] = "OpSConvert"; 2652 2653 fragments["testfun"] = testFun.specialize(specs); 2654 fragments["pre_main"] = preMain.specialize(specs); 2655 fragments["decoration"] = decoration.specialize(specs); 2656 2657 resources.outputs.clear(); 2658 resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Int32Buffer(sOutputs)))); 2659 createTestsForAllStages("sint_vector", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures); 2660 } 2661 { // signed int 2662 map<string, string> specs; 2663 2664 specs["base_type16"] = "u16"; 2665 specs["type16"] = "v2u16"; 2666 specs["type32"] = "v2u32"; 2667 specs["signed"] = "0"; 2668 specs["count"] = "32"; 2669 specs["convert"] = "OpUConvert"; 2670 2671 fragments["testfun"] = testFun.specialize(specs); 2672 fragments["pre_main"] = preMain.specialize(specs); 2673 fragments["decoration"] = decoration.specialize(specs); 2674 2675 resources.outputs.clear(); 2676 resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Int32Buffer(uOutputs)))); 2677 createTestsForAllStages("uint_vector", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures); 2678 } 2679 } 2680} 2681 2682void addGraphics16BitStorageUniformInt16To32Group (tcu::TestCaseGroup* testGroup) 2683{ 2684 de::Random rnd (deStringHash(testGroup->getName())); 2685 map<string, string> fragments; 2686 const deUint32 numDataPoints = 256; 2687 RGBA defaultColors[4]; 2688 vector<deInt16> inputs = getInt16s(rnd, numDataPoints); 2689 vector<deInt32> sOutputs; 2690 vector<deInt32> uOutputs; 2691 GraphicsResources resources; 2692 vector<string> extensions; 2693 const deUint16 signBitMask = 0x8000; 2694 const deUint32 signExtendMask = 0xffff0000; 2695 const StringTemplate capabilities ("OpCapability ${cap}\n"); 2696 2697 sOutputs.reserve(inputs.size()); 2698 uOutputs.reserve(inputs.size()); 2699 2700 for (deUint32 numNdx = 0; numNdx < inputs.size(); ++numNdx) 2701 { 2702 uOutputs.push_back(static_cast<deUint16>(inputs[numNdx])); 2703 if (inputs[numNdx] & signBitMask) 2704 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx] | signExtendMask)); 2705 else 2706 sOutputs.push_back(static_cast<deInt32>(inputs[numNdx])); 2707 } 2708 2709 resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Int16Buffer(inputs)))); 2710 2711 extensions.push_back("VK_KHR_16bit_storage"); 2712 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\""; 2713 2714 getDefaultColors(defaultColors); 2715 2716 struct IntegerFacts 2717 { 2718 const char* name; 2719 const char* type32; 2720 const char* type16; 2721 const char* opcode; 2722 bool isSigned; 2723 }; 2724 2725 const IntegerFacts intFacts[] = 2726 { 2727 {"sint", "%i32", "%i16", "OpSConvert", true}, 2728 {"uint", "%u32", "%u16", "OpUConvert", false}, 2729 }; 2730 2731 const StringTemplate scalarPreMain ( 2732 "${itype16} = OpTypeInt 16 ${signed}\n" 2733 " %c_i32_256 = OpConstant %i32 256\n" 2734 " %up_i32 = OpTypePointer Uniform ${itype32}\n" 2735 " %up_i16 = OpTypePointer Uniform ${itype16}\n" 2736 " %ra_i32 = OpTypeArray ${itype32} %c_i32_256\n" 2737 " %ra_i16 = OpTypeArray ${itype16} %c_i32_256\n" 2738 " %SSBO32 = OpTypeStruct %ra_i32\n" 2739 " %SSBO16 = OpTypeStruct %ra_i16\n" 2740 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 2741 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n" 2742 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 2743 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n"); 2744 2745 const StringTemplate scalarDecoration ( 2746 "OpDecorate %ra_i32 ArrayStride 4\n" 2747 "OpDecorate %ra_i16 ArrayStride 2\n" 2748 "OpMemberDecorate %SSBO32 0 Offset 0\n" 2749 "OpMemberDecorate %SSBO16 0 Offset 0\n" 2750 "OpDecorate %SSBO32 BufferBlock\n" 2751 "OpDecorate %SSBO16 ${indecor}\n" 2752 "OpDecorate %ssbo32 DescriptorSet 0\n" 2753 "OpDecorate %ssbo16 DescriptorSet 0\n" 2754 "OpDecorate %ssbo32 Binding 1\n" 2755 "OpDecorate %ssbo16 Binding 0\n"); 2756 2757 const StringTemplate scalarTestFunc ( 2758 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 2759 " %param = OpFunctionParameter %v4f32\n" 2760 2761 "%entry = OpLabel\n" 2762 " %i = OpVariable %fp_i32 Function\n" 2763 " OpStore %i %c_i32_0\n" 2764 " OpBranch %loop\n" 2765 2766 " %loop = OpLabel\n" 2767 " %15 = OpLoad %i32 %i\n" 2768 " %lt = OpSLessThan %bool %15 %c_i32_256\n" 2769 " OpLoopMerge %merge %inc None\n" 2770 " OpBranchConditional %lt %write %merge\n" 2771 2772 "%write = OpLabel\n" 2773 " %30 = OpLoad %i32 %i\n" 2774 " %src = OpAccessChain %up_i16 %ssbo16 %c_i32_0 %30\n" 2775 "%val16 = OpLoad ${itype16} %src\n" 2776 "%val32 = ${convert} ${itype32} %val16\n" 2777 " %dst = OpAccessChain %up_i32 %ssbo32 %c_i32_0 %30\n" 2778 " OpStore %dst %val32\n" 2779 " OpBranch %inc\n" 2780 2781 " %inc = OpLabel\n" 2782 " %37 = OpLoad %i32 %i\n" 2783 " %39 = OpIAdd %i32 %37 %c_i32_1\n" 2784 " OpStore %i %39\n" 2785 " OpBranch %loop\n" 2786 "%merge = OpLabel\n" 2787 " OpReturnValue %param\n" 2788 2789 "OpFunctionEnd\n"); 2790 2791 const StringTemplate vecPreMain ( 2792 "${itype16} = OpTypeInt 16 ${signed}\n" 2793 "%c_i32_128 = OpConstant %i32 128\n" 2794 "%v2itype16 = OpTypeVector ${itype16} 2\n" 2795 "%v2itype32 = OpTypeVector ${itype32} 2\n" 2796 " %up_v2i32 = OpTypePointer Uniform %v2itype32\n" 2797 " %up_v2i16 = OpTypePointer Uniform %v2itype16\n" 2798 " %ra_v2i32 = OpTypeArray %v2itype32 %c_i32_128\n" 2799 " %ra_v2i16 = OpTypeArray %v2itype16 %c_i32_128\n" 2800 " %SSBO32 = OpTypeStruct %ra_v2i32\n" 2801 " %SSBO16 = OpTypeStruct %ra_v2i16\n" 2802 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 2803 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n" 2804 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 2805 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n"); 2806 2807 const StringTemplate vecDecoration ( 2808 "OpDecorate %ra_v2i32 ArrayStride 8\n" 2809 "OpDecorate %ra_v2i16 ArrayStride 4\n" 2810 "OpMemberDecorate %SSBO32 0 Offset 0\n" 2811 "OpMemberDecorate %SSBO16 0 Offset 0\n" 2812 "OpDecorate %SSBO32 BufferBlock\n" 2813 "OpDecorate %SSBO16 ${indecor}\n" 2814 "OpDecorate %ssbo32 DescriptorSet 0\n" 2815 "OpDecorate %ssbo16 DescriptorSet 0\n" 2816 "OpDecorate %ssbo32 Binding 1\n" 2817 "OpDecorate %ssbo16 Binding 0\n"); 2818 2819 const StringTemplate vecTestFunc ( 2820 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 2821 " %param = OpFunctionParameter %v4f32\n" 2822 2823 "%entry = OpLabel\n" 2824 " %i = OpVariable %fp_i32 Function\n" 2825 " OpStore %i %c_i32_0\n" 2826 " OpBranch %loop\n" 2827 2828 " %loop = OpLabel\n" 2829 " %15 = OpLoad %i32 %i\n" 2830 " %lt = OpSLessThan %bool %15 %c_i32_128\n" 2831 " OpLoopMerge %merge %inc None\n" 2832 " OpBranchConditional %lt %write %merge\n" 2833 2834 "%write = OpLabel\n" 2835 " %30 = OpLoad %i32 %i\n" 2836 " %src = OpAccessChain %up_v2i16 %ssbo16 %c_i32_0 %30\n" 2837 "%val16 = OpLoad %v2itype16 %src\n" 2838 "%val32 = ${convert} %v2itype32 %val16\n" 2839 " %dst = OpAccessChain %up_v2i32 %ssbo32 %c_i32_0 %30\n" 2840 " OpStore %dst %val32\n" 2841 " OpBranch %inc\n" 2842 2843 " %inc = OpLabel\n" 2844 " %37 = OpLoad %i32 %i\n" 2845 " %39 = OpIAdd %i32 %37 %c_i32_1\n" 2846 " OpStore %i %39\n" 2847 " OpBranch %loop\n" 2848 "%merge = OpLabel\n" 2849 " OpReturnValue %param\n" 2850 2851 "OpFunctionEnd\n"); 2852 2853 struct Category 2854 { 2855 const char* name; 2856 const StringTemplate& preMain; 2857 const StringTemplate& decoration; 2858 const StringTemplate& testFunction; 2859 }; 2860 2861 const Category categories[] = 2862 { 2863 {"scalar", scalarPreMain, scalarDecoration, scalarTestFunc}, 2864 {"vector", vecPreMain, vecDecoration, vecTestFunc}, 2865 }; 2866 2867 for (deUint32 catIdx = 0; catIdx < DE_LENGTH_OF_ARRAY(categories); ++catIdx) 2868 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx) 2869 for (deUint32 factIdx = 0; factIdx < DE_LENGTH_OF_ARRAY(intFacts); ++factIdx) 2870 { 2871 map<string, string> specs; 2872 string name = string(CAPABILITIES[capIdx].name) + "_" + categories[catIdx].name + "_" + intFacts[factIdx].name; 2873 2874 specs["cap"] = CAPABILITIES[capIdx].cap; 2875 specs["indecor"] = CAPABILITIES[capIdx].decor; 2876 specs["itype32"] = intFacts[factIdx].type32; 2877 specs["itype16"] = intFacts[factIdx].type16; 2878 if (intFacts[factIdx].isSigned) 2879 specs["signed"] = "1"; 2880 else 2881 specs["signed"] = "0"; 2882 specs["convert"] = intFacts[factIdx].opcode; 2883 2884 fragments["pre_main"] = categories[catIdx].preMain.specialize(specs); 2885 fragments["testfun"] = categories[catIdx].testFunction.specialize(specs); 2886 fragments["capability"] = capabilities.specialize(specs); 2887 fragments["decoration"] = categories[catIdx].decoration.specialize(specs); 2888 2889 resources.inputs.back().first = CAPABILITIES[capIdx].dtype; 2890 resources.outputs.clear(); 2891 if (intFacts[factIdx].isSigned) 2892 resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Int32Buffer(sOutputs)))); 2893 else 2894 resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Int32Buffer(uOutputs)))); 2895 2896 createTestsForAllStages(name, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name)); 2897 } 2898} 2899 2900void addGraphics16BitStorageUniformFloat16To32Group (tcu::TestCaseGroup* testGroup) 2901{ 2902 de::Random rnd (deStringHash(testGroup->getName())); 2903 map<string, string> fragments; 2904 GraphicsResources resources; 2905 vector<string> extensions; 2906 const deUint32 numDataPoints = 256; 2907 RGBA defaultColors[4]; 2908 const StringTemplate capabilities ("OpCapability ${cap}\n"); 2909 vector<deFloat16> float16Data = getFloat16s(rnd, numDataPoints); 2910 vector<float> float32Data; 2911 2912 float32Data.reserve(numDataPoints); 2913 for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx) 2914 float32Data.push_back(deFloat16To32(float16Data[numIdx])); 2915 2916 resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float16Buffer(float16Data)))); 2917 resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(float32Data)))); 2918 resources.verifyIO = check32BitFloats; 2919 2920 extensions.push_back("VK_KHR_16bit_storage"); 2921 fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\""; 2922 2923 getDefaultColors(defaultColors); 2924 2925 { // scalar cases 2926 fragments["pre_main"] = 2927 " %f16 = OpTypeFloat 16\n" 2928 "%c_i32_256 = OpConstant %i32 256\n" 2929 " %up_f32 = OpTypePointer Uniform %f32\n" 2930 " %up_f16 = OpTypePointer Uniform %f16\n" 2931 " %ra_f32 = OpTypeArray %f32 %c_i32_256\n" 2932 " %ra_f16 = OpTypeArray %f16 %c_i32_256\n" 2933 " %SSBO32 = OpTypeStruct %ra_f32\n" 2934 " %SSBO16 = OpTypeStruct %ra_f16\n" 2935 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 2936 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n" 2937 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 2938 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n"; 2939 2940 const StringTemplate decoration ( 2941 "OpDecorate %ra_f32 ArrayStride 4\n" 2942 "OpDecorate %ra_f16 ArrayStride 2\n" 2943 "OpMemberDecorate %SSBO32 0 Offset 0\n" 2944 "OpMemberDecorate %SSBO16 0 Offset 0\n" 2945 "OpDecorate %SSBO32 BufferBlock\n" 2946 "OpDecorate %SSBO16 ${indecor}\n" 2947 "OpDecorate %ssbo32 DescriptorSet 0\n" 2948 "OpDecorate %ssbo16 DescriptorSet 0\n" 2949 "OpDecorate %ssbo32 Binding 1\n" 2950 "OpDecorate %ssbo16 Binding 0\n"); 2951 2952 // ssbo32[] <- convert ssbo16[] to 32bit float 2953 fragments["testfun"] = 2954 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 2955 " %param = OpFunctionParameter %v4f32\n" 2956 2957 "%entry = OpLabel\n" 2958 " %i = OpVariable %fp_i32 Function\n" 2959 " OpStore %i %c_i32_0\n" 2960 " OpBranch %loop\n" 2961 2962 " %loop = OpLabel\n" 2963 " %15 = OpLoad %i32 %i\n" 2964 " %lt = OpSLessThan %bool %15 %c_i32_256\n" 2965 " OpLoopMerge %merge %inc None\n" 2966 " OpBranchConditional %lt %write %merge\n" 2967 2968 "%write = OpLabel\n" 2969 " %30 = OpLoad %i32 %i\n" 2970 " %src = OpAccessChain %up_f16 %ssbo16 %c_i32_0 %30\n" 2971 "%val16 = OpLoad %f16 %src\n" 2972 "%val32 = OpFConvert %f32 %val16\n" 2973 " %dst = OpAccessChain %up_f32 %ssbo32 %c_i32_0 %30\n" 2974 " OpStore %dst %val32\n" 2975 " OpBranch %inc\n" 2976 2977 " %inc = OpLabel\n" 2978 " %37 = OpLoad %i32 %i\n" 2979 " %39 = OpIAdd %i32 %37 %c_i32_1\n" 2980 " OpStore %i %39\n" 2981 " OpBranch %loop\n" 2982 2983 "%merge = OpLabel\n" 2984 " OpReturnValue %param\n" 2985 2986 "OpFunctionEnd\n"; 2987 2988 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx) 2989 { 2990 map<string, string> specs; 2991 string testName = string(CAPABILITIES[capIdx].name) + "_scalar_float"; 2992 2993 specs["cap"] = CAPABILITIES[capIdx].cap; 2994 specs["indecor"] = CAPABILITIES[capIdx].decor; 2995 2996 fragments["capability"] = capabilities.specialize(specs); 2997 fragments["decoration"] = decoration.specialize(specs); 2998 2999 resources.inputs.back().first = CAPABILITIES[capIdx].dtype; 3000 3001 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name)); 3002 } 3003 } 3004 3005 { // vector cases 3006 fragments["pre_main"] = 3007 " %f16 = OpTypeFloat 16\n" 3008 "%c_i32_128 = OpConstant %i32 128\n" 3009 " %v2f16 = OpTypeVector %f16 2\n" 3010 " %up_v2f32 = OpTypePointer Uniform %v2f32\n" 3011 " %up_v2f16 = OpTypePointer Uniform %v2f16\n" 3012 " %ra_v2f32 = OpTypeArray %v2f32 %c_i32_128\n" 3013 " %ra_v2f16 = OpTypeArray %v2f16 %c_i32_128\n" 3014 " %SSBO32 = OpTypeStruct %ra_v2f32\n" 3015 " %SSBO16 = OpTypeStruct %ra_v2f16\n" 3016 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 3017 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n" 3018 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 3019 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n"; 3020 3021 const StringTemplate decoration ( 3022 "OpDecorate %ra_v2f32 ArrayStride 8\n" 3023 "OpDecorate %ra_v2f16 ArrayStride 4\n" 3024 "OpMemberDecorate %SSBO32 0 Offset 0\n" 3025 "OpMemberDecorate %SSBO16 0 Offset 0\n" 3026 "OpDecorate %SSBO32 BufferBlock\n" 3027 "OpDecorate %SSBO16 ${indecor}\n" 3028 "OpDecorate %ssbo32 DescriptorSet 0\n" 3029 "OpDecorate %ssbo16 DescriptorSet 0\n" 3030 "OpDecorate %ssbo32 Binding 1\n" 3031 "OpDecorate %ssbo16 Binding 0\n"); 3032 3033 // ssbo32[] <- convert ssbo16[] to 32bit float 3034 fragments["testfun"] = 3035 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 3036 " %param = OpFunctionParameter %v4f32\n" 3037 3038 "%entry = OpLabel\n" 3039 " %i = OpVariable %fp_i32 Function\n" 3040 " OpStore %i %c_i32_0\n" 3041 " OpBranch %loop\n" 3042 3043 " %loop = OpLabel\n" 3044 " %15 = OpLoad %i32 %i\n" 3045 " %lt = OpSLessThan %bool %15 %c_i32_128\n" 3046 " OpLoopMerge %merge %inc None\n" 3047 " OpBranchConditional %lt %write %merge\n" 3048 3049 "%write = OpLabel\n" 3050 " %30 = OpLoad %i32 %i\n" 3051 " %src = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30\n" 3052 "%val16 = OpLoad %v2f16 %src\n" 3053 "%val32 = OpFConvert %v2f32 %val16\n" 3054 " %dst = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30\n" 3055 " OpStore %dst %val32\n" 3056 " OpBranch %inc\n" 3057 3058 " %inc = OpLabel\n" 3059 " %37 = OpLoad %i32 %i\n" 3060 " %39 = OpIAdd %i32 %37 %c_i32_1\n" 3061 " OpStore %i %39\n" 3062 " OpBranch %loop\n" 3063 3064 "%merge = OpLabel\n" 3065 " OpReturnValue %param\n" 3066 3067 "OpFunctionEnd\n"; 3068 3069 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx) 3070 { 3071 map<string, string> specs; 3072 string testName = string(CAPABILITIES[capIdx].name) + "_vector_float"; 3073 3074 specs["cap"] = CAPABILITIES[capIdx].cap; 3075 specs["indecor"] = CAPABILITIES[capIdx].decor; 3076 3077 fragments["capability"] = capabilities.specialize(specs); 3078 fragments["decoration"] = decoration.specialize(specs); 3079 3080 resources.inputs.back().first = CAPABILITIES[capIdx].dtype; 3081 3082 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name)); 3083 } 3084 } 3085 3086 { // matrix cases 3087 fragments["pre_main"] = 3088 " %c_i32_32 = OpConstant %i32 32\n" 3089 " %f16 = OpTypeFloat 16\n" 3090 " %v2f16 = OpTypeVector %f16 2\n" 3091 " %m4x2f32 = OpTypeMatrix %v2f32 4\n" 3092 " %m4x2f16 = OpTypeMatrix %v2f16 4\n" 3093 " %up_v2f32 = OpTypePointer Uniform %v2f32\n" 3094 " %up_v2f16 = OpTypePointer Uniform %v2f16\n" 3095 "%a8m4x2f32 = OpTypeArray %m4x2f32 %c_i32_32\n" 3096 "%a8m4x2f16 = OpTypeArray %m4x2f16 %c_i32_32\n" 3097 " %SSBO32 = OpTypeStruct %a8m4x2f32\n" 3098 " %SSBO16 = OpTypeStruct %a8m4x2f16\n" 3099 "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n" 3100 "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n" 3101 " %ssbo32 = OpVariable %up_SSBO32 Uniform\n" 3102 " %ssbo16 = OpVariable %up_SSBO16 Uniform\n"; 3103 3104 const StringTemplate decoration ( 3105 "OpDecorate %a8m4x2f32 ArrayStride 32\n" 3106 "OpDecorate %a8m4x2f16 ArrayStride 16\n" 3107 "OpMemberDecorate %SSBO32 0 Offset 0\n" 3108 "OpMemberDecorate %SSBO32 0 ColMajor\n" 3109 "OpMemberDecorate %SSBO32 0 MatrixStride 8\n" 3110 "OpMemberDecorate %SSBO16 0 Offset 0\n" 3111 "OpMemberDecorate %SSBO16 0 ColMajor\n" 3112 "OpMemberDecorate %SSBO16 0 MatrixStride 4\n" 3113 "OpDecorate %SSBO32 BufferBlock\n" 3114 "OpDecorate %SSBO16 ${indecor}\n" 3115 "OpDecorate %ssbo32 DescriptorSet 0\n" 3116 "OpDecorate %ssbo16 DescriptorSet 0\n" 3117 "OpDecorate %ssbo32 Binding 1\n" 3118 "OpDecorate %ssbo16 Binding 0\n"); 3119 3120 fragments["testfun"] = 3121 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 3122 " %param = OpFunctionParameter %v4f32\n" 3123 3124 "%entry = OpLabel\n" 3125 " %i = OpVariable %fp_i32 Function\n" 3126 " OpStore %i %c_i32_0\n" 3127 " OpBranch %loop\n" 3128 3129 " %loop = OpLabel\n" 3130 " %15 = OpLoad %i32 %i\n" 3131 " %lt = OpSLessThan %bool %15 %c_i32_32\n" 3132 " OpLoopMerge %merge %inc None\n" 3133 " OpBranchConditional %lt %write %merge\n" 3134 3135 " %write = OpLabel\n" 3136 " %30 = OpLoad %i32 %i\n" 3137 " %src_0 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_0\n" 3138 " %src_1 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_1\n" 3139 " %src_2 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_2\n" 3140 " %src_3 = OpAccessChain %up_v2f16 %ssbo16 %c_i32_0 %30 %c_i32_3\n" 3141 "%val16_0 = OpLoad %v2f16 %src_0\n" 3142 "%val16_1 = OpLoad %v2f16 %src_1\n" 3143 "%val16_2 = OpLoad %v2f16 %src_2\n" 3144 "%val16_3 = OpLoad %v2f16 %src_3\n" 3145 "%val32_0 = OpFConvert %v2f32 %val16_0\n" 3146 "%val32_1 = OpFConvert %v2f32 %val16_1\n" 3147 "%val32_2 = OpFConvert %v2f32 %val16_2\n" 3148 "%val32_3 = OpFConvert %v2f32 %val16_3\n" 3149 " %dst_0 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_0\n" 3150 " %dst_1 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_1\n" 3151 " %dst_2 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_2\n" 3152 " %dst_3 = OpAccessChain %up_v2f32 %ssbo32 %c_i32_0 %30 %c_i32_3\n" 3153 " OpStore %dst_0 %val32_0\n" 3154 " OpStore %dst_1 %val32_1\n" 3155 " OpStore %dst_2 %val32_2\n" 3156 " OpStore %dst_3 %val32_3\n" 3157 " OpBranch %inc\n" 3158 3159 " %inc = OpLabel\n" 3160 " %37 = OpLoad %i32 %i\n" 3161 " %39 = OpIAdd %i32 %37 %c_i32_1\n" 3162 " OpStore %i %39\n" 3163 " OpBranch %loop\n" 3164 3165 "%merge = OpLabel\n" 3166 " OpReturnValue %param\n" 3167 3168 "OpFunctionEnd\n"; 3169 3170 for (deUint32 capIdx = 0; capIdx < DE_LENGTH_OF_ARRAY(CAPABILITIES); ++capIdx) 3171 { 3172 map<string, string> specs; 3173 string testName = string(CAPABILITIES[capIdx].name) + "_matrix_float"; 3174 3175 specs["cap"] = CAPABILITIES[capIdx].cap; 3176 specs["indecor"] = CAPABILITIES[capIdx].decor; 3177 3178 fragments["capability"] = capabilities.specialize(specs); 3179 fragments["decoration"] = decoration.specialize(specs); 3180 3181 resources.inputs.back().first = CAPABILITIES[capIdx].dtype; 3182 3183 createTestsForAllStages(testName, defaultColors, defaultColors, fragments, resources, extensions, testGroup, get16BitStorageFeatures(CAPABILITIES[capIdx].name)); 3184 } 3185 } 3186} 3187 3188} // anonymous 3189 3190tcu::TestCaseGroup* create16BitStorageComputeGroup (tcu::TestContext& testCtx) 3191{ 3192 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "16bit_storage", "Compute tests for VK_KHR_16bit_storage extension")); 3193 addTestGroup(group.get(), "uniform_32_to_16", "32bit floats/ints to 16bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform32To16Group); 3194 addTestGroup(group.get(), "uniform_16_to_32", "16bit floats/ints to 32bit tests under capability StorageUniform{|BufferBlock}", addCompute16bitStorageUniform16To32Group); 3195 addTestGroup(group.get(), "push_constant_16_to_32", "16bit floats/ints to 32bit tests under capability StoragePushConstant16", addCompute16bitStoragePushConstant16To32Group); 3196 3197 return group.release(); 3198} 3199 3200tcu::TestCaseGroup* create16BitStorageGraphicsGroup (tcu::TestContext& testCtx) 3201{ 3202 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "16bit_storage", "Graphics tests for VK_KHR_16bit_storage extension")); 3203 3204 addTestGroup(group.get(), "uniform_float_32_to_16", "32-bit floats into 16-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformFloat32To16Group); 3205 addTestGroup(group.get(), "uniform_float_16_to_32", "16-bit floats into 32-bit testsunder capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformFloat16To32Group); 3206 addTestGroup(group.get(), "uniform_int_32_to_16", "32-bit int into 16-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformInt32To16Group); 3207 addTestGroup(group.get(), "uniform_int_16_to_32", "16-bit int into 32-bit tests under capability StorageUniform{|BufferBlock}16", addGraphics16BitStorageUniformInt16To32Group); 3208 addTestGroup(group.get(), "input_output_float_32_to_16", "32-bit floats into 16-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputFloat32To16Group); 3209 addTestGroup(group.get(), "input_output_float_16_to_32", "16-bit floats into 32-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputFloat16To32Group); 3210 addTestGroup(group.get(), "input_output_int_32_to_16", "32-bit int into 16-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputInt32To16Group); 3211 addTestGroup(group.get(), "input_output_int_16_to_32", "16-bit int into 32-bit tests under capability StorageInputOutput16", addGraphics16BitStorageInputOutputInt16To32Group); 3212 addTestGroup(group.get(), "push_constant_float_16_to_32", "16-bit floats into 32-bit tests under capability StoragePushConstant16", addGraphics16BitStoragePushConstantFloat16To32Group); 3213 addTestGroup(group.get(), "push_constant_int_16_to_32", "16-bit int into 32-bit tests under capability StoragePushConstant16", addGraphics16BitStoragePushConstantInt16To32Group); 3214 3215 return group.release(); 3216} 3217 3218} // SpirVAssembly 3219} // vkt 3220