Blender V4.3
mtl_texture_util.mm
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BKE_global.hh"
10
11#include "DNA_userdef_types.h"
12
13#include "GPU_batch.hh"
14#include "GPU_batch_presets.hh"
15#include "GPU_capabilities.hh"
16#include "GPU_framebuffer.hh"
17#include "GPU_platform.hh"
18#include "GPU_state.hh"
19
20#include "mtl_backend.hh"
21#include "mtl_context.hh"
22#include "mtl_texture.hh"
23
24/* Utility file for secondary functionality which supports mtl_texture.mm. */
25
28
29namespace blender::gpu {
30
31/* -------------------------------------------------------------------- */
36{
37 switch (tex_format) {
38 /* Texture & Render-Buffer Formats. */
39 case GPU_RGBA8UI:
40 return MTLPixelFormatRGBA8Uint;
41 case GPU_RGBA8I:
42 return MTLPixelFormatRGBA8Sint;
43 case GPU_RGBA8:
44 return MTLPixelFormatRGBA8Unorm;
45 case GPU_RGBA32UI:
46 return MTLPixelFormatRGBA32Uint;
47 case GPU_RGBA32I:
48 return MTLPixelFormatRGBA32Sint;
49 case GPU_RGBA32F:
50 return MTLPixelFormatRGBA32Float;
51 case GPU_RGBA16UI:
52 return MTLPixelFormatRGBA16Uint;
53 case GPU_RGBA16I:
54 return MTLPixelFormatRGBA16Sint;
55 case GPU_RGBA16F:
56 return MTLPixelFormatRGBA16Float;
57 case GPU_RGBA16:
58 return MTLPixelFormatRGBA16Unorm;
59 case GPU_RG8UI:
60 return MTLPixelFormatRG8Uint;
61 case GPU_RG8I:
62 return MTLPixelFormatRG8Sint;
63 case GPU_RG8:
64 return MTLPixelFormatRG8Unorm;
65 case GPU_RG32UI:
66 return MTLPixelFormatRG32Uint;
67 case GPU_RG32I:
68 return MTLPixelFormatRG32Sint;
69 case GPU_RG32F:
70 return MTLPixelFormatRG32Float;
71 case GPU_RG16UI:
72 return MTLPixelFormatRG16Uint;
73 case GPU_RG16I:
74 return MTLPixelFormatRG16Sint;
75 case GPU_RG16F:
76 return MTLPixelFormatRG16Float;
77 case GPU_RG16:
78 return MTLPixelFormatRG16Unorm;
79 case GPU_R8UI:
80 return MTLPixelFormatR8Uint;
81 case GPU_R8I:
82 return MTLPixelFormatR8Sint;
83 case GPU_R8:
84 return MTLPixelFormatR8Unorm;
85 case GPU_R32UI:
86 return MTLPixelFormatR32Uint;
87 case GPU_R32I:
88 return MTLPixelFormatR32Sint;
89 case GPU_R32F:
90 return MTLPixelFormatR32Float;
91 case GPU_R16UI:
92 return MTLPixelFormatR16Uint;
93 case GPU_R16I:
94 return MTLPixelFormatR16Sint;
95 case GPU_R16F:
96 return MTLPixelFormatR16Float;
97 case GPU_R16:
98 return MTLPixelFormatR16Unorm;
99 /* Special formats texture & render-buffer. */
100 case GPU_RGB10_A2:
101 return MTLPixelFormatRGB10A2Unorm;
102 case GPU_RGB10_A2UI:
103 return MTLPixelFormatRGB10A2Uint;
105 return MTLPixelFormatRG11B10Float;
107 /* NOTE(fclem): DEPTH24_STENCIL8 not supported by Apple Silicon. Fallback to Depth32F8S. */
109 return MTLPixelFormatDepth32Float_Stencil8;
110 case GPU_SRGB8_A8:
111 return MTLPixelFormatRGBA8Unorm_sRGB;
112 /* Texture only formats. */
113 case GPU_RGB16F:
114 /* 48-Bit pixel format are not supported. Emulate using a padded type with alpha. */
115 return MTLPixelFormatRGBA16Float;
116 case GPU_RGBA16_SNORM:
117 return MTLPixelFormatRGBA16Snorm;
118 case GPU_RGBA8_SNORM:
119 return MTLPixelFormatRGBA8Snorm;
120 case GPU_RGB32F:
121 /* 96-Bit pixel format are not supported. Emulate using a padded type with alpha. */
122 return MTLPixelFormatRGBA32Float;
123 case GPU_RGB32I:
124 /* 96-Bit pixel format are not supported. Emulate using a padded type with alpha. */
125 return MTLPixelFormatRGBA32Sint;
126 case GPU_RGB32UI:
127 /* 96-Bit pixel format are not supported. Emulate using a padded type with alpha. */
128 return MTLPixelFormatRGBA32Uint;
129 case GPU_RGB16_SNORM:
130 /* 48-Bit pixel format are not supported. Emulate using a padded type with alpha. */
131 return MTLPixelFormatRGBA16Snorm;
132 case GPU_RGB16I:
133 /* 48-Bit pixel format are not supported. Emulate using a padded type with alpha. */
134 return MTLPixelFormatRGBA16Sint;
135 case GPU_RGB16UI:
136 /* 48-Bit pixel format are not supported. Emulate using a padded type with alpha. */
137 return MTLPixelFormatRGBA16Uint;
138 case GPU_RGB16:
139 /* 48-Bit pixel format are not supported. Emulate using a padded type with alpha. */
140 return MTLPixelFormatRGBA16Unorm;
141 case GPU_RGB8_SNORM:
142 /* 24-Bit pixel format are not supported. Emulate using a padded type with alpha. */
143 return MTLPixelFormatRGBA8Snorm;
144 case GPU_RGB8:
145 /* 24-Bit pixel format are not supported. Emulate using a padded type with alpha. */
146 return MTLPixelFormatRGBA8Unorm;
147 case GPU_RGB8I:
148 /* 24-Bit pixel format are not supported. Emulate using a padded type with alpha. */
149 return MTLPixelFormatRGBA8Sint;
150 case GPU_RGB8UI:
151 /* 24-Bit pixel format are not supported. Emulate using a padded type with alpha. */
152 return MTLPixelFormatRGBA8Uint;
153 case GPU_RG16_SNORM:
154 return MTLPixelFormatRG16Snorm;
155 case GPU_RG8_SNORM:
156 return MTLPixelFormatRG8Snorm;
157 case GPU_R16_SNORM:
158 return MTLPixelFormatR16Snorm;
159 case GPU_R8_SNORM:
160 return MTLPixelFormatR8Snorm;
161 /* Special formats, texture only. */
163 return MTLPixelFormatBC1_RGBA_sRGB;
165 return MTLPixelFormatBC2_RGBA_sRGB;
167 return MTLPixelFormatBC3_RGBA_sRGB;
168 case GPU_RGBA8_DXT1:
169 return MTLPixelFormatBC1_RGBA;
170 case GPU_RGBA8_DXT3:
171 return MTLPixelFormatBC2_RGBA;
172 case GPU_RGBA8_DXT5:
173 return MTLPixelFormatBC3_RGBA;
174 case GPU_SRGB8:
175 /* 24-Bit pixel format are not supported. Emulate using a padded type with alpha. */
176 return MTLPixelFormatRGBA8Unorm_sRGB;
177 case GPU_RGB9_E5:
178 return MTLPixelFormatRGB9E5Float;
179 /* Depth Formats. */
181 return MTLPixelFormatDepth32Float;
183 /* This formal is not supported on Metal.
184 * Use 32Float depth instead with some conversion steps for download and upload. */
185 return MTLPixelFormatDepth32Float;
187 return MTLPixelFormatDepth16Unorm;
188 }
189 BLI_assert_msg(false, "Unrecognised GPU pixel format!\n");
190 return MTLPixelFormatRGBA8Unorm;
191}
192
193size_t get_mtl_format_bytesize(MTLPixelFormat tex_format)
194{
195 switch (tex_format) {
196 case MTLPixelFormatRGBA8Uint:
197 case MTLPixelFormatRGBA8Sint:
198 case MTLPixelFormatRGBA8Unorm:
199 case MTLPixelFormatRGBA8Snorm:
200 case MTLPixelFormatRGB10A2Uint:
201 case MTLPixelFormatRGB10A2Unorm:
202 return 4;
203 case MTLPixelFormatRGBA32Uint:
204 case MTLPixelFormatRGBA32Sint:
205 case MTLPixelFormatRGBA32Float:
206 return 16;
207 case MTLPixelFormatRGBA16Uint:
208 case MTLPixelFormatRGBA16Sint:
209 case MTLPixelFormatRGBA16Float:
210 case MTLPixelFormatRGBA16Unorm:
211 case MTLPixelFormatRGBA16Snorm:
212 return 8;
213 case MTLPixelFormatRG8Uint:
214 case MTLPixelFormatRG8Sint:
215 case MTLPixelFormatRG8Unorm:
216 case MTLPixelFormatRG8Snorm:
217 case MTLPixelFormatRG8Unorm_sRGB:
218 return 2;
219 case MTLPixelFormatRG32Uint:
220 case MTLPixelFormatRG32Sint:
221 case MTLPixelFormatRG32Float:
222 return 8;
223 case MTLPixelFormatRG16Uint:
224 case MTLPixelFormatRG16Sint:
225 case MTLPixelFormatRG16Float:
226 case MTLPixelFormatRG16Unorm:
227 case MTLPixelFormatRG16Snorm:
228 return 4;
229 case MTLPixelFormatR8Uint:
230 case MTLPixelFormatR8Sint:
231 case MTLPixelFormatR8Unorm:
232 case MTLPixelFormatR8Snorm:
233 return 1;
234 case MTLPixelFormatR32Uint:
235 case MTLPixelFormatR32Sint:
236 case MTLPixelFormatR32Float:
237 return 4;
238 case MTLPixelFormatR16Uint:
239 case MTLPixelFormatR16Sint:
240 case MTLPixelFormatR16Float:
241 case MTLPixelFormatR16Snorm:
242 case MTLPixelFormatR16Unorm:
243 return 2;
244 case MTLPixelFormatRG11B10Float:
245 return 4;
246 case MTLPixelFormatDepth32Float_Stencil8:
247 return 8;
248 case MTLPixelFormatRGBA8Unorm_sRGB:
249 case MTLPixelFormatDepth32Float:
250 case MTLPixelFormatDepth24Unorm_Stencil8:
251 return 4;
252 case MTLPixelFormatDepth16Unorm:
253 return 2;
254 case MTLPixelFormatBC1_RGBA:
255 case MTLPixelFormatBC1_RGBA_sRGB:
256 return 1; /* NOTE: not quite correct (BC1 is 0.5 BPP). */
257 case MTLPixelFormatBC2_RGBA:
258 case MTLPixelFormatBC2_RGBA_sRGB:
259 case MTLPixelFormatBC3_RGBA:
260 case MTLPixelFormatBC3_RGBA_sRGB:
261 return 1;
262
263 default:
264 BLI_assert_msg(false, "Unrecognised GPU pixel format!\n");
265 return 1;
266 }
267}
268
269int get_mtl_format_num_components(MTLPixelFormat tex_format)
270{
271 switch (tex_format) {
272 case MTLPixelFormatRGBA8Uint:
273 case MTLPixelFormatRGBA8Sint:
274 case MTLPixelFormatRGBA8Unorm:
275 case MTLPixelFormatRGBA8Snorm:
276 case MTLPixelFormatRGBA32Uint:
277 case MTLPixelFormatRGBA32Sint:
278 case MTLPixelFormatRGBA32Float:
279 case MTLPixelFormatRGBA16Uint:
280 case MTLPixelFormatRGBA16Sint:
281 case MTLPixelFormatRGBA16Float:
282 case MTLPixelFormatRGBA16Unorm:
283 case MTLPixelFormatRGBA16Snorm:
284 case MTLPixelFormatRGBA8Unorm_sRGB:
285 case MTLPixelFormatRGB10A2Uint:
286 case MTLPixelFormatRGB10A2Unorm:
287 case MTLPixelFormatBC1_RGBA_sRGB:
288 case MTLPixelFormatBC2_RGBA_sRGB:
289 case MTLPixelFormatBC3_RGBA_sRGB:
290 case MTLPixelFormatBC1_RGBA:
291 case MTLPixelFormatBC2_RGBA:
292 case MTLPixelFormatBC3_RGBA:
293 return 4;
294
295 case MTLPixelFormatRG11B10Float:
296 return 3;
297
298 case MTLPixelFormatRG8Uint:
299 case MTLPixelFormatRG8Sint:
300 case MTLPixelFormatRG8Unorm:
301 case MTLPixelFormatRG32Uint:
302 case MTLPixelFormatRG32Sint:
303 case MTLPixelFormatRG32Float:
304 case MTLPixelFormatRG16Uint:
305 case MTLPixelFormatRG16Sint:
306 case MTLPixelFormatRG16Float:
307 case MTLPixelFormatDepth32Float_Stencil8:
308 case MTLPixelFormatRG16Snorm:
309 case MTLPixelFormatRG16Unorm:
310 case MTLPixelFormatRG8Snorm:
311 return 2;
312
313 case MTLPixelFormatR8Uint:
314 case MTLPixelFormatR8Sint:
315 case MTLPixelFormatR8Unorm:
316 case MTLPixelFormatR8Snorm:
317 case MTLPixelFormatR32Uint:
318 case MTLPixelFormatR32Sint:
319 case MTLPixelFormatR32Float:
320 case MTLPixelFormatR16Uint:
321 case MTLPixelFormatR16Sint:
322 case MTLPixelFormatR16Float:
323 case MTLPixelFormatR16Unorm:
324 case MTLPixelFormatR16Snorm:
325 case MTLPixelFormatDepth32Float:
326 case MTLPixelFormatDepth16Unorm:
327 case MTLPixelFormatDepth24Unorm_Stencil8:
328 /* Treating this format as single-channel for direct data copies -- Stencil component is not
329 * addressable. */
330 return 1;
331
332 default:
333 BLI_assert_msg(false, "Unrecognised GPU pixel format!\n");
334 return 1;
335 }
336}
337
339{
340 /* Add formats as needed -- Verify platforms. */
341 const MTLCapabilities &capabilities = MTLBackend::get_capabilities();
342
343 if (capabilities.supports_family_mac1 || capabilities.supports_family_mac_catalyst1) {
344
345 switch (format) {
346 case MTLPixelFormatA8Unorm:
347 case MTLPixelFormatR8Uint:
348 case MTLPixelFormatR8Sint:
349 case MTLPixelFormatR16Uint:
350 case MTLPixelFormatR16Sint:
351 case MTLPixelFormatRG32Uint:
352 case MTLPixelFormatRG32Sint:
353 case MTLPixelFormatRGBA8Uint:
354 case MTLPixelFormatRGBA8Sint:
355 case MTLPixelFormatRGBA32Uint:
356 case MTLPixelFormatRGBA32Sint:
357 case MTLPixelFormatDepth16Unorm:
358 case MTLPixelFormatDepth32Float:
359 case MTLPixelFormatInvalid:
360 case MTLPixelFormatBGR10A2Unorm:
361 case MTLPixelFormatRGB10A2Uint:
362 return false;
363 default:
364 return true;
365 }
366 }
367 else {
368 switch (format) {
369 case MTLPixelFormatA8Unorm:
370 case MTLPixelFormatR8Uint:
371 case MTLPixelFormatR8Sint:
372 case MTLPixelFormatR16Uint:
373 case MTLPixelFormatR16Sint:
374 case MTLPixelFormatRG32Uint:
375 case MTLPixelFormatRG32Sint:
376 case MTLPixelFormatRGBA8Uint:
377 case MTLPixelFormatRGBA8Sint:
378 case MTLPixelFormatRGBA32Uint:
379 case MTLPixelFormatRGBA32Sint:
380 case MTLPixelFormatRGBA32Float:
381 case MTLPixelFormatDepth16Unorm:
382 case MTLPixelFormatDepth32Float:
383 case MTLPixelFormatInvalid:
384 case MTLPixelFormatBGR10A2Unorm:
385 case MTLPixelFormatRGB10A2Uint:
386 return false;
387 default:
388 return true;
389 }
390 }
391}
392
395/* -------------------------------------------------------------------- */
399id<MTLComputePipelineState> gpu::MTLTexture::mtl_texture_update_impl(
400 TextureUpdateRoutineSpecialisation specialization_params,
401 blender::Map<TextureUpdateRoutineSpecialisation, id<MTLComputePipelineState>>
402 &specialization_cache,
403 eGPUTextureType texture_type)
404{
405 /* Check whether the Kernel exists. */
406 id<MTLComputePipelineState> *result = specialization_cache.lookup_ptr(specialization_params);
407 if (result != nullptr) {
408 return *result;
409 }
410
411 id<MTLComputePipelineState> return_pso = nil;
412 @autoreleasepool {
413
414 /* Fetch active context. */
415 MTLContext *ctx = MTLContext::get();
416 BLI_assert(ctx);
417
419 NSString *tex_update_kernel_src = [NSString
420 stringWithUTF8String:datatoc_compute_texture_update_msl];
421
422 /* Prepare options and specializations. */
423 MTLCompileOptions *options = [[[MTLCompileOptions alloc] init] autorelease];
424 options.languageVersion = MTLLanguageVersion2_2;
425 options.preprocessorMacros = @{
426 @"INPUT_DATA_TYPE" :
427 [NSString stringWithUTF8String:specialization_params.input_data_type.c_str()],
428 @"OUTPUT_DATA_TYPE" :
429 [NSString stringWithUTF8String:specialization_params.output_data_type.c_str()],
430 @"COMPONENT_COUNT_INPUT" :
431 [NSNumber numberWithInt:specialization_params.component_count_input],
432 @"COMPONENT_COUNT_OUTPUT" :
433 [NSNumber numberWithInt:specialization_params.component_count_output],
434 @"TEX_TYPE" : [NSNumber numberWithInt:((int)(texture_type))],
435 @"IS_TEXTURE_CLEAR" :
436 [NSNumber numberWithInt:((int)(specialization_params.is_clear ? 1 : 0))]
437 };
438
439 /* Prepare shader library for conversion routine. */
440 NSError *error = nullptr;
441 id<MTLLibrary> temp_lib = [[ctx->device newLibraryWithSource:tex_update_kernel_src
443 error:&error] autorelease];
444 if (error) {
445 /* Only exit out if genuine error and not warning. */
446 if ([[error localizedDescription] rangeOfString:@"Compilation succeeded"].location ==
447 NSNotFound)
448 {
449 NSLog(@"Compile Error - Metal Shader Library error %@ ", error);
450 BLI_assert(false);
451 return nil;
452 }
453 }
454
455 /* Fetch compute function. */
456 BLI_assert(temp_lib != nil);
457 id<MTLFunction> temp_compute_function = [[temp_lib
458 newFunctionWithName:@"compute_texture_update"] autorelease];
459 BLI_assert(temp_compute_function);
460
461 /* Otherwise, bake new Kernel. */
462 id<MTLComputePipelineState> compute_pso = [ctx->device
463 newComputePipelineStateWithFunction:temp_compute_function
464 error:&error];
465 if (error || compute_pso == nil) {
466 NSLog(@"Failed to prepare texture_update MTLComputePipelineState %@", error);
467 BLI_assert(false);
468 }
469
470 /* Store PSO. */
471 specialization_cache.add_new(specialization_params, compute_pso);
472 return_pso = compute_pso;
473 }
474
475 BLI_assert(return_pso != nil);
476 return return_pso;
477}
478
479id<MTLComputePipelineState> gpu::MTLTexture::texture_update_1d_get_kernel(
481{
482 MTLContext *mtl_context = MTLContext::get();
483 BLI_assert(mtl_context != nullptr);
484 return mtl_texture_update_impl(specialization,
485 mtl_context->get_texture_utils().texture_1d_update_compute_psos,
487}
488
489id<MTLComputePipelineState> gpu::MTLTexture::texture_update_1d_array_get_kernel(
491{
492 MTLContext *mtl_context = MTLContext::get();
493 BLI_assert(mtl_context != nullptr);
494 return mtl_texture_update_impl(
495 specialization,
496 mtl_context->get_texture_utils().texture_1d_array_update_compute_psos,
498}
499
500id<MTLComputePipelineState> gpu::MTLTexture::texture_update_2d_get_kernel(
502{
503 MTLContext *mtl_context = MTLContext::get();
504 BLI_assert(mtl_context != nullptr);
505 return mtl_texture_update_impl(specialization,
506 mtl_context->get_texture_utils().texture_2d_update_compute_psos,
508}
509
510id<MTLComputePipelineState> gpu::MTLTexture::texture_update_2d_array_get_kernel(
512{
513 MTLContext *mtl_context = MTLContext::get();
514 BLI_assert(mtl_context != nullptr);
515 return mtl_texture_update_impl(
516 specialization,
517 mtl_context->get_texture_utils().texture_2d_array_update_compute_psos,
519}
520
521id<MTLComputePipelineState> gpu::MTLTexture::texture_update_3d_get_kernel(
523{
524 MTLContext *mtl_context = MTLContext::get();
525 BLI_assert(mtl_context != nullptr);
526 return mtl_texture_update_impl(specialization,
527 mtl_context->get_texture_utils().texture_3d_update_compute_psos,
529}
530
531/* TODO(Metal): Data upload routine kernel for texture cube and texture cube array.
532 * Currently does not appear to be hit. */
533
534GPUShader *gpu::MTLTexture::depth_2d_update_sh_get(
536{
537
538 /* Check whether the Kernel exists. */
539 MTLContext *mtl_context = MTLContext::get();
540 BLI_assert(mtl_context != nullptr);
541
542 GPUShader **result = mtl_context->get_texture_utils().depth_2d_update_shaders.lookup_ptr(
543 specialization);
544 if (result != nullptr) {
545 return *result;
546 }
547
548 const char *depth_2d_info_variant = nullptr;
549 switch (specialization.data_mode) {
551 depth_2d_info_variant = "depth_2d_update_float";
552 break;
554 depth_2d_info_variant = "depth_2d_update_int24";
555 break;
557 depth_2d_info_variant = "depth_2d_update_int32";
558 break;
559 default:
560 BLI_assert(false && "Invalid format mode\n");
561 return nullptr;
562 }
563
564 GPUShader *shader = GPU_shader_create_from_info_name(depth_2d_info_variant);
565 mtl_context->get_texture_utils().depth_2d_update_shaders.add_new(specialization, shader);
566 return shader;
567}
568
569GPUShader *gpu::MTLTexture::fullscreen_blit_sh_get()
570{
571 MTLContext *mtl_context = MTLContext::get();
572 BLI_assert(mtl_context != nullptr);
573 if (mtl_context->get_texture_utils().fullscreen_blit_shader == nullptr) {
574 GPUShader *shader = GPU_shader_create_from_info_name("fullscreen_blit");
575
576 mtl_context->get_texture_utils().fullscreen_blit_shader = shader;
577 }
578 return mtl_context->get_texture_utils().fullscreen_blit_shader;
579}
580
581/* Special routine for updating 2D depth textures using the rendering pipeline. */
582void gpu::MTLTexture::update_sub_depth_2d(
583 int mip, int offset[3], int extent[3], eGPUDataFormat type, const void *data)
584{
585 /* Verify we are in a valid configuration. */
586 BLI_assert(ELEM(format_,
592 BLI_assert(validate_data_format(format_, type));
594
595 /* Determine whether we are in GPU_DATA_UINT_24_8 or GPU_DATA_FLOAT mode. */
596 bool is_float = (type == GPU_DATA_FLOAT);
597 eGPUTextureFormat format = (is_float) ? GPU_R32F : GPU_R32I;
598
599 /* Shader key - Add parameters here for different configurations. */
601 switch (type) {
602 case GPU_DATA_FLOAT:
603 specialization.data_mode = MTL_DEPTH_UPDATE_MODE_FLOAT;
604 break;
605
607 specialization.data_mode = MTL_DEPTH_UPDATE_MODE_INT24;
608 break;
609
610 case GPU_DATA_UINT:
611 specialization.data_mode = MTL_DEPTH_UPDATE_MODE_INT32;
612 break;
613
614 default:
615 BLI_assert_msg(false, "Unsupported eGPUDataFormat being passed to depth texture update\n");
616 return;
617 }
618
619 /* Push contents into an r32_tex and render contents to depth using a shader. */
620 GPUTexture *r32_tex_tmp = GPU_texture_create_2d("depth_intermediate_copy_tex",
621 w_,
622 h_,
623 1,
624 format,
627 nullptr);
628 GPU_texture_filter_mode(r32_tex_tmp, false);
630 gpu::MTLTexture *mtl_tex = static_cast<gpu::MTLTexture *>(unwrap(r32_tex_tmp));
631 mtl_tex->update_sub(mip, offset, extent, type, data);
632
633 GPUFrameBuffer *restore_fb = GPU_framebuffer_active_get();
634 GPUFrameBuffer *depth_fb_temp = GPU_framebuffer_create("depth_intermediate_copy_fb");
635 GPU_framebuffer_texture_attach(depth_fb_temp, wrap(static_cast<Texture *>(this)), 0, mip);
636 GPU_framebuffer_bind(depth_fb_temp);
637 if (extent[0] == w_ && extent[1] == h_) {
638 /* Skip load if the whole texture is being updated. */
639 GPU_framebuffer_clear_depth(depth_fb_temp, 0.0);
640 GPU_framebuffer_clear_stencil(depth_fb_temp, 0);
641 }
642
643 GPUShader *depth_2d_update_sh = depth_2d_update_sh_get(specialization);
644 BLI_assert(depth_2d_update_sh != nullptr);
645 Batch *quad = GPU_batch_preset_quad();
646 GPU_batch_set_shader(quad, depth_2d_update_sh);
647
648 GPU_batch_texture_bind(quad, "source_data", r32_tex_tmp);
649 GPU_batch_uniform_1i(quad, "mip", mip);
650 GPU_batch_uniform_2f(quad, "extent", (float)extent[0], (float)extent[1]);
651 GPU_batch_uniform_2f(quad, "offset", (float)offset[0], (float)offset[1]);
652 GPU_batch_uniform_2f(quad, "size", (float)w_, (float)h_);
653
654 bool depth_write_prev = GPU_depth_mask_get();
655 uint stencil_mask_prev = GPU_stencil_mask_get();
656 eGPUDepthTest depth_test_prev = GPU_depth_test_get();
657 eGPUStencilTest stencil_test_prev = GPU_stencil_test_get();
658 GPU_scissor_test(true);
659 GPU_scissor(offset[0], offset[1], extent[0], extent[1]);
660
664 GPU_depth_mask(true);
666
668
669 GPU_depth_mask(depth_write_prev);
670 GPU_stencil_write_mask_set(stencil_mask_prev);
671 GPU_stencil_test(stencil_test_prev);
672 GPU_depth_test(depth_test_prev);
673
674 if (restore_fb != nullptr) {
675 GPU_framebuffer_bind(restore_fb);
676 }
677 else {
679 }
680 GPU_framebuffer_free(depth_fb_temp);
681 GPU_texture_free(r32_tex_tmp);
682}
685/* -------------------------------------------------------------------- */
689id<MTLComputePipelineState> gpu::MTLTexture::mtl_texture_read_impl(
690 TextureReadRoutineSpecialisation specialization_params,
691 blender::Map<TextureReadRoutineSpecialisation, id<MTLComputePipelineState>>
692 &specialization_cache,
693 eGPUTextureType texture_type)
694{
695 /* Check whether the Kernel exists. */
696 id<MTLComputePipelineState> *result = specialization_cache.lookup_ptr(specialization_params);
697 if (result != nullptr) {
698 return *result;
699 }
700
701 id<MTLComputePipelineState> return_pso = nil;
702 @autoreleasepool {
703
704 /* Fetch active context. */
705 MTLContext *ctx = MTLContext::get();
706 BLI_assert(ctx);
707
709 NSString *tex_update_kernel_src = [NSString
710 stringWithUTF8String:datatoc_compute_texture_read_msl];
711
712 /* Defensive Debug Checks. */
713 int64_t depth_scale_factor = 1;
714 if (specialization_params.depth_format_mode > 0) {
715 BLI_assert(specialization_params.component_count_input == 1);
716 BLI_assert(specialization_params.component_count_output == 1);
717 switch (specialization_params.depth_format_mode) {
718 case 1:
719 /* FLOAT */
720 depth_scale_factor = 1;
721 break;
722 case 2:
723 /* D24 uint */
724 depth_scale_factor = 0xFFFFFFu;
725 break;
726 case 4:
727 /* D32 uint */
728 depth_scale_factor = 0xFFFFFFFFu;
729 break;
730 default:
731 BLI_assert_msg(0, "Unrecognized mode");
732 break;
733 }
734 }
735
736 /* Prepare options and specializations. */
737 MTLCompileOptions *options = [[[MTLCompileOptions alloc] init] autorelease];
738 options.languageVersion = MTLLanguageVersion2_2;
739 options.preprocessorMacros = @{
740 @"INPUT_DATA_TYPE" :
741 [NSString stringWithUTF8String:specialization_params.input_data_type.c_str()],
742 @"OUTPUT_DATA_TYPE" :
743 [NSString stringWithUTF8String:specialization_params.output_data_type.c_str()],
744 @"COMPONENT_COUNT_INPUT" :
745 [NSNumber numberWithInt:specialization_params.component_count_input],
746 @"COMPONENT_COUNT_OUTPUT" :
747 [NSNumber numberWithInt:specialization_params.component_count_output],
748 @"WRITE_COMPONENT_COUNT" :
749 [NSNumber numberWithInt:min_ii(specialization_params.component_count_input,
750 specialization_params.component_count_output)],
751 @"IS_DEPTH_FORMAT" :
752 [NSNumber numberWithInt:((specialization_params.depth_format_mode > 0) ? 1 : 0)],
753 @"DEPTH_SCALE_FACTOR" : [NSNumber numberWithLongLong:depth_scale_factor],
754 @"TEX_TYPE" : [NSNumber numberWithInt:((int)(texture_type))],
755 @"IS_DEPTHSTENCIL_24_8" :
756 [NSNumber numberWithInt:(specialization_params.depth_format_mode == 2) ? 1 : 0]
757 };
758
759 /* Prepare shader library for conversion routine. */
760 NSError *error = nullptr;
761 id<MTLLibrary> temp_lib = [[ctx->device newLibraryWithSource:tex_update_kernel_src
763 error:&error] autorelease];
764 if (error) {
765 /* Only exit out if genuine error and not warning. */
766 if ([[error localizedDescription] rangeOfString:@"Compilation succeeded"].location ==
767 NSNotFound)
768 {
769 NSLog(@"Compile Error - Metal Shader Library error %@ ", error);
770 BLI_assert(false);
771 return nil;
772 }
773 }
774
775 /* Fetch compute function. */
776 BLI_assert(temp_lib != nil);
777 id<MTLFunction> temp_compute_function = [[temp_lib newFunctionWithName:@"compute_texture_read"]
778 autorelease];
779 BLI_assert(temp_compute_function);
780
781 /* Otherwise, bake new Kernel. */
782 id<MTLComputePipelineState> compute_pso = [ctx->device
783 newComputePipelineStateWithFunction:temp_compute_function
784 error:&error];
785 if (error || compute_pso == nil) {
786 NSLog(@"Failed to prepare texture_read MTLComputePipelineState %@", error);
787 BLI_assert(false);
788 return nil;
789 }
790
791 /* Store PSO. */
792 specialization_cache.add_new(specialization_params, compute_pso);
793 return_pso = compute_pso;
794 }
795
796 BLI_assert(return_pso != nil);
797 return return_pso;
798}
799
800id<MTLComputePipelineState> gpu::MTLTexture::texture_read_2d_get_kernel(
802{
803 MTLContext *mtl_context = MTLContext::get();
804 BLI_assert(mtl_context != nullptr);
805 return mtl_texture_read_impl(specialization,
806 mtl_context->get_texture_utils().texture_2d_read_compute_psos,
808}
809
810id<MTLComputePipelineState> gpu::MTLTexture::texture_read_2d_array_get_kernel(
812{
813 MTLContext *mtl_context = MTLContext::get();
814 BLI_assert(mtl_context != nullptr);
815 return mtl_texture_read_impl(specialization,
816 mtl_context->get_texture_utils().texture_2d_array_read_compute_psos,
818}
819
820id<MTLComputePipelineState> gpu::MTLTexture::texture_read_1d_get_kernel(
822{
823 MTLContext *mtl_context = MTLContext::get();
824 BLI_assert(mtl_context != nullptr);
825 return mtl_texture_read_impl(specialization,
826 mtl_context->get_texture_utils().texture_1d_read_compute_psos,
828}
829
830id<MTLComputePipelineState> gpu::MTLTexture::texture_read_1d_array_get_kernel(
832{
833 MTLContext *mtl_context = MTLContext::get();
834 BLI_assert(mtl_context != nullptr);
835 return mtl_texture_read_impl(specialization,
836 mtl_context->get_texture_utils().texture_1d_array_read_compute_psos,
838}
839
840id<MTLComputePipelineState> gpu::MTLTexture::texture_read_3d_get_kernel(
842{
843 MTLContext *mtl_context = MTLContext::get();
844 BLI_assert(mtl_context != nullptr);
845 return mtl_texture_read_impl(specialization,
846 mtl_context->get_texture_utils().texture_3d_read_compute_psos,
848}
849
852} // namespace blender::gpu
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
MINLINE int min_ii(int a, int b)
unsigned int uint
#define ELEM(...)
#define GPU_batch_texture_bind(batch, name, tex)
Definition GPU_batch.hh:316
void GPU_batch_set_shader(blender::gpu::Batch *batch, GPUShader *shader)
void GPU_batch_draw(blender::gpu::Batch *batch)
#define GPU_batch_uniform_2f(batch, name, x, y)
Definition GPU_batch.hh:300
#define GPU_batch_uniform_1i(batch, name, x)
Definition GPU_batch.hh:297
blender::gpu::Batch * GPU_batch_preset_quad()
GPUFrameBuffer * GPU_framebuffer_create(const char *name)
GPUFrameBuffer * GPU_framebuffer_active_get()
void GPU_framebuffer_restore()
void GPU_framebuffer_clear_stencil(GPUFrameBuffer *fb, uint clear_stencil)
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
void GPU_framebuffer_clear_depth(GPUFrameBuffer *fb, float clear_depth)
void GPU_framebuffer_free(GPUFrameBuffer *framebuffer)
void GPU_framebuffer_texture_attach(GPUFrameBuffer *framebuffer, GPUTexture *texture, int slot, int mip)
GPUShader * GPU_shader_create_from_info_name(const char *info_name)
void GPU_scissor_test(bool enable)
Definition gpu_state.cc:183
void GPU_depth_mask(bool depth)
Definition gpu_state.cc:110
eGPUDepthTest GPU_depth_test_get()
Definition gpu_state.cc:239
void GPU_stencil_test(eGPUStencilTest test)
Definition gpu_state.cc:73
void GPU_stencil_write_mask_set(uint write_mask)
Definition gpu_state.cc:205
void GPU_stencil_reference_set(uint reference)
Definition gpu_state.cc:200
void GPU_scissor(int x, int y, int width, int height)
Definition gpu_state.cc:188
eGPUStencilTest GPU_stencil_test_get()
Definition gpu_state.cc:245
eGPUDepthTest
Definition GPU_state.hh:107
@ GPU_DEPTH_ALWAYS
Definition GPU_state.hh:109
uint GPU_stencil_mask_get()
Definition gpu_state.cc:233
eGPUStencilTest
Definition GPU_state.hh:117
@ GPU_STENCIL_ALWAYS
Definition GPU_state.hh:119
void GPU_depth_test(eGPUDepthTest test)
Definition gpu_state.cc:68
bool GPU_depth_mask_get()
Definition gpu_state.cc:276
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(GPUTexture *texture)
eGPUDataFormat
@ GPU_DATA_UINT_24_8
@ GPU_DATA_UINT
@ GPU_DATA_FLOAT
void GPU_texture_extend_mode(GPUTexture *texture, GPUSamplerExtendMode extend_mode)
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
@ GPU_SAMPLER_EXTEND_MODE_EXTEND
void GPU_texture_filter_mode(GPUTexture *texture, bool use_filter)
eGPUTextureFormat
@ GPU_RGB16
@ GPU_R16UI
@ GPU_RGB8
@ GPU_DEPTH32F_STENCIL8
@ GPU_SRGB8
@ GPU_R16I
@ GPU_SRGB8_A8
@ GPU_RG8_SNORM
@ GPU_DEPTH24_STENCIL8
@ GPU_RGB10_A2
@ GPU_RGB8I
@ GPU_R32I
@ GPU_RGBA8_SNORM
@ GPU_RGB10_A2UI
@ GPU_RG8UI
@ GPU_RGB16I
@ GPU_RGBA16_SNORM
@ GPU_RGB9_E5
@ GPU_SRGB8_A8_DXT5
@ GPU_RG8I
@ GPU_RG16I
@ GPU_RG32UI
@ GPU_RGB32I
@ GPU_RG8
@ GPU_RG32I
@ GPU_SRGB8_A8_DXT1
@ GPU_RGBA32UI
@ GPU_R8I
@ GPU_R16
@ GPU_RG16UI
@ GPU_RGBA8I
@ GPU_RGBA8_DXT1
@ GPU_RGBA8UI
@ GPU_RGB32F
@ GPU_RGBA16UI
@ GPU_RGBA16I
@ GPU_R8UI
@ GPU_RGBA16
@ GPU_SRGB8_A8_DXT3
@ GPU_RGB8_SNORM
@ GPU_RGBA8_DXT3
@ GPU_RGB32UI
@ GPU_R8_SNORM
@ GPU_RG32F
@ GPU_R8
@ GPU_RGB16_SNORM
@ GPU_DEPTH_COMPONENT24
@ GPU_RG16_SNORM
@ GPU_RGB8UI
@ GPU_RGB16F
@ GPU_RGB16UI
@ GPU_RGBA32I
@ GPU_RGBA8_DXT5
@ GPU_DEPTH_COMPONENT32F
@ GPU_R16_SNORM
@ GPU_DEPTH_COMPONENT16
struct GPUShader GPUShader
void init()
static MTLCapabilities & get_capabilities()
static MTLContext * get()
additional_info("compositor_sum_float_shared") .push_constant(Type additional_info("compositor_sum_float_shared") .push_constant(Type GPU_RGBA32F
CCL_NAMESPACE_BEGIN struct Options options
DOF_TILES_FLATTEN_GROUP_SIZE coc_tx GPU_R11F_G11F_B10F
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
out_radiance out_gbuf_normal out_gbuf_closure2 GPU_RG16
SHADOW_TILEMAP_RES tiles_buf[] statistics_buf render_view_buf[SHADOW_VIEW_MAX] GPU_R32UI
RAYTRACE_GROUP_SIZE additional_info("eevee_shared", "eevee_gbuffer_data", "eevee_global_ubo", "eevee_sampling_data", "eevee_utility_texture", "eevee_hiz_data", "draw_view") .specialization_constant(Type RAYTRACE_GROUP_SIZE in_sh_0_tx in_sh_2_tx screen_normal_tx GPU_RGBA8
blender::gpu::Batch * quad
format
static void error(const char *str)
@ MTL_DEPTH_UPDATE_MODE_INT32
@ MTL_DEPTH_UPDATE_MODE_INT24
@ MTL_DEPTH_UPDATE_MODE_FLOAT
char datatoc_compute_texture_update_msl[]
char datatoc_compute_texture_read_msl[]
size_t get_mtl_format_bytesize(MTLPixelFormat tex_format)
static Context * unwrap(GPUContext *ctx)
MTLPixelFormat gpu_texture_format_to_metal(eGPUTextureFormat tex_format)
static GPUContext * wrap(Context *ctx)
constexpr bool validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat data_format)
int get_mtl_format_num_components(MTLPixelFormat tex_format)
bool mtl_format_supports_blending(MTLPixelFormat format)
__int64 int64_t
Definition stdint.h:89