32 void gpu::MTLTexture::mtl_texture_init()
39 resource_mode_ = MTL_TEXTURE_MODE_DEFAULT;
44 texture_buffer_ = nil;
45 mip_swizzle_view_ = nil;
51 vert_buffer_ =
nullptr;
52 vert_buffer_mtl_ = nil;
53 vert_buffer_offset_ = -1;
56 tex_swizzle_mask_[0] =
'r';
57 tex_swizzle_mask_[1] =
'g';
58 tex_swizzle_mask_[2] =
'b';
59 tex_swizzle_mask_[3] =
'a';
60 mtl_swizzle_mask_ = MTLTextureSwizzleChannelsMake(
61 MTLTextureSwizzleRed, MTLTextureSwizzleGreen, MTLTextureSwizzleBlue, MTLTextureSwizzleAlpha);
76 id<MTLTexture> metal_texture)
86 init_2D(metal_texture.width, metal_texture.height, 0, 1,
format);
89 texture_ = metal_texture;
95 resource_mode_ = MTL_TEXTURE_MODE_EXTERNAL;
103 if (ctx !=
nullptr) {
115 void gpu::MTLTexture::bake_mip_swizzle_view()
117 if (texture_view_dirty_flags_) {
119 if (mip_swizzle_view_ != nil) {
120 [mip_swizzle_view_ release];
121 mip_swizzle_view_ = nil;
145 int range_len =
min_ii((mip_texture_max_level_ - mip_texture_base_level_) + 1,
146 texture_.mipmapLevelCount);
148 BLI_assert(mip_texture_base_level_ < texture_.mipmapLevelCount);
149 BLI_assert(mip_texture_base_layer_ < num_slices);
150 mip_swizzle_view_ = [texture_
151 newTextureViewWithPixelFormat:texture_.pixelFormat
152 textureType:texture_.textureType
153 levels:NSMakeRange(mip_texture_base_level_, range_len)
154 slices:NSMakeRange(mip_texture_base_layer_, num_slices)
155 swizzle:mtl_swizzle_mask_];
157 "Updating texture view - MIP TEXTURE BASE LEVEL: %d, MAX LEVEL: %d (Range len: %d)\n",
158 mip_texture_base_level_,
159 min_ii(mip_texture_max_level_, texture_.mipmapLevelCount),
161 mip_swizzle_view_.label = [texture_
label];
162 texture_view_dirty_flags_ = TEXTURE_VIEW_NOT_DIRTY;
169 id<MTLTexture> gpu::MTLTexture::get_metal_handle()
173 this->ensure_baked();
176 if (resource_mode_ == MTL_TEXTURE_MODE_VBO) {
180 id<MTLBuffer> buf = nil;
182 BLI_assert(buf == vert_buffer_mtl_ && r_offset == vert_buffer_offset_);
190 if (resource_mode_ == MTL_TEXTURE_MODE_TEXTURE_VIEW) {
191 BLI_assert(mip_swizzle_view_ &&
"Texture view should always have a valid handle.");
194 if (mip_swizzle_view_ != nil || texture_view_dirty_flags_) {
195 bake_mip_swizzle_view();
196 return mip_swizzle_view_;
203 id<MTLTexture> gpu::MTLTexture::get_metal_handle_base()
207 this->ensure_baked();
210 if (resource_mode_ == MTL_TEXTURE_MODE_TEXTURE_VIEW) {
211 BLI_assert(mip_swizzle_view_ &&
"Texture view should always have a valid handle.");
212 if (mip_swizzle_view_ != nil || texture_view_dirty_flags_) {
213 bake_mip_swizzle_view();
215 return mip_swizzle_view_;
225 void gpu::MTLTexture::blit(id<MTLBlitCommandEncoder> blit_encoder,
231 gpu::MTLTexture *
dest,
244 MTLSize src_size = MTLSizeMake(
width,
height, depth);
245 MTLOrigin src_origin = MTLOriginMake(src_x_offset, src_y_offset, src_z_offset);
246 MTLOrigin dst_origin = MTLOriginMake(dst_x_offset, dst_y_offset, dst_z_offset);
248 if (this->format_get() !=
dest->format_get()) {
250 "[Warning] gpu::MTLTexture: Cannot copy between two textures of different types using a "
251 "blit encoder. TODO: Support this operation\n");
257 [blit_encoder copyFromTexture:this->get_metal_handle_base()
258 sourceSlice:src_slice
260 sourceOrigin:src_origin
262 toTexture:
dest->get_metal_handle_base()
263 destinationSlice:dst_slice
264 destinationLevel:dst_mip
265 destinationOrigin:dst_origin];
268 void gpu::MTLTexture::blit(gpu::MTLTexture *dst,
279 BLI_assert(this->type_get() == dst->type_get());
281 GPUShader *shader = fullscreen_blit_sh_get();
287 GPUFrameBuffer *blit_target_fb = dst->get_blit_framebuffer(dst_slice, dst_mip);
296 float w = dst->width_get();
297 float h = dst->height_get();
336 if (restore_fb !=
nullptr) {
348 bool update_attachments =
false;
351 update_attachments =
true;
356 if (blit_fb_slice_ != dst_slice || blit_fb_mip_ != dst_mip) {
357 update_attachments =
true;
361 if (update_attachments) {
364 GPU_framebuffer_ensure_config(
366 {GPU_ATTACHMENT_TEXTURE_LAYER_MIP(
wrap(
static_cast<Texture *
>(
this)),
367 static_cast<int>(dst_slice),
368 static_cast<int>(dst_mip)),
369 GPU_ATTACHMENT_NONE});
373 GPU_framebuffer_ensure_config(
375 {GPU_ATTACHMENT_NONE,
376 GPU_ATTACHMENT_TEXTURE_LAYER_MIP(
wrap(
static_cast<Texture *
>(
this)),
377 static_cast<int>(dst_slice),
378 static_cast<int>(dst_mip))});
380 blit_fb_slice_ = dst_slice;
381 blit_fb_mip_ = dst_mip;
388 MTLSamplerState gpu::MTLTexture::get_sampler_state()
390 MTLSamplerState sampler_state;
391 sampler_state.state = this->sampler_state;
393 return sampler_state;
404 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_TEXTURE_VIEW);
407 this->ensure_mipmaps(mip);
410 this->ensure_baked();
414 BLI_assert(mip >= mip_min_ && mip <= mip_max_);
416 BLI_assert(texture_.mipmapLevelCount >= mip_max_);
422 if (is_depth_format) {
431 "[Error] gpu::MTLTexture::update_sub not yet supported for other depth "
451 switch (this->dimensions_count()) {
453 totalsize = input_bytes_per_pixel *
max_ii(expected_update_w, 1);
456 totalsize = input_bytes_per_pixel *
max_ii(expected_update_w, 1) *
max_ii(extent[1], 1);
459 totalsize = input_bytes_per_pixel *
max_ii(expected_update_w, 1) *
max_ii(extent[1], 1) *
487 destination_num_channels};
490 bool can_use_direct_blit =
true;
491 if (expected_dst_bytes_per_pixel != input_bytes_per_pixel ||
492 num_channels != destination_num_channels) {
493 can_use_direct_blit =
false;
496 if (is_depth_format) {
500 if (extent[0] == 1 && extent[1] == 1 && extent[2] == 1 && totalsize == 4) {
501 can_use_direct_blit =
false;
508 "SRGB data upload does not work correctly using compute upload. "
516 "Special input data type must be a 1-1 mapping with destination texture as it "
517 "cannot easily be split");
521 if (!can_use_direct_blit) {
523 "gpu::MTLTexture::update_sub supplied bpp is %d bytes (%d components per "
524 "pixel), but backing texture bpp is %d bytes (%d components per pixel) "
525 "(TODO(Metal): Channel Conversion needed) (w: %d, h: %d, d: %d)\n",
526 input_bytes_per_pixel,
528 expected_dst_bytes_per_pixel,
529 destination_num_channels,
537 "[Error]: Updating texture layers other than mip=0 when data is mismatched is not "
538 "possible in METAL on macOS using texture->write\n");
545 "[Error]: Updating texture -- destination MTLPixelFormat '%d' does not support write "
546 "operations, and no suitable TextureView format exists.\n",
547 *(
int *)(&destination_format));
553 id<MTLBuffer> staging_buffer = nil;
559 memcpy(allocation.
data,
data, totalsize);
568 if (compatible_write_format == MTLPixelFormatInvalid) {
569 MTL_LOG_ERROR(
"Cannot use compute update blit with texture-view format: %d\n",
570 *((
int *)&compatible_write_format));
573 id<MTLTexture> texture_handle = ((compatible_write_format == destination_format)) ?
576 newTextureViewWithPixelFormat:compatible_write_format];
579 id<MTLBlitCommandEncoder> blit_encoder = nil;
580 id<MTLComputeCommandEncoder> compute_encoder = nil;
581 if (can_use_direct_blit) {
595 if (can_use_direct_blit) {
597 int bytes_per_row = expected_dst_bytes_per_pixel *
601 int bytes_per_image = bytes_per_row;
603 for (
int array_index = 0; array_index < max_array_index; array_index++) {
605 int buffer_array_offset = staging_buffer_offset + (bytes_per_image * array_index);
607 copyFromBuffer:staging_buffer
608 sourceOffset:buffer_array_offset
609 sourceBytesPerRow:bytes_per_row
610 sourceBytesPerImage:bytes_per_image
611 sourceSize:MTLSizeMake(extent[0], 1, 1)
612 toTexture:texture_handle
616 destinationOrigin:MTLOriginMake(
offset[0], 0, 0)];
622 id<MTLComputePipelineState> pso = texture_update_1d_get_kernel(
623 compute_specialisation_kernel);
624 TextureUpdateParams
params = {mip,
630 [compute_encoder setComputePipelineState:pso];
632 [compute_encoder setBuffer:staging_buffer
offset:staging_buffer_offset atIndex:1];
633 [compute_encoder setTexture:texture_handle atIndex:0];
635 dispatchThreads:MTLSizeMake(extent[0], 1, 1)
636 threadsPerThreadgroup:MTLSizeMake(64, 1, 1)];
639 id<MTLComputePipelineState> pso = texture_update_1d_array_get_kernel(
640 compute_specialisation_kernel);
641 TextureUpdateParams
params = {mip,
642 {extent[0], extent[1], 1},
647 [compute_encoder setComputePipelineState:pso];
649 [compute_encoder setBuffer:staging_buffer
offset:staging_buffer_offset atIndex:1];
650 [compute_encoder setTexture:texture_handle atIndex:0];
652 dispatchThreads:MTLSizeMake(extent[0], extent[1], 1)
653 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
661 if (can_use_direct_blit) {
663 int bytes_per_row = expected_dst_bytes_per_pixel *
667 int bytes_per_image = bytes_per_row * extent[1];
669 int texture_array_relative_offset = 0;
673 for (
int array_slice = base_slice; array_slice < final_slice; array_slice++) {
675 if (array_slice > 0) {
680 [blit_encoder copyFromBuffer:staging_buffer
681 sourceOffset:staging_buffer_offset + texture_array_relative_offset
682 sourceBytesPerRow:bytes_per_row
683 sourceBytesPerImage:bytes_per_image
684 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
685 toTexture:texture_handle
686 destinationSlice:array_slice
688 destinationOrigin:MTLOriginMake(
offset[0],
offset[1], 0)];
690 texture_array_relative_offset += bytes_per_image;
696 id<MTLComputePipelineState> pso = texture_update_2d_get_kernel(
697 compute_specialisation_kernel);
698 TextureUpdateParams
params = {mip,
699 {extent[0], extent[1], 1},
704 [compute_encoder setComputePipelineState:pso];
706 [compute_encoder setBuffer:staging_buffer
offset:staging_buffer_offset atIndex:1];
707 [compute_encoder setTexture:texture_handle atIndex:0];
709 dispatchThreads:MTLSizeMake(
710 extent[0], extent[1], 1)
711 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
714 id<MTLComputePipelineState> pso = texture_update_2d_array_get_kernel(
715 compute_specialisation_kernel);
716 TextureUpdateParams
params = {mip,
717 {extent[0], extent[1], extent[2]},
722 [compute_encoder setComputePipelineState:pso];
724 [compute_encoder setBuffer:staging_buffer
offset:staging_buffer_offset atIndex:1];
725 [compute_encoder setTexture:texture_handle atIndex:0];
726 [compute_encoder dispatchThreads:MTLSizeMake(extent[0],
729 threadsPerThreadgroup:MTLSizeMake(4, 4, 4)];
737 if (can_use_direct_blit) {
738 int bytes_per_row = expected_dst_bytes_per_pixel *
742 int bytes_per_image = bytes_per_row * extent[1];
743 [blit_encoder copyFromBuffer:staging_buffer
744 sourceOffset:staging_buffer_offset
745 sourceBytesPerRow:bytes_per_row
746 sourceBytesPerImage:bytes_per_image
747 sourceSize:MTLSizeMake(extent[0], extent[1], extent[2])
748 toTexture:texture_handle
754 id<MTLComputePipelineState> pso = texture_update_3d_get_kernel(
755 compute_specialisation_kernel);
756 TextureUpdateParams
params = {mip,
757 {extent[0], extent[1], extent[2]},
762 [compute_encoder setComputePipelineState:pso];
764 [compute_encoder setBuffer:staging_buffer
offset:staging_buffer_offset atIndex:1];
765 [compute_encoder setTexture:texture_handle atIndex:0];
767 dispatchThreads:MTLSizeMake(
768 extent[0], extent[1], extent[2])
769 threadsPerThreadgroup:MTLSizeMake(4, 4, 4)];
775 if (can_use_direct_blit) {
776 int bytes_per_row = expected_dst_bytes_per_pixel *
780 int bytes_per_image = bytes_per_row * extent[1];
782 int texture_array_relative_offset = 0;
785 for (
int i = 0; i < extent[2]; i++) {
786 int face_index =
offset[2] + i;
788 [blit_encoder copyFromBuffer:staging_buffer
789 sourceOffset:staging_buffer_offset + texture_array_relative_offset
790 sourceBytesPerRow:bytes_per_row
791 sourceBytesPerImage:bytes_per_image
792 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
793 toTexture:texture_handle
794 destinationSlice:face_index
796 destinationOrigin:MTLOriginMake(
offset[0],
offset[1], 0)];
797 texture_array_relative_offset += bytes_per_image;
802 "TODO(Metal): Support compute texture update for GPU_TEXTURE_CUBE %d, %d, %d\n",
810 if (can_use_direct_blit) {
812 int bytes_per_row = expected_dst_bytes_per_pixel *
816 int bytes_per_image = bytes_per_row * extent[1];
819 int texture_array_relative_offset = 0;
820 for (
int i = 0; i < extent[2]; i++) {
821 int face_index =
offset[2] + i;
822 [blit_encoder copyFromBuffer:staging_buffer
823 sourceOffset:staging_buffer_offset + texture_array_relative_offset
824 sourceBytesPerRow:bytes_per_row
825 sourceBytesPerImage:bytes_per_image
826 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
827 toTexture:texture_handle
828 destinationSlice:face_index
830 destinationOrigin:MTLOriginMake(
offset[0],
offset[1], 0)];
831 texture_array_relative_offset += bytes_per_image;
836 "TODO(Metal): Support compute texture update for GPU_TEXTURE_CUBE_ARRAY %d, %d, "
856 if (can_use_direct_blit) {
860 if (texture_.storageMode == MTLStorageModeManaged) {
861 [blit_encoder synchronizeResource:texture_buffer_];
867 if (texture_.storageMode == MTLStorageModeManaged) {
869 [blit_encoder synchronizeResource:texture_buffer_];
875 void gpu::MTLTexture::ensure_mipmaps(
int miplvl)
879 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_TEXTURE_VIEW);
884 int max_dimension =
max_iii(w_, effective_h, effective_d);
885 int max_miplvl =
floor(log2(max_dimension));
886 miplvl =
min_ii(max_miplvl, miplvl);
889 if (mipmaps_ < miplvl) {
893 if (is_baked_ && mipmaps_ > mtl_max_mips_) {
895 MTL_LOG_WARNING(
"Texture requires regenerating due to increase in mip-count\n");
898 this->mip_range_set(0, mipmaps_);
908 MTL_LOG_ERROR(
"Cannot Generate mip-maps -- metal device invalid\n");
914 this->ensure_mipmaps(9999);
917 this->ensure_baked();
918 BLI_assert(is_baked_ && texture_ &&
"MTLTexture is not valid");
920 if (mipmaps_ == 1 || mtl_max_mips_ == 1) {
921 MTL_LOG_WARNING(
"Call to generate mipmaps on texture with 'mipmaps_=1\n'");
929 MTL_LOG_WARNING(
"Cannot generate mipmaps for textures using DEPTH formats\n");
938 [enc insertDebugSignpost:
@"Generate MipMaps"];
940 [enc generateMipmapsForTexture:texture_];
951 (mt_dst->
d_ == mt_src->
d_));
962 this->ensure_baked();
974 int extent[3] = {1, 1, 1};
975 this->mip_size_get(mip, extent);
977 switch (mt_dst->
type_) {
983 [blit_encoder copyFromTexture:this->get_metal_handle_base()
984 toTexture:mt_dst->get_metal_handle_base()];
988 this->blit(blit_encoder,
1011 this->ensure_baked();
1017 fb->clear_attachment(this->attachment_type(0), data_format,
data);
1027 return MTLTextureSwizzleRed;
1030 return MTLTextureSwizzleGreen;
1033 return MTLTextureSwizzleBlue;
1036 return MTLTextureSwizzleAlpha;
1038 return MTLTextureSwizzleZero;
1040 return MTLTextureSwizzleOne;
1046 if (memcmp(tex_swizzle_mask_, swizzle_mask, 4) != 0) {
1047 memcpy(tex_swizzle_mask_, swizzle_mask, 4);
1050 MTLTextureSwizzleChannels new_swizzle_mask = MTLTextureSwizzleChannelsMake(
1056 mtl_swizzle_mask_ = new_swizzle_mask;
1057 texture_view_dirty_flags_ |= TEXTURE_VIEW_SWIZZLE_DIRTY;
1081 " MTLTexture of type TEXTURE_1D_ARRAY or TEXTURE_BUFFER cannot have a mipcount "
1082 "greater than 1\n");
1090 mip_texture_base_level_ = mip_min_;
1091 mip_texture_max_level_ = mip_max_;
1092 texture_view_dirty_flags_ |= TEXTURE_VIEW_MIP_DIRTY;
1103 int extent[3] = {1, 1, 1};
1104 this->mip_size_get(mip, extent);
1106 size_t sample_len = extent[0] * extent[1] * extent[2];
1108 size_t texture_size = sample_len * sample_size;
1115 this->read_internal(
1116 mip, 0, 0, 0, extent[0], extent[1], extent[2],
type, num_channels, texture_size + 8,
data);
1120 MTL_LOG_WARNING(
"MTLTexture::read - reading from texture with no image data\n");
1127 void gpu::MTLTexture::read_internal(
int mip,
1135 int num_output_components,
1136 int debug_data_size,
1141 MTL_LOG_WARNING(
"gpu::MTLTexture::read_internal - Trying to read from a non-baked texture!\n");
1150 BLI_assert(num_output_components <= num_channels);
1151 uint desired_output_bpp = num_output_components *
to_bytesize(desired_output_format);
1160 bool format_conversion_needed = (data_format != desired_output_format);
1161 bool can_use_simple_read = (desired_output_bpp == image_bpp) && (!format_conversion_needed) &&
1162 (num_output_components == image_components);
1166 if (is_depth_format) {
1167 can_use_simple_read =
false;
1169 image_components = 1;
1181 image_bpp =
sizeof(int);
1182 image_components = 1;
1183 desired_output_bpp =
sizeof(int);
1184 num_output_components = 1;
1187 format_conversion_needed =
false;
1188 can_use_simple_read =
true;
1192 uint bytes_per_row = desired_output_bpp *
width;
1193 uint bytes_per_image = bytes_per_row *
height;
1194 uint total_bytes = bytes_per_image * depth;
1196 if (can_use_simple_read) {
1200 ((num_output_components *
to_bytesize(desired_output_format)) == desired_output_bpp) &&
1201 (desired_output_bpp == image_bpp));
1207 id<MTLBuffer> destination_buffer = nil;
1208 uint destination_offset = 0;
1209 void *destination_buffer_host_ptr =
nullptr;
1212 MTLResourceOptions bufferOptions = MTLResourceStorageModeManaged;
1213 destination_buffer = [ctx->device newBufferWithLength:
max_ii(total_bytes, 256)
1215 destination_offset = 0;
1216 destination_buffer_host_ptr = (
void *)((
uint8_t *)([destination_buffer contents]) +
1217 destination_offset);
1220 int depth_format_mode = 0;
1221 if (is_depth_format) {
1222 depth_format_mode = 1;
1223 switch (desired_output_format) {
1225 depth_format_mode = 1;
1228 depth_format_mode = 2;
1231 depth_format_mode = 4;
1234 BLI_assert(
false &&
"Unhandled depth read format case");
1243 num_output_components,
1246 bool copy_successful =
false;
1254 id<MTLTexture> read_texture = texture_;
1256 read_texture = [texture_ newTextureViewWithPixelFormat:MTLPixelFormatRGBA8Unorm];
1262 if (can_use_simple_read) {
1264 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1266 [enc insertDebugSignpost:
@"GPUTextureRead"];
1268 [enc copyFromTexture:read_texture
1271 sourceOrigin:MTLOriginMake(x_off, y_off, 0)
1273 toBuffer:destination_buffer
1274 destinationOffset:destination_offset
1275 destinationBytesPerRow:bytes_per_row
1276 destinationBytesPerImage:bytes_per_image];
1277 [enc synchronizeResource:destination_buffer];
1278 copy_successful = true;
1283 id<MTLComputeCommandEncoder> compute_encoder =
1284 ctx->main_command_buffer.ensure_begin_compute_encoder();
1285 id<MTLComputePipelineState> pso = texture_read_2d_get_kernel(
1286 compute_specialisation_kernel);
1287 TextureReadParams
params = {
1292 [compute_encoder setComputePipelineState:pso];
1294 [compute_encoder setBuffer:destination_buffer
offset:destination_offset atIndex:1];
1295 [compute_encoder setTexture:read_texture atIndex:0];
1296 [compute_encoder dispatchThreads:MTLSizeMake(
width,
height, 1)
1297 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
1300 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1302 [enc insertDebugSignpost:
@"GPUTextureRead-syncResource"];
1304 [enc synchronizeResource:destination_buffer];
1305 copy_successful =
true;
1310 if (can_use_simple_read) {
1312 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1314 [enc insertDebugSignpost:
@"GPUTextureRead"];
1316 int base_slice = z_off;
1317 int final_slice = base_slice + depth;
1318 int texture_array_relative_offset = 0;
1320 for (
int array_slice = base_slice; array_slice < final_slice; array_slice++) {
1321 [enc copyFromTexture:read_texture
1324 sourceOrigin:MTLOriginMake(x_off, y_off, 0)
1326 toBuffer:destination_buffer
1327 destinationOffset:destination_offset + texture_array_relative_offset
1328 destinationBytesPerRow:bytes_per_row
1329 destinationBytesPerImage:bytes_per_image];
1330 [enc synchronizeResource:destination_buffer];
1332 texture_array_relative_offset += bytes_per_image;
1334 copy_successful = true;
1339 id<MTLComputeCommandEncoder> compute_encoder =
1340 ctx->main_command_buffer.ensure_begin_compute_encoder();
1341 id<MTLComputePipelineState> pso = texture_read_2d_array_get_kernel(
1342 compute_specialisation_kernel);
1343 TextureReadParams
params = {
1346 {x_off, y_off, z_off},
1348 [compute_encoder setComputePipelineState:pso];
1350 [compute_encoder setBuffer:destination_buffer
offset:destination_offset atIndex:1];
1351 [compute_encoder setTexture:read_texture atIndex:0];
1354 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
1357 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1359 [enc insertDebugSignpost:
@"GPUTextureRead-syncResource"];
1361 [enc synchronizeResource:destination_buffer];
1362 copy_successful =
true;
1367 if (can_use_simple_read) {
1368 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1370 [enc insertDebugSignpost:
@"GPUTextureRead"];
1372 int base_slice = z_off;
1373 int final_slice = base_slice + depth;
1374 int texture_array_relative_offset = 0;
1376 for (
int array_slice = base_slice; array_slice < final_slice; array_slice++) {
1377 [enc copyFromTexture:read_texture
1378 sourceSlice:array_slice
1380 sourceOrigin:MTLOriginMake(x_off, y_off, 0)
1382 toBuffer:destination_buffer
1383 destinationOffset:destination_offset + texture_array_relative_offset
1384 destinationBytesPerRow:bytes_per_row
1385 destinationBytesPerImage:bytes_per_image];
1386 [enc synchronizeResource:destination_buffer];
1388 texture_array_relative_offset += bytes_per_image;
1391 copy_successful = true;
1394 MTL_LOG_ERROR(
"TODO(Metal): unsupported compute copy of texture cube array");
1400 "[Warning] gpu::MTLTexture::read_internal simple-copy not yet supported for texture "
1406 if (copy_successful) {
1411 memcpy(r_data, destination_buffer_host_ptr, total_bytes);
1412 MTL_LOG_INFO(
"gpu::MTLTexture::read_internal success! %d bytes read\n", total_bytes);
1416 "[Warning] gpu::MTLTexture::read_internal not yet supported for this config -- data "
1417 "format different (src %d bytes, dst %d bytes) (src format: %d, dst format: %d), or "
1418 "varying component counts (src %d, dst %d)\n",
1422 (
int)desired_output_format,
1424 num_output_components);
1442 this->prepare_internal();
1449 this->prepare_internal();
1460 this->prepare_internal();
1463 resource_mode_ = MTL_TEXTURE_MODE_TEXTURE_VIEW;
1464 source_texture_ =
src;
1465 mip_texture_base_level_ = mip_offset;
1466 mip_texture_base_layer_ = layer_offset;
1470 texture_ = mtltex->texture_;
1479 bake_mip_swizzle_view();
1495 void gpu::MTLTexture::prepare_internal()
1511 int max_dimension =
max_iii(w_, effective_h, effective_d);
1512 int max_miplvl =
max_ii(
floor(log2(max_dimension)) + 1, 1);
1513 mtl_max_mips_ = max_miplvl;
1517 void gpu::MTLTexture::ensure_baked()
1521 bool copy_previous_contents =
false;
1522 if (is_baked_ && is_dirty_) {
1523 copy_previous_contents =
true;
1524 id<MTLTexture> previous_texture = texture_;
1525 [previous_texture retain];
1535 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_EXTERNAL);
1536 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_TEXTURE_VIEW);
1537 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_VBO);
1549 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
1550 texture_descriptor_.pixelFormat = mtl_format;
1553 texture_descriptor_.width = w_;
1554 texture_descriptor_.height = 1;
1555 texture_descriptor_.depth = 1;
1557 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
1558 texture_descriptor_.usage =
1559 MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite |
1560 MTLTextureUsagePixelFormatView;
1561 texture_descriptor_.storageMode = MTLStorageModePrivate;
1562 texture_descriptor_.sampleCount = 1;
1563 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
1564 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
1571 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
1572 texture_descriptor_.pixelFormat = mtl_format;
1575 texture_descriptor_.width = w_;
1576 texture_descriptor_.height = h_;
1577 texture_descriptor_.depth = 1;
1579 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
1580 texture_descriptor_.usage =
1581 MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite |
1582 MTLTextureUsagePixelFormatView;
1583 texture_descriptor_.storageMode = MTLStorageModePrivate;
1584 texture_descriptor_.sampleCount = 1;
1585 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
1586 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
1592 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
1593 texture_descriptor_.pixelFormat = mtl_format;
1594 texture_descriptor_.textureType = MTLTextureType3D;
1595 texture_descriptor_.width = w_;
1596 texture_descriptor_.height = h_;
1597 texture_descriptor_.depth = d_;
1598 texture_descriptor_.arrayLength = 1;
1599 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
1600 texture_descriptor_.usage =
1601 MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite |
1602 MTLTextureUsagePixelFormatView;
1603 texture_descriptor_.storageMode = MTLStorageModePrivate;
1604 texture_descriptor_.sampleCount = 1;
1605 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
1606 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
1615 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
1616 texture_descriptor_.pixelFormat = mtl_format;
1618 MTLTextureTypeCubeArray :
1620 texture_descriptor_.width = w_;
1621 texture_descriptor_.height = h_;
1622 texture_descriptor_.depth = 1;
1624 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
1625 texture_descriptor_.usage =
1626 MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite |
1627 MTLTextureUsagePixelFormatView;
1628 texture_descriptor_.storageMode = MTLStorageModePrivate;
1629 texture_descriptor_.sampleCount = 1;
1630 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
1631 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
1636 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
1637 texture_descriptor_.pixelFormat = mtl_format;
1638 texture_descriptor_.textureType = MTLTextureTypeTextureBuffer;
1639 texture_descriptor_.width = w_;
1640 texture_descriptor_.height = 1;
1641 texture_descriptor_.depth = 1;
1642 texture_descriptor_.arrayLength = 1;
1643 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
1644 texture_descriptor_.usage =
1645 MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite |
1646 MTLTextureUsagePixelFormatView;
1647 texture_descriptor_.storageMode = MTLStorageModePrivate;
1648 texture_descriptor_.sampleCount = 1;
1649 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
1650 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
1654 MTL_LOG_ERROR(
"[METAL] Error: Cannot create texture with unknown type: %d\n", type_);
1660 resource_mode_ = MTL_TEXTURE_MODE_DEFAULT;
1663 texture_ = [ctx->device newTextureWithDescriptor:texture_descriptor_];
1665 [texture_descriptor_ release];
1666 texture_descriptor_ =
nullptr;
1667 texture_.label = [NSString stringWithUTF8String:this->get_name()];
1674 if (copy_previous_contents) {
1675 id<MTLTexture> previous_texture;
1682 void gpu::MTLTexture::reset()
1685 MTL_LOG_INFO(
"Texture %s reset. Size %d, %d, %d\n", this->get_name(), w_, h_, d_);
1687 if (texture_ != nil) {
1694 if (mip_swizzle_view_ != nil) {
1695 [mip_swizzle_view_ release];
1696 mip_swizzle_view_ = nil;
1699 if (texture_buffer_ != nil) {
1700 [texture_buffer_ release];
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
MINLINE int max_iii(int a, int b, int c)
#define UNUSED_VARS_NDEBUG(...)
GHOST C-API function and type declarations.
void GPU_batch_set_shader(GPUBatch *batch, GPUShader *shader)
#define GPU_batch_texture_bind(batch, name, tex)
void GPU_batch_draw(GPUBatch *batch)
struct GPUBatch * GPU_batch_preset_quad(void)
GPUContext * GPU_context_active_get(void)
struct GPUFrameBuffer GPUFrameBuffer
void GPU_framebuffer_restore(void)
GPUFrameBuffer * GPU_framebuffer_active_get(void)
void GPU_framebuffer_free(GPUFrameBuffer *fb)
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
GPUFrameBuffer * GPU_framebuffer_create(const char *name)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
struct GPUShader GPUShader
void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value)
void GPU_shader_uniform_2f(GPUShader *sh, const char *name, float x, float y)
void GPU_face_culling(eGPUFaceCullTest culling)
void GPU_blend(eGPUBlend blend)
void GPU_scissor_test(bool enable)
uint GPU_stencil_mask_get(void)
void GPU_depth_mask(bool depth)
void GPU_stencil_test(eGPUStencilTest test)
void GPU_stencil_write_mask_set(uint write_mask)
void GPU_stencil_reference_set(uint reference)
eGPUBlend GPU_blend_get(void)
eGPUFaceCullTest GPU_face_culling_get(void)
eGPUStencilTest GPU_stencil_test_get(void)
bool GPU_depth_mask_get(void)
eGPUDepthTest GPU_depth_test_get(void)
void GPU_depth_test(eGPUDepthTest test)
struct GPUTexture GPUTexture
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
struct GPUVertBuf GPUVertBuf
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Texture
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
StateManager * state_manager
id< MTLComputeCommandEncoder > ensure_begin_compute_encoder()
id< MTLBlitCommandEncoder > ensure_begin_blit_encoder()
MTLContextGlobalShaderPipelineState pipeline_state
MTLScratchBufferManager & get_scratchbuffer_manager()
MTLCommandBufferManager main_command_buffer
static MTLContext * get()
MTLTemporaryBuffer scratch_buffer_allocate_range_aligned(uint64_t alloc_size, uint alignment)
uint gl_bindcode_get() const override
void swizzle_set(const char swizzle_mask[4]) override
MTLTexture(const char *name)
void generate_mipmap() override
void mip_range_set(int min, int max) override
void * read(int mip, eGPUDataFormat type) override
void update_sub(int mip, int offset[3], int extent[3], eGPUDataFormat type, const void *data) override
bool init_internal() override
void clear(eGPUDataFormat format, const void *data) override
void copy_to(Texture *dst) override
virtual void texture_unbind(Texture *tex)=0
eGPUTextureFormat format_
bool init_2D(int w, int h, int layers, int mip_len, eGPUTextureFormat format)
CCL_NAMESPACE_BEGIN struct Options options
SyclQueue void void * src
BLI_INLINE float fb(float length, float L)
ccl_global float * buffer
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_gpu_kernel_postfix ccl_global float int int int int float bool reset
clear internal cached data and reset random seed
void *(* MEM_mallocN)(size_t len, const char *str)
#define MTL_LOG_INFO(info,...)
#define MTL_LOG_WARNING(info,...)
#define MTL_LOG_ERROR(info,...)
MTLPixelFormat gpu_texture_format_to_metal(eGPUTextureFormat tex_format)
std::string tex_data_format_to_msl_type_str(eGPUDataFormat type)
bool validate_data_format_mtl(eGPUTextureFormat tex_format, eGPUDataFormat data_format)
static GPUContext * wrap(Context *ctx)
std::string tex_data_format_to_msl_texture_template_type(eGPUDataFormat type)
static Context * unwrap(GPUContext *ctx)
MTLPixelFormat mtl_format_get_writeable_view_format(MTLPixelFormat format)
static MTLTextureSwizzle swizzle_to_mtl(const char swizzle)
int get_mtl_format_num_components(MTLPixelFormat tex_format)
eGPUDataFormat to_mtl_internal_data_format(eGPUTextureFormat tex_format)
static size_t to_bytesize(GPUIndexBufType type)
int to_component_len(eGPUTextureFormat format)
int get_mtl_format_bytesize(MTLPixelFormat tex_format)
T length(const vec_base< T, Size > &a)
unsigned __int64 uint64_t
id< MTLBuffer > metal_buffer