Blender V5.0
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
8
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/* -------------------------------------------------------------------- */
34
36{
37#define CASE(a, b, c, blender_enum, d, mtl_pixel_enum, f, g, h) \
38 case TextureFormat::blender_enum: \
39 return MTLPixelFormat##mtl_pixel_enum;
40
41 switch (tex_format) {
44 break;
45 }
46#undef CASE
47 BLI_assert_msg(false, "Unrecognised GPU pixel format!\n");
48 return MTLPixelFormatRGBA8Unorm;
49}
50
51size_t get_mtl_format_bytesize(MTLPixelFormat tex_format)
52{
53 switch (tex_format) {
54 case MTLPixelFormatRGBA8Uint:
55 case MTLPixelFormatRGBA8Sint:
56 case MTLPixelFormatRGBA8Unorm:
57 case MTLPixelFormatRGBA8Snorm:
58 case MTLPixelFormatRGB10A2Uint:
59 case MTLPixelFormatRGB10A2Unorm:
60 return 4;
61 case MTLPixelFormatRGBA32Uint:
62 case MTLPixelFormatRGBA32Sint:
63 case MTLPixelFormatRGBA32Float:
64 return 16;
65 case MTLPixelFormatRGBA16Uint:
66 case MTLPixelFormatRGBA16Sint:
67 case MTLPixelFormatRGBA16Float:
68 case MTLPixelFormatRGBA16Unorm:
69 case MTLPixelFormatRGBA16Snorm:
70 return 8;
71 case MTLPixelFormatRG8Uint:
72 case MTLPixelFormatRG8Sint:
73 case MTLPixelFormatRG8Unorm:
74 case MTLPixelFormatRG8Snorm:
75 case MTLPixelFormatRG8Unorm_sRGB:
76 return 2;
77 case MTLPixelFormatRG32Uint:
78 case MTLPixelFormatRG32Sint:
79 case MTLPixelFormatRG32Float:
80 return 8;
81 case MTLPixelFormatRG16Uint:
82 case MTLPixelFormatRG16Sint:
83 case MTLPixelFormatRG16Float:
84 case MTLPixelFormatRG16Unorm:
85 case MTLPixelFormatRG16Snorm:
86 return 4;
87 case MTLPixelFormatR8Uint:
88 case MTLPixelFormatR8Sint:
89 case MTLPixelFormatR8Unorm:
90 case MTLPixelFormatR8Snorm:
91 return 1;
92 case MTLPixelFormatR32Uint:
93 case MTLPixelFormatR32Sint:
94 case MTLPixelFormatR32Float:
95 return 4;
96 case MTLPixelFormatR16Uint:
97 case MTLPixelFormatR16Sint:
98 case MTLPixelFormatR16Float:
99 case MTLPixelFormatR16Snorm:
100 case MTLPixelFormatR16Unorm:
101 return 2;
102 case MTLPixelFormatRG11B10Float:
103 return 4;
104 case MTLPixelFormatDepth32Float_Stencil8:
105 return 8;
106 case MTLPixelFormatRGBA8Unorm_sRGB:
107 case MTLPixelFormatDepth32Float:
108 case MTLPixelFormatDepth24Unorm_Stencil8:
109 return 4;
110 case MTLPixelFormatDepth16Unorm:
111 return 2;
112 case MTLPixelFormatBC1_RGBA:
113 case MTLPixelFormatBC1_RGBA_sRGB:
114 return 1; /* NOTE: not quite correct (BC1 is 0.5 BPP). */
115 case MTLPixelFormatBC2_RGBA:
116 case MTLPixelFormatBC2_RGBA_sRGB:
117 case MTLPixelFormatBC3_RGBA:
118 case MTLPixelFormatBC3_RGBA_sRGB:
119 return 1;
120
121 default:
122 BLI_assert_msg(false, "Unrecognised GPU pixel format!\n");
123 return 1;
124 }
125}
126
127int get_mtl_format_num_components(MTLPixelFormat tex_format)
128{
129 switch (tex_format) {
130 case MTLPixelFormatRGBA8Uint:
131 case MTLPixelFormatRGBA8Sint:
132 case MTLPixelFormatRGBA8Unorm:
133 case MTLPixelFormatRGBA8Snorm:
134 case MTLPixelFormatRGBA32Uint:
135 case MTLPixelFormatRGBA32Sint:
136 case MTLPixelFormatRGBA32Float:
137 case MTLPixelFormatRGBA16Uint:
138 case MTLPixelFormatRGBA16Sint:
139 case MTLPixelFormatRGBA16Float:
140 case MTLPixelFormatRGBA16Unorm:
141 case MTLPixelFormatRGBA16Snorm:
142 case MTLPixelFormatRGBA8Unorm_sRGB:
143 case MTLPixelFormatRGB10A2Uint:
144 case MTLPixelFormatRGB10A2Unorm:
145 case MTLPixelFormatBC1_RGBA_sRGB:
146 case MTLPixelFormatBC2_RGBA_sRGB:
147 case MTLPixelFormatBC3_RGBA_sRGB:
148 case MTLPixelFormatBC1_RGBA:
149 case MTLPixelFormatBC2_RGBA:
150 case MTLPixelFormatBC3_RGBA:
151 return 4;
152
153 case MTLPixelFormatRG11B10Float:
154 return 3;
155
156 case MTLPixelFormatRG8Uint:
157 case MTLPixelFormatRG8Sint:
158 case MTLPixelFormatRG8Unorm:
159 case MTLPixelFormatRG32Uint:
160 case MTLPixelFormatRG32Sint:
161 case MTLPixelFormatRG32Float:
162 case MTLPixelFormatRG16Uint:
163 case MTLPixelFormatRG16Sint:
164 case MTLPixelFormatRG16Float:
165 case MTLPixelFormatDepth32Float_Stencil8:
166 case MTLPixelFormatRG16Snorm:
167 case MTLPixelFormatRG16Unorm:
168 case MTLPixelFormatRG8Snorm:
169 return 2;
170
171 case MTLPixelFormatR8Uint:
172 case MTLPixelFormatR8Sint:
173 case MTLPixelFormatR8Unorm:
174 case MTLPixelFormatR8Snorm:
175 case MTLPixelFormatR32Uint:
176 case MTLPixelFormatR32Sint:
177 case MTLPixelFormatR32Float:
178 case MTLPixelFormatR16Uint:
179 case MTLPixelFormatR16Sint:
180 case MTLPixelFormatR16Float:
181 case MTLPixelFormatR16Unorm:
182 case MTLPixelFormatR16Snorm:
183 case MTLPixelFormatDepth32Float:
184 case MTLPixelFormatDepth16Unorm:
185 case MTLPixelFormatDepth24Unorm_Stencil8:
186 /* Treating this format as single-channel for direct data copies -- Stencil component is not
187 * addressable. */
188 return 1;
189
190 default:
191 BLI_assert_msg(false, "Unrecognised GPU pixel format!\n");
192 return 1;
193 }
194}
195
197{
198 /* Add formats as needed -- Verify platforms. */
199 const MTLCapabilities &capabilities = MTLBackend::get_capabilities();
200
201 if (capabilities.supports_family_mac1 || capabilities.supports_family_mac_catalyst1) {
202
203 switch (format) {
204 case MTLPixelFormatA8Unorm:
205 case MTLPixelFormatR8Uint:
206 case MTLPixelFormatR8Sint:
207 case MTLPixelFormatR16Uint:
208 case MTLPixelFormatR16Sint:
209 case MTLPixelFormatRG32Uint:
210 case MTLPixelFormatRG32Sint:
211 case MTLPixelFormatRGBA8Uint:
212 case MTLPixelFormatRGBA8Sint:
213 case MTLPixelFormatRGBA32Uint:
214 case MTLPixelFormatRGBA32Sint:
215 case MTLPixelFormatDepth16Unorm:
216 case MTLPixelFormatDepth32Float:
217 case MTLPixelFormatInvalid:
218 case MTLPixelFormatBGR10A2Unorm:
219 case MTLPixelFormatRGB10A2Uint:
220 return false;
221 default:
222 return true;
223 }
224 }
225 else {
226 switch (format) {
227 case MTLPixelFormatA8Unorm:
228 case MTLPixelFormatR8Uint:
229 case MTLPixelFormatR8Sint:
230 case MTLPixelFormatR16Uint:
231 case MTLPixelFormatR16Sint:
232 case MTLPixelFormatRG32Uint:
233 case MTLPixelFormatRG32Sint:
234 case MTLPixelFormatRGBA8Uint:
235 case MTLPixelFormatRGBA8Sint:
236 case MTLPixelFormatRGBA32Uint:
237 case MTLPixelFormatRGBA32Sint:
238 case MTLPixelFormatRGBA32Float:
239 case MTLPixelFormatDepth16Unorm:
240 case MTLPixelFormatDepth32Float:
241 case MTLPixelFormatInvalid:
242 case MTLPixelFormatBGR10A2Unorm:
243 case MTLPixelFormatRGB10A2Uint:
244 return false;
245 default:
246 return true;
247 }
248 }
249}
250
252
253/* -------------------------------------------------------------------- */
256
257id<MTLComputePipelineState> gpu::MTLTexture::mtl_texture_update_impl(
258 TextureUpdateRoutineSpecialisation specialization_params,
259 blender::Map<TextureUpdateRoutineSpecialisation, id<MTLComputePipelineState>>
260 &specialization_cache,
261 GPUTextureType texture_type)
262{
263 /* Check whether the Kernel exists. */
264 id<MTLComputePipelineState> *result = specialization_cache.lookup_ptr(specialization_params);
265 if (result != nullptr) {
266 return *result;
267 }
268
269 id<MTLComputePipelineState> return_pso = nil;
270 @autoreleasepool {
271
272 /* Fetch active context. */
273 MTLContext *ctx = MTLContext::get();
274 BLI_assert(ctx);
275
277 NSString *tex_update_kernel_src = [NSString
278 stringWithUTF8String:datatoc_compute_texture_update_msl];
279
280 /* Prepare options and specializations. */
281 MTLCompileOptions *options = [[[MTLCompileOptions alloc] init] autorelease];
282 options.languageVersion = MTLLanguageVersion2_2;
283 options.preprocessorMacros = @{
284 @"INPUT_DATA_TYPE" :
285 [NSString stringWithUTF8String:specialization_params.input_data_type.c_str()],
286 @"OUTPUT_DATA_TYPE" :
287 [NSString stringWithUTF8String:specialization_params.output_data_type.c_str()],
288 @"COMPONENT_COUNT_INPUT" :
289 [NSNumber numberWithInt:specialization_params.component_count_input],
290 @"COMPONENT_COUNT_OUTPUT" :
291 [NSNumber numberWithInt:specialization_params.component_count_output],
292 @"TEX_TYPE" : [NSNumber numberWithInt:((int)(texture_type))],
293 @"IS_TEXTURE_CLEAR" :
294 [NSNumber numberWithInt:((int)(specialization_params.is_clear ? 1 : 0))]
295 };
296
297 /* Prepare shader library for conversion routine. */
298 NSError *error = nullptr;
299 id<MTLLibrary> temp_lib = [[ctx->device newLibraryWithSource:tex_update_kernel_src
301 error:&error] autorelease];
302 if (error) {
303 /* Only exit out if genuine error and not warning. */
304 if ([[error localizedDescription] rangeOfString:@"Compilation succeeded"].location ==
305 NSNotFound)
306 {
307 NSLog(@"Compile Error - Metal Shader Library error %@ ", error);
308 BLI_assert(false);
309 return nil;
310 }
311 }
312
313 /* Fetch compute function. */
314 BLI_assert(temp_lib != nil);
315 id<MTLFunction> temp_compute_function = [[temp_lib
316 newFunctionWithName:@"compute_texture_update"] autorelease];
317 BLI_assert(temp_compute_function);
318
319 /* Otherwise, bake new Kernel. */
320 id<MTLComputePipelineState> compute_pso = [ctx->device
321 newComputePipelineStateWithFunction:temp_compute_function
322 error:&error];
323 if (error || compute_pso == nil) {
324 NSLog(@"Failed to prepare texture_update MTLComputePipelineState %@", error);
325 BLI_assert(false);
326 }
327
328 /* Store PSO. */
329 specialization_cache.add_new(specialization_params, compute_pso);
330 return_pso = compute_pso;
331 }
332
333 BLI_assert(return_pso != nil);
334 return return_pso;
335}
336
337id<MTLComputePipelineState> gpu::MTLTexture::texture_update_1d_get_kernel(
338 TextureUpdateRoutineSpecialisation specialization)
339{
340 MTLContext *mtl_context = MTLContext::get();
341 BLI_assert(mtl_context != nullptr);
342 return mtl_texture_update_impl(specialization,
343 mtl_context->get_texture_utils().texture_1d_update_compute_psos,
345}
346
347id<MTLComputePipelineState> gpu::MTLTexture::texture_update_1d_array_get_kernel(
348 TextureUpdateRoutineSpecialisation specialization)
349{
350 MTLContext *mtl_context = MTLContext::get();
351 BLI_assert(mtl_context != nullptr);
352 return mtl_texture_update_impl(
353 specialization,
354 mtl_context->get_texture_utils().texture_1d_array_update_compute_psos,
356}
357
358id<MTLComputePipelineState> gpu::MTLTexture::texture_update_2d_get_kernel(
359 TextureUpdateRoutineSpecialisation specialization)
360{
361 MTLContext *mtl_context = MTLContext::get();
362 BLI_assert(mtl_context != nullptr);
363 return mtl_texture_update_impl(specialization,
364 mtl_context->get_texture_utils().texture_2d_update_compute_psos,
366}
367
368id<MTLComputePipelineState> gpu::MTLTexture::texture_update_2d_array_get_kernel(
369 TextureUpdateRoutineSpecialisation specialization)
370{
371 MTLContext *mtl_context = MTLContext::get();
372 BLI_assert(mtl_context != nullptr);
373 return mtl_texture_update_impl(
374 specialization,
375 mtl_context->get_texture_utils().texture_2d_array_update_compute_psos,
377}
378
379id<MTLComputePipelineState> gpu::MTLTexture::texture_update_3d_get_kernel(
380 TextureUpdateRoutineSpecialisation specialization)
381{
382 MTLContext *mtl_context = MTLContext::get();
383 BLI_assert(mtl_context != nullptr);
384 return mtl_texture_update_impl(specialization,
385 mtl_context->get_texture_utils().texture_3d_update_compute_psos,
387}
388
389/* TODO(Metal): Data upload routine kernel for texture cube and texture cube array.
390 * Currently does not appear to be hit. */
391
392gpu::Shader *gpu::MTLTexture::depth_2d_update_sh_get(
393 DepthTextureUpdateRoutineSpecialisation specialization)
394{
395
396 /* Check whether the Kernel exists. */
397 MTLContext *mtl_context = MTLContext::get();
398 BLI_assert(mtl_context != nullptr);
399
400 gpu::Shader **result = mtl_context->get_texture_utils().depth_2d_update_shaders.lookup_ptr(
401 specialization);
402 if (result != nullptr) {
403 return *result;
404 }
405
406 const char *depth_2d_info_variant = nullptr;
407 switch (specialization.data_mode) {
409 depth_2d_info_variant = "depth_2d_update_float";
410 break;
412 depth_2d_info_variant = "depth_2d_update_int24";
413 break;
415 depth_2d_info_variant = "depth_2d_update_int32";
416 break;
417 default:
418 BLI_assert(false && "Invalid format mode\n");
419 return nullptr;
420 }
421
422 gpu::Shader *shader = GPU_shader_create_from_info_name(depth_2d_info_variant);
423 mtl_context->get_texture_utils().depth_2d_update_shaders.add_new(specialization, shader);
424 return shader;
425}
426
427gpu::Shader *gpu::MTLTexture::fullscreen_blit_sh_get()
428{
429 MTLContext *mtl_context = MTLContext::get();
430 BLI_assert(mtl_context != nullptr);
431 if (mtl_context->get_texture_utils().fullscreen_blit_shader == nullptr) {
432 gpu::Shader *shader = GPU_shader_create_from_info_name("fullscreen_blit");
433
434 mtl_context->get_texture_utils().fullscreen_blit_shader = shader;
435 }
436 return mtl_context->get_texture_utils().fullscreen_blit_shader;
437}
438
439/* Special routine for updating 2D depth textures using the rendering pipeline. */
440void gpu::MTLTexture::update_sub_depth_2d(
441 int mip, int offset[3], int extent[3], eGPUDataFormat type, const void *data)
442{
443 /* Verify we are in a valid configuration. */
444 BLI_assert(ELEM(format_,
445 TextureFormat::SFLOAT_32_DEPTH,
446 TextureFormat::UNORM_16_DEPTH,
447 TextureFormat::SFLOAT_32_DEPTH_UINT_8));
448 BLI_assert(validate_data_format(format_, type));
450
451 /* Determine whether we are in GPU_DATA_UINT_24_8_DEPRECATED or GPU_DATA_FLOAT mode. */
452 bool is_float = (type == GPU_DATA_FLOAT);
453 TextureFormat format = (is_float) ? TextureFormat::SFLOAT_32 : TextureFormat::SINT_32;
454
455 /* Shader key - Add parameters here for different configurations. */
456 DepthTextureUpdateRoutineSpecialisation specialization;
457 switch (type) {
458 case GPU_DATA_FLOAT:
459 specialization.data_mode = MTL_DEPTH_UPDATE_MODE_FLOAT;
460 break;
461
463 specialization.data_mode = MTL_DEPTH_UPDATE_MODE_INT24;
464 break;
465
466 case GPU_DATA_UINT:
467 specialization.data_mode = MTL_DEPTH_UPDATE_MODE_INT32;
468 break;
469
470 default:
471 BLI_assert_msg(false, "Unsupported eGPUDataFormat being passed to depth texture update\n");
472 return;
473 }
474
475 /* Push contents into an r32_tex and render contents to depth using a shader. */
476 gpu::Texture *r32_tex_tmp = GPU_texture_create_2d("depth_intermediate_copy_tex",
477 w_,
478 h_,
479 1,
480 format,
483 nullptr);
484 GPU_texture_filter_mode(r32_tex_tmp, false);
486 gpu::MTLTexture *mtl_tex = static_cast<gpu::MTLTexture *>(r32_tex_tmp);
487 mtl_tex->update_sub(mip, offset, extent, type, data);
488
489 gpu::FrameBuffer *restore_fb = GPU_framebuffer_active_get();
490 gpu::FrameBuffer *depth_fb_temp = GPU_framebuffer_create("depth_intermediate_copy_fb");
491 GPU_framebuffer_texture_attach(depth_fb_temp, this, 0, mip);
492 GPU_framebuffer_bind(depth_fb_temp);
493 if (extent[0] == w_ && extent[1] == h_) {
494 /* Skip load if the whole texture is being updated. */
495 GPU_framebuffer_clear_depth(depth_fb_temp, 0.0);
496 GPU_framebuffer_clear_stencil(depth_fb_temp, 0);
497 }
498
499 gpu::Shader *depth_2d_update_sh = depth_2d_update_sh_get(specialization);
500 BLI_assert(depth_2d_update_sh != nullptr);
501 Batch *quad = GPU_batch_preset_quad();
502 GPU_batch_set_shader(quad, depth_2d_update_sh);
503
504 GPU_batch_texture_bind(quad, "source_data", r32_tex_tmp);
505 GPU_batch_uniform_1i(quad, "mip", mip);
506 GPU_batch_uniform_2f(quad, "extent", (float)extent[0], (float)extent[1]);
507 GPU_batch_uniform_2f(quad, "offset", (float)offset[0], (float)offset[1]);
508 GPU_batch_uniform_2f(quad, "size", (float)w_, (float)h_);
509
510 bool depth_write_prev = GPU_depth_mask_get();
511 uint stencil_mask_prev = GPU_stencil_mask_get();
512 GPUDepthTest depth_test_prev = GPU_depth_test_get();
513 GPUStencilTest stencil_test_prev = GPU_stencil_test_get();
514 GPU_scissor_test(true);
515 GPU_scissor(offset[0], offset[1], extent[0], extent[1]);
516
520 GPU_depth_mask(true);
522
524
525 GPU_depth_mask(depth_write_prev);
526 GPU_stencil_write_mask_set(stencil_mask_prev);
527 GPU_stencil_test(stencil_test_prev);
528 GPU_depth_test(depth_test_prev);
529
530 if (restore_fb != nullptr) {
531 GPU_framebuffer_bind(restore_fb);
532 }
533 else {
535 }
536 GPU_framebuffer_free(depth_fb_temp);
537 GPU_texture_free(r32_tex_tmp);
538}
540
541/* -------------------------------------------------------------------- */
544
545id<MTLComputePipelineState> gpu::MTLTexture::mtl_texture_read_impl(
546 TextureReadRoutineSpecialisation specialization_params,
547 blender::Map<TextureReadRoutineSpecialisation, id<MTLComputePipelineState>>
548 &specialization_cache,
549 GPUTextureType texture_type)
550{
551 /* Check whether the Kernel exists. */
552 id<MTLComputePipelineState> *result = specialization_cache.lookup_ptr(specialization_params);
553 if (result != nullptr) {
554 return *result;
555 }
556
557 id<MTLComputePipelineState> return_pso = nil;
558 @autoreleasepool {
559
560 /* Fetch active context. */
562 BLI_assert(ctx);
563
565 NSString *tex_update_kernel_src = [NSString
566 stringWithUTF8String:datatoc_compute_texture_read_msl];
567
568 /* Defensive Debug Checks. */
569 int64_t depth_scale_factor = 1;
570 if (specialization_params.depth_format_mode > 0) {
571 BLI_assert(specialization_params.component_count_input == 1);
572 BLI_assert(specialization_params.component_count_output == 1);
573 switch (specialization_params.depth_format_mode) {
574 case 1:
575 /* FLOAT */
576 depth_scale_factor = 1;
577 break;
578 case 2:
579 /* D24 uint */
580 depth_scale_factor = 0xFFFFFFu;
581 break;
582 case 4:
583 /* D32 uint */
584 depth_scale_factor = 0xFFFFFFFFu;
585 break;
586 default:
587 BLI_assert_msg(0, "Unrecognized mode");
588 break;
589 }
590 }
591
592 /* Prepare options and specializations. */
593 MTLCompileOptions *options = [[[MTLCompileOptions alloc] init] autorelease];
594 options.languageVersion = MTLLanguageVersion2_2;
595 options.preprocessorMacros = @{
596 @"INPUT_DATA_TYPE" :
597 [NSString stringWithUTF8String:specialization_params.input_data_type.c_str()],
598 @"OUTPUT_DATA_TYPE" :
599 [NSString stringWithUTF8String:specialization_params.output_data_type.c_str()],
600 @"COMPONENT_COUNT_INPUT" :
601 [NSNumber numberWithInt:specialization_params.component_count_input],
602 @"COMPONENT_COUNT_OUTPUT" :
603 [NSNumber numberWithInt:specialization_params.component_count_output],
604 @"WRITE_COMPONENT_COUNT" :
605 [NSNumber numberWithInt:min_ii(specialization_params.component_count_input,
606 specialization_params.component_count_output)],
607 @"IS_DEPTH_FORMAT" :
608 [NSNumber numberWithInt:((specialization_params.depth_format_mode > 0) ? 1 : 0)],
609 @"DEPTH_SCALE_FACTOR" : [NSNumber numberWithLongLong:depth_scale_factor],
610 @"TEX_TYPE" : [NSNumber numberWithInt:((int)(texture_type))],
611 @"IS_DEPTHSTENCIL_24_8" :
612 [NSNumber numberWithInt:(specialization_params.depth_format_mode == 2) ? 1 : 0]
613 };
614
615 /* Prepare shader library for conversion routine. */
616 NSError *error = nullptr;
617 id<MTLLibrary> temp_lib = [[ctx->device newLibraryWithSource:tex_update_kernel_src
619 error:&error] autorelease];
620 if (error) {
621 /* Only exit out if genuine error and not warning. */
622 if ([[error localizedDescription] rangeOfString:@"Compilation succeeded"].location ==
623 NSNotFound)
624 {
625 NSLog(@"Compile Error - Metal Shader Library error %@ ", error);
626 BLI_assert(false);
627 return nil;
628 }
629 }
630
631 /* Fetch compute function. */
632 BLI_assert(temp_lib != nil);
633 id<MTLFunction> temp_compute_function = [[temp_lib newFunctionWithName:@"compute_texture_read"]
634 autorelease];
635 BLI_assert(temp_compute_function);
636
637 /* Otherwise, bake new Kernel. */
638 id<MTLComputePipelineState> compute_pso = [ctx->device
639 newComputePipelineStateWithFunction:temp_compute_function
640 error:&error];
641 if (error || compute_pso == nil) {
642 NSLog(@"Failed to prepare texture_read MTLComputePipelineState %@", error);
643 BLI_assert(false);
644 return nil;
645 }
646
647 /* Store PSO. */
648 specialization_cache.add_new(specialization_params, compute_pso);
649 return_pso = compute_pso;
650 }
651
652 BLI_assert(return_pso != nil);
653 return return_pso;
654}
655
656id<MTLComputePipelineState> gpu::MTLTexture::texture_read_2d_get_kernel(
657 TextureReadRoutineSpecialisation specialization)
658{
659 MTLContext *mtl_context = MTLContext::get();
660 BLI_assert(mtl_context != nullptr);
661 return mtl_texture_read_impl(specialization,
662 mtl_context->get_texture_utils().texture_2d_read_compute_psos,
664}
665
666id<MTLComputePipelineState> gpu::MTLTexture::texture_read_2d_array_get_kernel(
667 TextureReadRoutineSpecialisation specialization)
668{
669 MTLContext *mtl_context = MTLContext::get();
670 BLI_assert(mtl_context != nullptr);
671 return mtl_texture_read_impl(specialization,
672 mtl_context->get_texture_utils().texture_2d_array_read_compute_psos,
674}
675
676id<MTLComputePipelineState> gpu::MTLTexture::texture_read_1d_get_kernel(
677 TextureReadRoutineSpecialisation specialization)
678{
679 MTLContext *mtl_context = MTLContext::get();
680 BLI_assert(mtl_context != nullptr);
681 return mtl_texture_read_impl(specialization,
682 mtl_context->get_texture_utils().texture_1d_read_compute_psos,
684}
685
686id<MTLComputePipelineState> gpu::MTLTexture::texture_read_1d_array_get_kernel(
687 TextureReadRoutineSpecialisation specialization)
688{
689 MTLContext *mtl_context = MTLContext::get();
690 BLI_assert(mtl_context != nullptr);
691 return mtl_texture_read_impl(specialization,
692 mtl_context->get_texture_utils().texture_1d_array_read_compute_psos,
694}
695
696id<MTLComputePipelineState> gpu::MTLTexture::texture_read_3d_get_kernel(
697 TextureReadRoutineSpecialisation specialization)
698{
699 MTLContext *mtl_context = MTLContext::get();
700 BLI_assert(mtl_context != nullptr);
701 return mtl_texture_read_impl(specialization,
702 mtl_context->get_texture_utils().texture_3d_read_compute_psos,
704}
705
707
708} // namespace blender::gpu
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
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:288
void GPU_batch_draw(blender::gpu::Batch *batch)
void GPU_batch_set_shader(blender::gpu::Batch *batch, blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
#define GPU_batch_uniform_2f(batch, name, x, y)
Definition GPU_batch.hh:272
#define GPU_batch_uniform_1i(batch, name, x)
Definition GPU_batch.hh:269
blender::gpu::Batch * GPU_batch_preset_quad()
#define CASE(a, size, c, blender_enum, d, e, f, g, h)
blender::gpu::FrameBuffer * GPU_framebuffer_create(const char *name)
void GPU_framebuffer_clear_stencil(blender::gpu::FrameBuffer *fb, uint clear_stencil)
void GPU_framebuffer_restore()
void GPU_framebuffer_free(blender::gpu::FrameBuffer *fb)
void GPU_framebuffer_texture_attach(blender::gpu::FrameBuffer *fb, blender::gpu::Texture *texture, int slot, int mip)
void GPU_framebuffer_clear_depth(blender::gpu::FrameBuffer *fb, float clear_depth)
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
blender::gpu::FrameBuffer * GPU_framebuffer_active_get()
blender::gpu::Shader * GPU_shader_create_from_info_name(const char *info_name)
GPUStencilTest GPU_stencil_test_get()
Definition gpu_state.cc:250
void GPU_scissor_test(bool enable)
Definition gpu_state.cc:188
GPUDepthTest
Definition GPU_state.hh:110
@ GPU_DEPTH_ALWAYS
Definition GPU_state.hh:112
void GPU_depth_mask(bool depth)
Definition gpu_state.cc:110
void GPU_stencil_write_mask_set(uint write_mask)
Definition gpu_state.cc:210
void GPU_depth_test(GPUDepthTest test)
Definition gpu_state.cc:68
void GPU_stencil_test(GPUStencilTest test)
Definition gpu_state.cc:73
GPUStencilTest
Definition GPU_state.hh:120
@ GPU_STENCIL_ALWAYS
Definition GPU_state.hh:122
void GPU_stencil_reference_set(uint reference)
Definition gpu_state.cc:205
void GPU_scissor(int x, int y, int width, int height)
Definition gpu_state.cc:193
GPUDepthTest GPU_depth_test_get()
Definition gpu_state.cc:244
uint GPU_stencil_mask_get()
Definition gpu_state.cc:238
bool GPU_depth_mask_get()
Definition gpu_state.cc:287
#define GPU_TEXTURE_FORMAT_EXPAND(impl)
eGPUDataFormat
@ GPU_DATA_UINT
@ GPU_DATA_UINT_24_8_DEPRECATED
@ GPU_DATA_FLOAT
void GPU_texture_extend_mode(blender::gpu::Texture *texture, GPUSamplerExtendMode extend_mode)
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
@ GPU_SAMPLER_EXTEND_MODE_EXTEND
blender::gpu::Texture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_filter_mode(blender::gpu::Texture *texture, bool use_filter)
void GPU_texture_free(blender::gpu::Texture *texture)
BMesh const char void * data
void init()
long long int int64_t
static MTLCapabilities & get_capabilities()
static MTLContext * get()
CCL_NAMESPACE_BEGIN struct Options options
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)
MTLPixelFormat gpu_texture_format_to_metal(TextureFormat tex_format)
int get_mtl_format_num_components(MTLPixelFormat tex_format)
constexpr bool validate_data_format(TextureFormat tex_format, eGPUDataFormat data_format)
bool mtl_format_supports_blending(MTLPixelFormat format)
static void init(bNodeTree *, bNode *node)