GrMtlUtil.mm 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * Copyright 2017 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "src/gpu/mtl/GrMtlUtil.h"
  8. #include "include/gpu/GrSurface.h"
  9. #include "include/private/GrTypesPriv.h"
  10. #include "src/gpu/mtl/GrMtlGpu.h"
  11. #include "src/gpu/mtl/GrMtlRenderTarget.h"
  12. #include "src/gpu/mtl/GrMtlTexture.h"
  13. #include "src/sksl/SkSLCompiler.h"
  14. #import <Metal/Metal.h>
  15. #if !__has_feature(objc_arc)
  16. #error This file must be compiled with Arc. Use -fobjc-arc flag
  17. #endif
  18. #define PRINT_MSL 0 // print out the MSL code generated
  19. bool GrPixelConfigToMTLFormat(GrPixelConfig config, MTLPixelFormat* format) {
  20. MTLPixelFormat dontCare;
  21. if (!format) {
  22. format = &dontCare;
  23. }
  24. switch (config) {
  25. case kUnknown_GrPixelConfig:
  26. return false;
  27. case kRGBA_8888_GrPixelConfig:
  28. *format = MTLPixelFormatRGBA8Unorm;
  29. return true;
  30. case kRGB_888_GrPixelConfig:
  31. *format = MTLPixelFormatRGBA8Unorm;
  32. return true;
  33. case kRGB_888X_GrPixelConfig:
  34. *format = MTLPixelFormatRGBA8Unorm;
  35. return true;
  36. case kRG_88_GrPixelConfig:
  37. *format = MTLPixelFormatRG8Unorm;
  38. return true;
  39. case kBGRA_8888_GrPixelConfig:
  40. *format = MTLPixelFormatBGRA8Unorm;
  41. return true;
  42. case kSRGBA_8888_GrPixelConfig:
  43. *format = MTLPixelFormatRGBA8Unorm_sRGB;
  44. return true;
  45. case kRGBA_1010102_GrPixelConfig:
  46. *format = MTLPixelFormatRGB10A2Unorm;
  47. return true;
  48. case kRGB_565_GrPixelConfig:
  49. #ifdef SK_BUILD_FOR_IOS
  50. *format = MTLPixelFormatB5G6R5Unorm;
  51. return true;
  52. #else
  53. return false;
  54. #endif
  55. case kRGBA_4444_GrPixelConfig:
  56. #ifdef SK_BUILD_FOR_IOS
  57. *format = MTLPixelFormatABGR4Unorm;
  58. return true;
  59. #else
  60. return false;
  61. #endif
  62. case kAlpha_8_GrPixelConfig: // fall through
  63. case kAlpha_8_as_Red_GrPixelConfig:
  64. *format = MTLPixelFormatR8Unorm;
  65. return true;
  66. case kAlpha_8_as_Alpha_GrPixelConfig:
  67. return false;
  68. case kGray_8_GrPixelConfig: // fall through
  69. case kGray_8_as_Red_GrPixelConfig:
  70. *format = MTLPixelFormatR8Unorm;
  71. return true;
  72. case kGray_8_as_Lum_GrPixelConfig:
  73. return false;
  74. case kRGBA_float_GrPixelConfig:
  75. *format = MTLPixelFormatRGBA32Float;
  76. return true;
  77. case kRGBA_half_GrPixelConfig:
  78. *format = MTLPixelFormatRGBA16Float;
  79. return true;
  80. case kRGBA_half_Clamped_GrPixelConfig:
  81. *format = MTLPixelFormatRGBA16Float;
  82. return true;
  83. case kAlpha_half_GrPixelConfig: // fall through
  84. case kAlpha_half_as_Red_GrPixelConfig:
  85. *format = MTLPixelFormatR16Float;
  86. return true;
  87. case kAlpha_half_as_Lum_GrPixelConfig:
  88. return false;
  89. case kRGB_ETC1_GrPixelConfig:
  90. #ifdef SK_BUILD_FOR_IOS
  91. *format = MTLPixelFormatETC2_RGB8;
  92. return true;
  93. #else
  94. return false;
  95. #endif
  96. case kR_16_GrPixelConfig:
  97. *format = MTLPixelFormatR16Unorm;
  98. return true;
  99. case kRG_1616_GrPixelConfig:
  100. *format = MTLPixelFormatRG16Unorm;
  101. return true;
  102. // Experimental (for Y416 and mutant P016/P010)
  103. case kRGBA_16161616_GrPixelConfig:
  104. *format = MTLPixelFormatRGBA16Unorm;
  105. return true;
  106. case kRG_half_GrPixelConfig:
  107. *format = MTLPixelFormatRG16Float;
  108. return true;
  109. }
  110. SK_ABORT("Unexpected config");
  111. return false;
  112. }
  113. MTLTextureDescriptor* GrGetMTLTextureDescriptor(id<MTLTexture> mtlTexture) {
  114. MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init];
  115. texDesc.textureType = mtlTexture.textureType;
  116. texDesc.pixelFormat = mtlTexture.pixelFormat;
  117. texDesc.width = mtlTexture.width;
  118. texDesc.height = mtlTexture.height;
  119. texDesc.depth = mtlTexture.depth;
  120. texDesc.mipmapLevelCount = mtlTexture.mipmapLevelCount;
  121. texDesc.arrayLength = mtlTexture.arrayLength;
  122. texDesc.sampleCount = mtlTexture.sampleCount;
  123. texDesc.usage = mtlTexture.usage;
  124. return texDesc;
  125. }
  126. #if PRINT_MSL
  127. void print_msl(const char* source) {
  128. SkTArray<SkString> lines;
  129. SkStrSplit(source, "\n", kStrict_SkStrSplitMode, &lines);
  130. for (int i = 0; i < lines.count(); i++) {
  131. SkString& line = lines[i];
  132. line.prependf("%4i\t", i + 1);
  133. SkDebugf("%s\n", line.c_str());
  134. }
  135. }
  136. #endif
  137. id<MTLLibrary> GrCompileMtlShaderLibrary(const GrMtlGpu* gpu,
  138. const char* shaderString,
  139. SkSL::Program::Kind kind,
  140. const SkSL::Program::Settings& settings,
  141. SkSL::Program::Inputs* outInputs) {
  142. std::unique_ptr<SkSL::Program> program =
  143. gpu->shaderCompiler()->convertProgram(kind,
  144. SkSL::String(shaderString),
  145. settings);
  146. if (!program) {
  147. SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str());
  148. SkASSERT(false);
  149. return nil;
  150. }
  151. *outInputs = program->fInputs;
  152. SkSL::String code;
  153. if (!gpu->shaderCompiler()->toMetal(*program, &code)) {
  154. SkDebugf("%s\n", gpu->shaderCompiler()->errorText().c_str());
  155. SkASSERT(false);
  156. return nil;
  157. }
  158. NSString* mtlCode = [[NSString alloc] initWithCString: code.c_str()
  159. encoding: NSASCIIStringEncoding];
  160. #if PRINT_MSL
  161. print_msl([mtlCode cStringUsingEncoding: NSASCIIStringEncoding]);
  162. #endif
  163. MTLCompileOptions* defaultOptions = [[MTLCompileOptions alloc] init];
  164. #if defined(SK_BUILD_FOR_MAC) && defined(GR_USE_COMPLETION_HANDLER)
  165. bool timedout;
  166. id<MTLLibrary> compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), mtlCode,
  167. defaultOptions, &timedout);
  168. if (timedout) {
  169. // try again
  170. compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), mtlCode,
  171. defaultOptions, &timedout);
  172. }
  173. #else
  174. NSError* error = nil;
  175. id<MTLLibrary> compiledLibrary = [gpu->device() newLibraryWithSource: mtlCode
  176. options: defaultOptions
  177. error: &error];
  178. if (error) {
  179. SkDebugf("Error compiling MSL shader: %s\n",
  180. [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
  181. return nil;
  182. }
  183. #endif
  184. return compiledLibrary;
  185. }
  186. id<MTLLibrary> GrMtlNewLibraryWithSource(id<MTLDevice> device, NSString* mslCode,
  187. MTLCompileOptions* options, bool* timedout) {
  188. dispatch_semaphore_t compilerSemaphore = dispatch_semaphore_create(0);
  189. __block dispatch_semaphore_t semaphore = compilerSemaphore;
  190. __block id<MTLLibrary> compiledLibrary;
  191. [device newLibraryWithSource: mslCode
  192. options: options
  193. completionHandler:
  194. ^(id<MTLLibrary> library, NSError* error) {
  195. if (error) {
  196. SkDebugf("Error compiling MSL shader: %s\n",
  197. [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
  198. }
  199. compiledLibrary = library;
  200. dispatch_semaphore_signal(semaphore);
  201. }
  202. ];
  203. // Wait 100 ms for the compiler
  204. if (dispatch_semaphore_wait(compilerSemaphore, dispatch_time(DISPATCH_TIME_NOW, 100000))) {
  205. SkDebugf("Timeout compiling MSL shader\n");
  206. *timedout = true;
  207. return nil;
  208. }
  209. *timedout = false;
  210. return compiledLibrary;
  211. }
  212. id<MTLRenderPipelineState> GrMtlNewRenderPipelineStateWithDescriptor(
  213. id<MTLDevice> device, MTLRenderPipelineDescriptor* pipelineDescriptor, bool* timedout) {
  214. dispatch_semaphore_t pipelineSemaphore = dispatch_semaphore_create(0);
  215. __block dispatch_semaphore_t semaphore = pipelineSemaphore;
  216. __block id<MTLRenderPipelineState> pipelineState;
  217. [device newRenderPipelineStateWithDescriptor: pipelineDescriptor
  218. completionHandler:
  219. ^(id<MTLRenderPipelineState> state, NSError* error) {
  220. if (error) {
  221. SkDebugf("Error creating pipeline: %s\n",
  222. [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
  223. }
  224. pipelineState = state;
  225. dispatch_semaphore_signal(semaphore);
  226. }
  227. ];
  228. // Wait 500 ms for pipeline creation
  229. if (dispatch_semaphore_wait(pipelineSemaphore, dispatch_time(DISPATCH_TIME_NOW, 500000))) {
  230. SkDebugf("Timeout creating pipeline.\n");
  231. *timedout = true;
  232. return nil;
  233. }
  234. *timedout = false;
  235. return pipelineState;
  236. }
  237. id<MTLTexture> GrGetMTLTextureFromSurface(GrSurface* surface) {
  238. id<MTLTexture> mtlTexture = nil;
  239. GrMtlRenderTarget* renderTarget = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget());
  240. GrMtlTexture* texture;
  241. if (renderTarget) {
  242. // We should not be using this for multisampled rendertargets
  243. if (renderTarget->numSamples() > 1) {
  244. SkASSERT(false);
  245. return nil;
  246. }
  247. mtlTexture = renderTarget->mtlColorTexture();
  248. } else {
  249. texture = static_cast<GrMtlTexture*>(surface->asTexture());
  250. if (texture) {
  251. mtlTexture = texture->mtlTexture();
  252. }
  253. }
  254. return mtlTexture;
  255. }
  256. //////////////////////////////////////////////////////////////////////////////
  257. // CPP Utils
  258. GrMTLPixelFormat GrGetMTLPixelFormatFromMtlTextureInfo(const GrMtlTextureInfo& info) {
  259. id<MTLTexture> mtlTexture = GrGetMTLTexture(info.fTexture.get());
  260. return static_cast<GrMTLPixelFormat>(mtlTexture.pixelFormat);
  261. }