ImageFunctionHLSL.cpp (12345B)
1 // 2 // Copyright 2017 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 // ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output. 7 // 8 9 #include "compiler/translator/ImageFunctionHLSL.h" 10 #include "compiler/translator/ImmutableStringBuilder.h" 11 #include "compiler/translator/UtilsHLSL.h" 12 13 namespace sh 14 { 15 16 // static 17 ImmutableString ImageFunctionHLSL::GetImageReference( 18 TInfoSinkBase &out, 19 const ImageFunctionHLSL::ImageFunction &imageFunction) 20 { 21 static const ImmutableString kImageIndexStr("[index]"); 22 if (imageFunction.readonly) 23 { 24 static const ImmutableString kReadonlyImagesStr("readonlyImages"); 25 ImmutableString suffix( 26 TextureGroupSuffix(imageFunction.image, imageFunction.imageInternalFormat)); 27 out << " const uint index = imageIndex - readonlyImageIndexOffset" << suffix.data() 28 << ";\n"; 29 ImmutableStringBuilder imageRefBuilder(kReadonlyImagesStr.length() + suffix.length() + 30 kImageIndexStr.length()); 31 imageRefBuilder << kReadonlyImagesStr << suffix << kImageIndexStr; 32 return imageRefBuilder; 33 } 34 else 35 { 36 static const ImmutableString kImagesStr("images"); 37 ImmutableString suffix( 38 RWTextureGroupSuffix(imageFunction.image, imageFunction.imageInternalFormat)); 39 out << " const uint index = imageIndex - imageIndexOffset" << suffix.data() << ";\n"; 40 ImmutableStringBuilder imageRefBuilder(kImagesStr.length() + suffix.length() + 41 kImageIndexStr.length()); 42 imageRefBuilder << kImagesStr << suffix << kImageIndexStr; 43 return imageRefBuilder; 44 } 45 } 46 47 void ImageFunctionHLSL::OutputImageFunctionArgumentList( 48 TInfoSinkBase &out, 49 const ImageFunctionHLSL::ImageFunction &imageFunction) 50 { 51 out << "uint imageIndex"; 52 53 if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::LOAD || 54 imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE) 55 { 56 switch (imageFunction.image) 57 { 58 case EbtImage2D: 59 case EbtIImage2D: 60 case EbtUImage2D: 61 out << ", int2 p"; 62 break; 63 case EbtImage3D: 64 case EbtIImage3D: 65 case EbtUImage3D: 66 case EbtImageCube: 67 case EbtIImageCube: 68 case EbtUImageCube: 69 case EbtImage2DArray: 70 case EbtIImage2DArray: 71 case EbtUImage2DArray: 72 out << ", int3 p"; 73 break; 74 case EbtUImageBuffer: 75 case EbtIImageBuffer: 76 case EbtImageBuffer: 77 out << ", int p"; 78 break; 79 80 default: 81 UNREACHABLE(); 82 } 83 84 if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE) 85 { 86 switch (imageFunction.image) 87 { 88 case EbtImage2D: 89 case EbtImage3D: 90 case EbtImageCube: 91 case EbtImage2DArray: 92 case EbtImageBuffer: 93 out << ", float4 data"; 94 break; 95 case EbtIImage2D: 96 case EbtIImage3D: 97 case EbtIImageCube: 98 case EbtIImage2DArray: 99 case EbtIImageBuffer: 100 out << ", int4 data"; 101 break; 102 case EbtUImage2D: 103 case EbtUImage3D: 104 case EbtUImageCube: 105 case EbtUImage2DArray: 106 case EbtUImageBuffer: 107 out << ", uint4 data"; 108 break; 109 default: 110 UNREACHABLE(); 111 } 112 } 113 } 114 } 115 116 // static 117 void ImageFunctionHLSL::OutputImageSizeFunctionBody( 118 TInfoSinkBase &out, 119 const ImageFunctionHLSL::ImageFunction &imageFunction, 120 const ImmutableString &imageReference) 121 { 122 if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) || 123 IsImageCube(imageFunction.image)) 124 { 125 // "depth" stores either the number of layers in an array texture or 3D depth 126 out << " uint width; uint height; uint depth;\n" 127 << " " << imageReference << ".GetDimensions(width, height, depth);\n"; 128 } 129 else if (IsImage2D(imageFunction.image)) 130 { 131 out << " uint width; uint height;\n" 132 << " " << imageReference << ".GetDimensions(width, height);\n"; 133 } 134 else if (IsImageBuffer(imageFunction.image)) 135 { 136 out << " uint width;\n" 137 << " " << imageReference << ".GetDimensions(width);\n"; 138 } 139 else 140 UNREACHABLE(); 141 142 if (strcmp(imageFunction.getReturnType(), "int3") == 0) 143 { 144 out << " return int3(width, height, depth);\n"; 145 } 146 else if (strcmp(imageFunction.getReturnType(), "int2") == 0) 147 { 148 out << " return int2(width, height);\n"; 149 } 150 else if (strcmp(imageFunction.getReturnType(), "int") == 0) 151 out << " return int(width);\n"; 152 else 153 UNREACHABLE(); 154 } 155 156 // static 157 void ImageFunctionHLSL::OutputImageLoadFunctionBody( 158 TInfoSinkBase &out, 159 const ImageFunctionHLSL::ImageFunction &imageFunction, 160 const ImmutableString &imageReference) 161 { 162 if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) || 163 IsImageCube(imageFunction.image)) 164 { 165 out << " return " << imageReference << "[uint3(p.x, p.y, p.z)];\n"; 166 } 167 else if (IsImage2D(imageFunction.image)) 168 { 169 out << " return " << imageReference << "[uint2(p.x, p.y)];\n"; 170 } 171 else if (IsImageBuffer(imageFunction.image)) 172 { 173 out << " return " << imageReference << "[uint(p.x)];\n"; 174 } 175 else 176 UNREACHABLE(); 177 } 178 179 // static 180 void ImageFunctionHLSL::OutputImageStoreFunctionBody( 181 TInfoSinkBase &out, 182 const ImageFunctionHLSL::ImageFunction &imageFunction, 183 const ImmutableString &imageReference) 184 { 185 if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) || 186 IsImage2D(imageFunction.image) || IsImageCube(imageFunction.image) || 187 IsImageBuffer(imageFunction.image)) 188 { 189 out << " " << imageReference << "[p] = data;\n"; 190 } 191 else 192 UNREACHABLE(); 193 } 194 195 ImmutableString ImageFunctionHLSL::ImageFunction::name() const 196 { 197 static const ImmutableString kGlImageName("gl_image"); 198 199 ImmutableString suffix(nullptr); 200 if (readonly) 201 { 202 suffix = ImmutableString(TextureTypeSuffix(image, imageInternalFormat)); 203 } 204 else 205 { 206 suffix = ImmutableString(RWTextureTypeSuffix(image, imageInternalFormat)); 207 } 208 209 ImmutableStringBuilder name(kGlImageName.length() + suffix.length() + 5u); 210 211 name << kGlImageName << suffix; 212 213 switch (method) 214 { 215 case Method::SIZE: 216 name << "Size"; 217 break; 218 case Method::LOAD: 219 name << "Load"; 220 break; 221 case Method::STORE: 222 name << "Store"; 223 break; 224 default: 225 UNREACHABLE(); 226 } 227 228 return name; 229 } 230 231 ImageFunctionHLSL::ImageFunction::DataType ImageFunctionHLSL::ImageFunction::getDataType( 232 TLayoutImageInternalFormat format) const 233 { 234 switch (format) 235 { 236 case EiifRGBA32F: 237 case EiifRGBA16F: 238 case EiifR32F: 239 return ImageFunction::DataType::FLOAT4; 240 case EiifRGBA32UI: 241 case EiifRGBA16UI: 242 case EiifRGBA8UI: 243 case EiifR32UI: 244 return ImageFunction::DataType::UINT4; 245 case EiifRGBA32I: 246 case EiifRGBA16I: 247 case EiifRGBA8I: 248 case EiifR32I: 249 return ImageFunction::DataType::INT4; 250 case EiifRGBA8: 251 return ImageFunction::DataType::UNORM_FLOAT4; 252 case EiifRGBA8_SNORM: 253 return ImageFunction::DataType::SNORM_FLOAT4; 254 default: 255 UNREACHABLE(); 256 } 257 258 return ImageFunction::DataType::NONE; 259 } 260 261 const char *ImageFunctionHLSL::ImageFunction::getReturnType() const 262 { 263 if (method == ImageFunction::Method::SIZE) 264 { 265 switch (image) 266 { 267 case EbtImage2D: 268 case EbtIImage2D: 269 case EbtUImage2D: 270 case EbtImageCube: 271 case EbtIImageCube: 272 case EbtUImageCube: 273 return "int2"; 274 case EbtImage3D: 275 case EbtIImage3D: 276 case EbtUImage3D: 277 case EbtImage2DArray: 278 case EbtIImage2DArray: 279 case EbtUImage2DArray: 280 return "int3"; 281 case EbtImageBuffer: 282 case EbtIImageBuffer: 283 case EbtUImageBuffer: 284 return "int"; 285 default: 286 UNREACHABLE(); 287 } 288 } 289 else if (method == ImageFunction::Method::LOAD) 290 { 291 switch (image) 292 { 293 case EbtImageBuffer: 294 case EbtImage2D: 295 case EbtImage3D: 296 case EbtImageCube: 297 case EbtImage2DArray: 298 return "float4"; 299 case EbtIImageBuffer: 300 case EbtIImage2D: 301 case EbtIImage3D: 302 case EbtIImageCube: 303 case EbtIImage2DArray: 304 return "int4"; 305 case EbtUImageBuffer: 306 case EbtUImage2D: 307 case EbtUImage3D: 308 case EbtUImageCube: 309 case EbtUImage2DArray: 310 return "uint4"; 311 default: 312 UNREACHABLE(); 313 } 314 } 315 else if (method == ImageFunction::Method::STORE) 316 { 317 return "void"; 318 } 319 else 320 { 321 UNREACHABLE(); 322 } 323 return ""; 324 } 325 326 bool ImageFunctionHLSL::ImageFunction::operator<(const ImageFunction &rhs) const 327 { 328 return std::tie(image, type, method, readonly) < 329 std::tie(rhs.image, rhs.type, rhs.method, rhs.readonly); 330 } 331 332 ImmutableString ImageFunctionHLSL::useImageFunction(const ImmutableString &name, 333 const TBasicType &type, 334 TLayoutImageInternalFormat imageInternalFormat, 335 bool readonly) 336 { 337 ASSERT(IsImage(type)); 338 ImageFunction imageFunction; 339 imageFunction.image = type; 340 imageFunction.imageInternalFormat = imageInternalFormat; 341 imageFunction.readonly = readonly; 342 imageFunction.type = imageFunction.getDataType(imageInternalFormat); 343 344 if (name == "imageSize") 345 { 346 imageFunction.method = ImageFunction::Method::SIZE; 347 } 348 else if (name == "imageLoad") 349 { 350 imageFunction.method = ImageFunction::Method::LOAD; 351 } 352 else if (name == "imageStore") 353 { 354 imageFunction.method = ImageFunction::Method::STORE; 355 } 356 else 357 UNREACHABLE(); 358 359 mUsesImage.insert(imageFunction); 360 return imageFunction.name(); 361 } 362 363 void ImageFunctionHLSL::imageFunctionHeader(TInfoSinkBase &out) 364 { 365 for (const ImageFunction &imageFunction : mUsesImage) 366 { 367 // Skip to generate image2D functions here, dynamically generate these 368 // functions when linking, or after dispatch or draw. 369 if (IsImage2D(imageFunction.image)) 370 { 371 mUsedImage2DFunctionNames.insert(imageFunction.name().data()); 372 continue; 373 } 374 // Function header 375 out << imageFunction.getReturnType() << " " << imageFunction.name() << "("; 376 377 OutputImageFunctionArgumentList(out, imageFunction); 378 379 out << ")\n" 380 "{\n"; 381 382 ImmutableString imageReference = GetImageReference(out, imageFunction); 383 if (imageFunction.method == ImageFunction::Method::SIZE) 384 { 385 OutputImageSizeFunctionBody(out, imageFunction, imageReference); 386 } 387 else if (imageFunction.method == ImageFunction::Method::LOAD) 388 { 389 OutputImageLoadFunctionBody(out, imageFunction, imageReference); 390 } 391 else 392 { 393 OutputImageStoreFunctionBody(out, imageFunction, imageReference); 394 } 395 396 out << "}\n" 397 "\n"; 398 } 399 } 400 401 } // namespace sh