ShaderStorageBlockFunctionHLSL.cpp (16060B)
1 // 2 // Copyright 2018 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // ShaderStorageBlockFunctionHLSL: Wrapper functions for RWByteAddressBuffer Load/Store functions. 7 // 8 9 #include "compiler/translator/ShaderStorageBlockFunctionHLSL.h" 10 11 #include "common/utilities.h" 12 #include "compiler/translator/UtilsHLSL.h" 13 #include "compiler/translator/blocklayout.h" 14 #include "compiler/translator/blocklayoutHLSL.h" 15 #include "compiler/translator/util.h" 16 17 namespace sh 18 { 19 20 // static 21 void ShaderStorageBlockFunctionHLSL::OutputSSBOLoadFunctionBody( 22 TInfoSinkBase &out, 23 const ShaderStorageBlockFunction &ssboFunction) 24 { 25 const char *convertString; 26 switch (ssboFunction.type.getBasicType()) 27 { 28 case EbtFloat: 29 convertString = "asfloat("; 30 break; 31 case EbtInt: 32 convertString = "asint("; 33 break; 34 case EbtUInt: 35 convertString = "asuint("; 36 break; 37 case EbtBool: 38 convertString = "asint("; 39 break; 40 default: 41 UNREACHABLE(); 42 return; 43 } 44 45 size_t bytesPerComponent = 46 gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type))); 47 out << " " << ssboFunction.typeString << " result"; 48 if (ssboFunction.type.isScalar()) 49 { 50 size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent; 51 out << " = " << convertString << "buffer.Load(loc + " << offset << "));\n "; 52 } 53 else if (ssboFunction.type.isVector()) 54 { 55 if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle) 56 { 57 size_t componentStride = bytesPerComponent; 58 if (ssboFunction.rowMajor) 59 { 60 componentStride = ssboFunction.matrixStride; 61 } 62 63 out << " = {"; 64 for (const int offset : ssboFunction.swizzleOffsets) 65 { 66 size_t offsetInBytes = offset * componentStride; 67 out << convertString << "buffer.Load(loc + " << offsetInBytes << ")),"; 68 } 69 out << "};\n"; 70 } 71 else 72 { 73 out << " = " << convertString << "buffer.Load" 74 << static_cast<uint32_t>(ssboFunction.type.getNominalSize()) << "(loc));\n"; 75 } 76 } 77 else if (ssboFunction.type.isMatrix()) 78 { 79 if (ssboFunction.rowMajor) 80 { 81 out << ";"; 82 out << " float" << static_cast<uint32_t>(ssboFunction.type.getRows()) << "x" 83 << static_cast<uint32_t>(ssboFunction.type.getCols()) << " tmp_ = {"; 84 for (uint8_t rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++) 85 { 86 out << "asfloat(buffer.Load" << static_cast<uint32_t>(ssboFunction.type.getCols()) 87 << "(loc + " << rowIndex * ssboFunction.matrixStride << ")), "; 88 } 89 out << "};\n"; 90 out << " result = transpose(tmp_);\n"; 91 } 92 else 93 { 94 out << " = {"; 95 for (uint8_t columnIndex = 0; columnIndex < ssboFunction.type.getCols(); columnIndex++) 96 { 97 out << "asfloat(buffer.Load" << static_cast<uint32_t>(ssboFunction.type.getRows()) 98 << "(loc + " << columnIndex * ssboFunction.matrixStride << ")), "; 99 } 100 out << "};\n"; 101 } 102 } 103 else 104 { 105 // TODO(jiajia.qin@intel.com): Process all possible return types. http://anglebug.com/1951 106 out << ";\n"; 107 } 108 109 out << " return result;\n"; 110 return; 111 } 112 113 // static 114 void ShaderStorageBlockFunctionHLSL::OutputSSBOStoreFunctionBody( 115 TInfoSinkBase &out, 116 const ShaderStorageBlockFunction &ssboFunction) 117 { 118 size_t bytesPerComponent = 119 gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type))); 120 if (ssboFunction.type.isScalar()) 121 { 122 size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent; 123 if (ssboFunction.type.getBasicType() == EbtBool) 124 { 125 out << " buffer.Store(loc + " << offset << ", uint(value));\n"; 126 } 127 else 128 { 129 out << " buffer.Store(loc + " << offset << ", asuint(value));\n"; 130 } 131 } 132 else if (ssboFunction.type.isVector()) 133 { 134 out << " uint" << static_cast<uint32_t>(ssboFunction.type.getNominalSize()) 135 << " _value;\n"; 136 if (ssboFunction.type.getBasicType() == EbtBool) 137 { 138 out << " _value = uint" << static_cast<uint32_t>(ssboFunction.type.getNominalSize()) 139 << "(value);\n"; 140 } 141 else 142 { 143 out << " _value = asuint(value);\n"; 144 } 145 146 if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle) 147 { 148 size_t componentStride = bytesPerComponent; 149 if (ssboFunction.rowMajor) 150 { 151 componentStride = ssboFunction.matrixStride; 152 } 153 const TVector<int> &swizzleOffsets = ssboFunction.swizzleOffsets; 154 for (int index = 0; index < static_cast<int>(swizzleOffsets.size()); index++) 155 { 156 size_t offsetInBytes = swizzleOffsets[index] * componentStride; 157 out << "buffer.Store(loc + " << offsetInBytes << ", _value[" << index << "]);\n"; 158 } 159 } 160 else 161 { 162 out << " buffer.Store" << static_cast<uint32_t>(ssboFunction.type.getNominalSize()) 163 << "(loc, _value);\n"; 164 } 165 } 166 else if (ssboFunction.type.isMatrix()) 167 { 168 if (ssboFunction.rowMajor) 169 { 170 out << " float" << static_cast<uint32_t>(ssboFunction.type.getRows()) << "x" 171 << static_cast<uint32_t>(ssboFunction.type.getCols()) 172 << " tmp_ = transpose(value);\n"; 173 for (uint8_t rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++) 174 { 175 out << " buffer.Store" << static_cast<uint32_t>(ssboFunction.type.getCols()) 176 << "(loc + " << rowIndex * ssboFunction.matrixStride << ", asuint(tmp_[" 177 << static_cast<uint32_t>(rowIndex) << "]));\n"; 178 } 179 } 180 else 181 { 182 for (uint8_t columnIndex = 0; columnIndex < ssboFunction.type.getCols(); columnIndex++) 183 { 184 out << " buffer.Store" << static_cast<uint32_t>(ssboFunction.type.getRows()) 185 << "(loc + " << columnIndex * ssboFunction.matrixStride << ", asuint(value[" 186 << static_cast<uint32_t>(columnIndex) << "]));\n"; 187 } 188 } 189 } 190 else 191 { 192 // TODO(jiajia.qin@intel.com): Process all possible return types. http://anglebug.com/1951 193 } 194 } 195 196 // static 197 void ShaderStorageBlockFunctionHLSL::OutputSSBOLengthFunctionBody(TInfoSinkBase &out, 198 int unsizedArrayStride) 199 { 200 out << " uint dim = 0;\n"; 201 out << " buffer.GetDimensions(dim);\n"; 202 out << " return int((dim - loc)/uint(" << unsizedArrayStride << "));\n"; 203 } 204 205 // static 206 void ShaderStorageBlockFunctionHLSL::OutputSSBOAtomicMemoryFunctionBody( 207 TInfoSinkBase &out, 208 const ShaderStorageBlockFunction &ssboFunction) 209 { 210 out << " " << ssboFunction.typeString << " original_value;\n"; 211 switch (ssboFunction.method) 212 { 213 case SSBOMethod::ATOMIC_ADD: 214 out << " buffer.InterlockedAdd(loc, value, original_value);\n"; 215 break; 216 case SSBOMethod::ATOMIC_MIN: 217 out << " buffer.InterlockedMin(loc, value, original_value);\n"; 218 break; 219 case SSBOMethod::ATOMIC_MAX: 220 out << " buffer.InterlockedMax(loc, value, original_value);\n"; 221 break; 222 case SSBOMethod::ATOMIC_AND: 223 out << " buffer.InterlockedAnd(loc, value, original_value);\n"; 224 break; 225 case SSBOMethod::ATOMIC_OR: 226 out << " buffer.InterlockedOr(loc, value, original_value);\n"; 227 break; 228 case SSBOMethod::ATOMIC_XOR: 229 out << " buffer.InterlockedXor(loc, value, original_value);\n"; 230 break; 231 case SSBOMethod::ATOMIC_EXCHANGE: 232 out << " buffer.InterlockedExchange(loc, value, original_value);\n"; 233 break; 234 case SSBOMethod::ATOMIC_COMPSWAP: 235 out << " buffer.InterlockedCompareExchange(loc, compare_value, value, " 236 "original_value);\n"; 237 break; 238 default: 239 UNREACHABLE(); 240 } 241 out << " return original_value;\n"; 242 } 243 244 bool ShaderStorageBlockFunctionHLSL::ShaderStorageBlockFunction::operator<( 245 const ShaderStorageBlockFunction &rhs) const 246 { 247 return functionName < rhs.functionName; 248 } 249 250 TString ShaderStorageBlockFunctionHLSL::registerShaderStorageBlockFunction( 251 const TType &type, 252 SSBOMethod method, 253 TLayoutBlockStorage storage, 254 bool rowMajor, 255 int matrixStride, 256 int unsizedArrayStride, 257 TIntermSwizzle *swizzleNode) 258 { 259 ShaderStorageBlockFunction ssboFunction; 260 ssboFunction.typeString = TypeString(type); 261 ssboFunction.method = method; 262 switch (method) 263 { 264 case SSBOMethod::LOAD: 265 ssboFunction.functionName = "_Load_"; 266 break; 267 case SSBOMethod::STORE: 268 ssboFunction.functionName = "_Store_"; 269 break; 270 case SSBOMethod::LENGTH: 271 ssboFunction.unsizedArrayStride = unsizedArrayStride; 272 ssboFunction.functionName = "_Length_" + str(unsizedArrayStride); 273 mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); 274 return ssboFunction.functionName; 275 case SSBOMethod::ATOMIC_ADD: 276 ssboFunction.functionName = "_ssbo_atomicAdd_" + ssboFunction.typeString; 277 mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); 278 return ssboFunction.functionName; 279 case SSBOMethod::ATOMIC_MIN: 280 ssboFunction.functionName = "_ssbo_atomicMin_" + ssboFunction.typeString; 281 mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); 282 return ssboFunction.functionName; 283 case SSBOMethod::ATOMIC_MAX: 284 ssboFunction.functionName = "_ssbo_atomicMax_" + ssboFunction.typeString; 285 mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); 286 return ssboFunction.functionName; 287 case SSBOMethod::ATOMIC_AND: 288 ssboFunction.functionName = "_ssbo_atomicAnd_" + ssboFunction.typeString; 289 mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); 290 return ssboFunction.functionName; 291 case SSBOMethod::ATOMIC_OR: 292 ssboFunction.functionName = "_ssbo_atomicOr_" + ssboFunction.typeString; 293 mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); 294 return ssboFunction.functionName; 295 case SSBOMethod::ATOMIC_XOR: 296 ssboFunction.functionName = "_ssbo_atomicXor_" + ssboFunction.typeString; 297 mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); 298 return ssboFunction.functionName; 299 case SSBOMethod::ATOMIC_EXCHANGE: 300 ssboFunction.functionName = "_ssbo_atomicExchange_" + ssboFunction.typeString; 301 mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); 302 return ssboFunction.functionName; 303 case SSBOMethod::ATOMIC_COMPSWAP: 304 ssboFunction.functionName = "_ssbo_atomicCompSwap_" + ssboFunction.typeString; 305 mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); 306 return ssboFunction.functionName; 307 default: 308 UNREACHABLE(); 309 } 310 311 ssboFunction.functionName += ssboFunction.typeString; 312 ssboFunction.type = type; 313 if (swizzleNode != nullptr) 314 { 315 ssboFunction.swizzleOffsets = swizzleNode->getSwizzleOffsets(); 316 ssboFunction.isDefaultSwizzle = false; 317 } 318 else 319 { 320 if (ssboFunction.type.getNominalSize() > 1) 321 { 322 for (uint8_t index = 0; index < ssboFunction.type.getNominalSize(); index++) 323 { 324 ssboFunction.swizzleOffsets.push_back(index); 325 } 326 } 327 else 328 { 329 ssboFunction.swizzleOffsets.push_back(0); 330 } 331 332 ssboFunction.isDefaultSwizzle = true; 333 } 334 ssboFunction.rowMajor = rowMajor; 335 ssboFunction.matrixStride = matrixStride; 336 ssboFunction.functionName += "_" + TString(getBlockStorageString(storage)); 337 338 if (rowMajor) 339 { 340 ssboFunction.functionName += "_rm_"; 341 } 342 else 343 { 344 ssboFunction.functionName += "_cm_"; 345 } 346 347 for (const int offset : ssboFunction.swizzleOffsets) 348 { 349 switch (offset) 350 { 351 case 0: 352 ssboFunction.functionName += "x"; 353 break; 354 case 1: 355 ssboFunction.functionName += "y"; 356 break; 357 case 2: 358 ssboFunction.functionName += "z"; 359 break; 360 case 3: 361 ssboFunction.functionName += "w"; 362 break; 363 default: 364 UNREACHABLE(); 365 } 366 } 367 368 mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); 369 return ssboFunction.functionName; 370 } 371 372 void ShaderStorageBlockFunctionHLSL::shaderStorageBlockFunctionHeader(TInfoSinkBase &out) 373 { 374 for (const ShaderStorageBlockFunction &ssboFunction : mRegisteredShaderStorageBlockFunctions) 375 { 376 switch (ssboFunction.method) 377 { 378 case SSBOMethod::LOAD: 379 { 380 // Function header 381 out << ssboFunction.typeString << " " << ssboFunction.functionName 382 << "(RWByteAddressBuffer buffer, uint loc)\n"; 383 out << "{\n"; 384 OutputSSBOLoadFunctionBody(out, ssboFunction); 385 break; 386 } 387 case SSBOMethod::STORE: 388 { 389 // Function header 390 out << "void " << ssboFunction.functionName 391 << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString 392 << " value)\n"; 393 out << "{\n"; 394 OutputSSBOStoreFunctionBody(out, ssboFunction); 395 break; 396 } 397 case SSBOMethod::LENGTH: 398 { 399 out << "int " << ssboFunction.functionName 400 << "(RWByteAddressBuffer buffer, uint loc)\n"; 401 out << "{\n"; 402 OutputSSBOLengthFunctionBody(out, ssboFunction.unsizedArrayStride); 403 break; 404 } 405 case SSBOMethod::ATOMIC_ADD: 406 case SSBOMethod::ATOMIC_MIN: 407 case SSBOMethod::ATOMIC_MAX: 408 case SSBOMethod::ATOMIC_AND: 409 case SSBOMethod::ATOMIC_OR: 410 case SSBOMethod::ATOMIC_XOR: 411 case SSBOMethod::ATOMIC_EXCHANGE: 412 { 413 out << ssboFunction.typeString << " " << ssboFunction.functionName 414 << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString 415 << " value)\n"; 416 out << "{\n"; 417 418 OutputSSBOAtomicMemoryFunctionBody(out, ssboFunction); 419 break; 420 } 421 case SSBOMethod::ATOMIC_COMPSWAP: 422 { 423 out << ssboFunction.typeString << " " << ssboFunction.functionName 424 << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString 425 << " compare_value, " << ssboFunction.typeString << " value)\n"; 426 out << "{\n"; 427 OutputSSBOAtomicMemoryFunctionBody(out, ssboFunction); 428 break; 429 } 430 default: 431 UNREACHABLE(); 432 } 433 434 out << "}\n" 435 "\n"; 436 } 437 } 438 439 } // namespace sh