37void gpu::MTLTexture::mtl_texture_init()
44 resource_mode_ = MTL_TEXTURE_MODE_DEFAULT;
49 mip_swizzle_view_ = nil;
55 vert_buffer_ =
nullptr;
56 vert_buffer_mtl_ = nil;
59 tex_swizzle_mask_[0] =
'r';
60 tex_swizzle_mask_[1] =
'g';
61 tex_swizzle_mask_[2] =
'b';
62 tex_swizzle_mask_[3] =
'a';
63 mtl_swizzle_mask_ = MTLTextureSwizzleChannelsMake(
64 MTLTextureSwizzleRed, MTLTextureSwizzleGreen, MTLTextureSwizzleBlue, MTLTextureSwizzleAlpha);
76 id<MTLTexture> metal_texture)
86 init_2D((
int)metal_texture.width, (
int)metal_texture.height, 0, 1,
format);
89 texture_ = metal_texture;
97 resource_mode_ = MTL_TEXTURE_MODE_EXTERNAL;
105 if (ctx !=
nullptr) {
117void gpu::MTLTexture::bake_mip_swizzle_view()
119 if (texture_view_dirty_flags_) {
125 if (resource_mode_ != MTL_TEXTURE_MODE_TEXTURE_VIEW &&
126 texture_view_dirty_flags_ == TEXTURE_VIEW_MIP_DIRTY && mip_swizzle_view_ == nil)
129 if (mip_texture_base_level_ == 0 && mip_texture_max_level_ == mtl_max_mips_) {
130 texture_view_dirty_flags_ = TEXTURE_VIEW_NOT_DIRTY;
136 if (mip_swizzle_view_ != nil) {
137 [mip_swizzle_view_ release];
138 mip_swizzle_view_ = nil;
143 const gpu::Texture *tex_view_src =
this;
144 if (resource_mode_ == MTL_TEXTURE_MODE_TEXTURE_VIEW) {
145 tex_view_src =
unwrap(source_texture_);
153 max_slices = tex_view_src->height_get();
157 max_slices = tex_view_src->depth_get();
166 max_slices = tex_view_src->depth_get();
177 if (texture_view_stencil_) {
178 switch (texture_view_pixel_format) {
179 case MTLPixelFormatDepth24Unorm_Stencil8:
180 texture_view_pixel_format = MTLPixelFormatX24_Stencil8;
182 case MTLPixelFormatDepth32Float_Stencil8:
183 texture_view_pixel_format = MTLPixelFormatX32_Stencil8;
186 BLI_assert_msg(
false,
"Texture format does not support stencil views.");
193 MTLTextureType texture_view_texture_type =
to_metal_type(type_);
200 (texture_view_pixel_format == texture_.pixelFormat) ||
202 "Usage Flag GPU_TEXTURE_USAGE_FORMAT_VIEW must be specified if a texture view is "
203 "created with a different format to its source texture.");
205 int range_len =
min_ii((mip_texture_max_level_ - mip_texture_base_level_) + 1,
206 (
int)texture_.mipmapLevelCount - mip_texture_base_level_);
208 BLI_assert(mip_texture_base_level_ < texture_.mipmapLevelCount);
209 BLI_assert(mip_texture_base_layer_ < max_slices);
211 mip_swizzle_view_ = [texture_
212 newTextureViewWithPixelFormat:texture_view_pixel_format
213 textureType:texture_view_texture_type
214 levels:NSMakeRange(mip_texture_base_level_, range_len)
215 slices:NSMakeRange(mip_texture_base_layer_, num_slices)
216 swizzle:mtl_swizzle_mask_];
218 "Updating texture view - MIP TEXTURE BASE LEVEL: %d, MAX LEVEL: %d (Range len: %d)",
219 mip_texture_base_level_,
220 min_ii(mip_texture_max_level_, (
int)texture_.mipmapLevelCount),
223 mip_swizzle_view_.label = [NSString
225 @"MipSwizzleView_%s__format=%u_type=%u_baselevel=%u_numlevels=%u_swizzle='%c%c%c%c'",
226 [[texture_ label] UTF8String],
227 (
uint)texture_view_pixel_format,
228 (
uint)texture_view_texture_type,
229 (
uint)mip_texture_base_level_,
231 tex_swizzle_mask_[0],
232 tex_swizzle_mask_[1],
233 tex_swizzle_mask_[2],
234 tex_swizzle_mask_[3]];
236 mip_swizzle_view_.label = [texture_ label];
238 texture_view_dirty_flags_ = TEXTURE_VIEW_NOT_DIRTY;
245id<MTLTexture> gpu::MTLTexture::get_metal_handle()
249 if (resource_mode_ == MTL_TEXTURE_MODE_VBO) {
250 id<MTLBuffer> buf = vert_buffer_->get_metal_buffer();
253 if (buf != vert_buffer_mtl_) {
255 "MTLTexture '%p' using MTL_TEXTURE_MODE_VBO requires re-generation due to updated "
262 this->init_internal(vert_buffer_);
265 buf = vert_buffer_->get_metal_buffer();
271 BLI_assert(vert_buffer_->get_metal_buffer() == vert_buffer_mtl_);
275 this->ensure_baked();
279 if (resource_mode_ == MTL_TEXTURE_MODE_TEXTURE_VIEW) {
280 BLI_assert_msg(mip_swizzle_view_,
"Texture view should always have a valid handle.");
283 if (mip_swizzle_view_ != nil || texture_view_dirty_flags_) {
284 bake_mip_swizzle_view();
289 if (mip_swizzle_view_ != nil) {
290 return mip_swizzle_view_;
298id<MTLTexture> gpu::MTLTexture::get_metal_handle_base()
302 this->ensure_baked();
305 if (resource_mode_ == MTL_TEXTURE_MODE_TEXTURE_VIEW) {
306 BLI_assert_msg(mip_swizzle_view_,
"Texture view should always have a valid handle.");
307 if (mip_swizzle_view_ != nil || texture_view_dirty_flags_) {
308 bake_mip_swizzle_view();
311 return mip_swizzle_view_;
321void gpu::MTLTexture::blit(id<MTLBlitCommandEncoder> blit_encoder,
327 gpu::MTLTexture *dst,
339 BLI_assert(width > 0 && height > 0 && depth > 0);
340 MTLSize src_size = MTLSizeMake(width, height, depth);
341 MTLOrigin src_origin = MTLOriginMake(src_x_offset, src_y_offset, src_z_offset);
342 MTLOrigin dst_origin = MTLOriginMake(dst_x_offset, dst_y_offset, dst_z_offset);
344 if (this->format_get() != dst->format_get()) {
346 "gpu::MTLTexture: Cannot copy between two textures of different types using a "
347 "blit encoder. TODO: Support this operation");
353 [blit_encoder copyFromTexture:this->get_metal_handle_base()
354 sourceSlice:src_slice
356 sourceOrigin:src_origin
358 toTexture:dst->get_metal_handle_base()
359 destinationSlice:dst_slice
360 destinationLevel:dst_mip
361 destinationOrigin:dst_origin];
375 BLI_assert(this->type_get() == dst->type_get());
377 GPUShader *
shader = fullscreen_blit_sh_get();
383 GPUFrameBuffer *blit_target_fb = dst->get_blit_framebuffer(dst_slice, dst_mip);
391 float w = dst->width_get();
392 float h = dst->height_get();
431 if (restore_fb !=
nullptr) {
439GPUFrameBuffer *gpu::MTLTexture::get_blit_framebuffer(
int dst_slice,
uint dst_mip)
443 bool update_attachments =
false;
446 update_attachments =
true;
451 if (blit_fb_slice_ != dst_slice || blit_fb_mip_ != dst_mip) {
452 update_attachments =
true;
456 if (update_attachments) {
462 wrap(
static_cast<Texture *
>(
this)),
int(dst_slice),
int(dst_mip)),
471 wrap(
static_cast<Texture *
>(
this)),
int(dst_slice),
int(dst_mip))});
473 blit_fb_slice_ = dst_slice;
474 blit_fb_mip_ = dst_mip;
484 sampler_state.
state = this->sampler_state;
486 return sampler_state;
497 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_TEXTURE_VIEW);
500 this->ensure_mipmaps(mip);
503 this->ensure_baked();
513 if (is_depth_format) {
517 update_sub_depth_2d(mip, offset, extent, type,
data);
521 "gpu::MTLTexture::update_sub not yet supported for other depth "
533 size_t totalsize = 0;
549 totalsize = input_bytes_per_pixel *
max_ulul(expected_update_w, 1);
552 totalsize = input_bytes_per_pixel *
max_ulul(expected_update_w, 1) * (size_t)extent[1];
555 totalsize = input_bytes_per_pixel *
max_ulul(expected_update_w, 1) * (size_t)extent[1] *
566 if (totalsize <= 0 || extent[0] <= 0) {
568 "MTLTexture::update_sub called with extent size of zero for one or more dimensions. "
569 "(%d, %d, %d) - DimCount: %u",
597 destination_num_channels,
604 bool can_use_direct_blit =
true;
605 if (!is_compressed && (expected_dst_bytes_per_pixel != input_bytes_per_pixel ||
606 num_channels != destination_num_channels))
608 can_use_direct_blit =
false;
611 if (is_depth_format) {
615 if (extent[0] == 1 && extent[1] == 1 && extent[2] == 1 && totalsize == 4) {
616 can_use_direct_blit =
false;
623 "SRGB data upload does not work correctly using compute upload. "
633 "Special input data type must be a 1-1 mapping with destination texture as it "
634 "cannot easily be split");
638 if (!can_use_direct_blit) {
642 "Updating texture layers other than mip=0 when data is mismatched is not "
643 "possible in METAL on macOS using texture->write\n");
650 "Updating texture -- destination MTLPixelFormat '%d' does not support write "
651 "operations, and no suitable TextureView format exists.\n",
652 *(
int *)(&destination_format));
662 if (compatible_write_format == MTLPixelFormatInvalid) {
663 MTL_LOG_ERROR(
"Cannot use compute update blit with texture-view format: %d\n",
664 *((
int *)&compatible_write_format));
670 totalsize,
true,
data);
675 id<MTLBlitCommandEncoder> blit_encoder = nil;
676 id<MTLComputeCommandEncoder> compute_encoder = nil;
677 id<MTLTexture> staging_texture = nil;
678 id<MTLTexture> texture_handle = nil;
681 bool use_staging_texture =
false;
683 if (can_use_direct_blit) {
690 if ((compatible_write_format != destination_format) &&
693 use_staging_texture =
true;
704 use_staging_texture =
true;
706 if (compatible_write_format != destination_format) {
708 use_staging_texture =
true;
714 if (use_staging_texture) {
717 MTLTextureUsage original_usage = texture_descriptor_.usage;
718 texture_descriptor_.usage = original_usage | MTLTextureUsageShaderWrite |
719 MTLTextureUsagePixelFormatView;
720 staging_texture = [ctx->
device newTextureWithDescriptor:texture_descriptor_];
721 staging_texture.label =
@"Staging texture";
722 texture_descriptor_.usage = original_usage;
725 texture_handle = ((compatible_write_format == destination_format)) ?
726 [staging_texture retain] :
727 [staging_texture newTextureViewWithPixelFormat:compatible_write_format];
731 if (compatible_write_format != destination_format) {
733 texture_handle = [texture_ newTextureViewWithPixelFormat:compatible_write_format];
736 texture_handle = texture_;
737 [texture_handle retain];
746 if (can_use_direct_blit) {
748 size_t bytes_per_row = expected_dst_bytes_per_pixel *
752 size_t bytes_per_image = bytes_per_row;
756 bytes_per_row = blocks_x * block_size;
757 bytes_per_image = bytes_per_row;
760 for (
int array_index = 0; array_index < max_array_index; array_index++) {
762 size_t buffer_array_offset = (bytes_per_image * (size_t)array_index);
764 copyFromBuffer:staging_buffer
765 sourceOffset:buffer_array_offset
766 sourceBytesPerRow:bytes_per_row
767 sourceBytesPerImage:bytes_per_image
768 sourceSize:MTLSizeMake(extent[0], 1, 1)
769 toTexture:texture_handle
773 destinationOrigin:MTLOriginMake(offset[0], 0, 0)];
779 id<MTLComputePipelineState> pso = texture_update_1d_get_kernel(
780 compute_specialization_kernel);
781 TextureUpdateParams
params = {mip,
795 dispatchThreads:MTLSizeMake(extent[0], 1, 1)
796 threadsPerThreadgroup:MTLSizeMake(64, 1, 1)];
799 id<MTLComputePipelineState> pso = texture_update_1d_array_get_kernel(
800 compute_specialization_kernel);
801 TextureUpdateParams
params = {mip,
802 {extent[0], extent[1], 1},
803 {offset[0], offset[1], 0},
815 dispatchThreads:MTLSizeMake(extent[0], extent[1], 1)
816 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
824 if (can_use_direct_blit) {
826 size_t bytes_per_row = expected_dst_bytes_per_pixel *
830 size_t bytes_per_image = bytes_per_row * extent[1];
835 bytes_per_row = blocks_x * block_size;
836 bytes_per_image = bytes_per_row * blocks_y;
839 size_t texture_array_relative_offset = 0;
843 for (
int array_slice = base_slice; array_slice < final_slice; array_slice++) {
845 if (array_slice > 0) {
850 [blit_encoder copyFromBuffer:staging_buffer
851 sourceOffset:texture_array_relative_offset
852 sourceBytesPerRow:bytes_per_row
853 sourceBytesPerImage:bytes_per_image
854 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
855 toTexture:texture_handle
856 destinationSlice:array_slice
858 destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)];
860 texture_array_relative_offset += bytes_per_image;
866 id<MTLComputePipelineState> pso = texture_update_2d_get_kernel(
867 compute_specialization_kernel);
868 TextureUpdateParams
params = {mip,
869 {extent[0], extent[1], 1},
870 {offset[0], offset[1], 0},
882 dispatchThreads:MTLSizeMake(
883 extent[0], extent[1], 1)
884 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
887 id<MTLComputePipelineState> pso = texture_update_2d_array_get_kernel(
888 compute_specialization_kernel);
889 TextureUpdateParams
params = {mip,
890 {extent[0], extent[1], extent[2]},
891 {offset[0], offset[1], offset[2]},
902 [compute_encoder dispatchThreads:MTLSizeMake(extent[0],
905 threadsPerThreadgroup:MTLSizeMake(4, 4, 4)];
913 if (can_use_direct_blit) {
914 size_t bytes_per_row = expected_dst_bytes_per_pixel *
918 size_t bytes_per_image = bytes_per_row * extent[1];
919 [blit_encoder copyFromBuffer:staging_buffer
921 sourceBytesPerRow:bytes_per_row
922 sourceBytesPerImage:bytes_per_image
923 sourceSize:MTLSizeMake(extent[0], extent[1], extent[2])
924 toTexture:texture_handle
927 destinationOrigin:MTLOriginMake(offset[0], offset[1], offset[2])];
930 id<MTLComputePipelineState> pso = texture_update_3d_get_kernel(
931 compute_specialization_kernel);
932 TextureUpdateParams
params = {mip,
933 {extent[0], extent[1], extent[2]},
934 {offset[0], offset[1], offset[2]},
946 dispatchThreads:MTLSizeMake(
947 extent[0], extent[1], extent[2])
948 threadsPerThreadgroup:MTLSizeMake(4, 4, 4)];
954 if (can_use_direct_blit) {
955 size_t bytes_per_row = expected_dst_bytes_per_pixel *
959 size_t bytes_per_image = bytes_per_row * extent[1];
960 size_t texture_array_relative_offset = 0;
963 for (
int i = 0;
i < extent[2];
i++) {
964 int face_index = offset[2] +
i;
966 [blit_encoder copyFromBuffer:staging_buffer
967 sourceOffset:texture_array_relative_offset
968 sourceBytesPerRow:bytes_per_row
969 sourceBytesPerImage:bytes_per_image
970 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
971 toTexture:texture_handle
972 destinationSlice:face_index
974 destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)];
975 texture_array_relative_offset += bytes_per_image;
980 "TODO(Metal): Support compute texture update for GPU_TEXTURE_CUBE %d, %d, %d\n",
988 if (can_use_direct_blit) {
990 size_t bytes_per_row = expected_dst_bytes_per_pixel *
994 size_t bytes_per_image = bytes_per_row * extent[1];
997 size_t texture_array_relative_offset = 0;
998 for (
int i = 0;
i < extent[2];
i++) {
999 int face_index = offset[2] +
i;
1000 [blit_encoder copyFromBuffer:staging_buffer
1001 sourceOffset:texture_array_relative_offset
1002 sourceBytesPerRow:bytes_per_row
1003 sourceBytesPerImage:bytes_per_image
1004 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
1005 toTexture:texture_handle
1006 destinationSlice:face_index
1007 destinationLevel:mip
1008 destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)];
1009 texture_array_relative_offset += bytes_per_image;
1014 "TODO(Metal): Support compute texture update for GPU_TEXTURE_CUBE_ARRAY %d, %d, "
1034 if (use_staging_texture) {
1046 for (
int array_index = base_slice; array_index < final_slice; array_index++) {
1047 [blit_encoder copyFromTexture:staging_texture
1048 sourceSlice:array_index
1050 sourceOrigin:MTLOriginMake(offset[0], 0, 0)
1051 sourceSize:MTLSizeMake(extent[0], 1, 1)
1053 destinationSlice:array_index
1054 destinationLevel:mip
1055 destinationOrigin:MTLOriginMake(offset[0], 0, 0)];
1062 for (
int array_index = base_slice; array_index < final_slice; array_index++) {
1063 [blit_encoder copyFromTexture:staging_texture
1064 sourceSlice:array_index
1066 sourceOrigin:MTLOriginMake(offset[0], offset[1], 0)
1067 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
1069 destinationSlice:array_index
1070 destinationLevel:mip
1071 destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)];
1075 [blit_encoder copyFromTexture:staging_texture
1078 sourceOrigin:MTLOriginMake(offset[0], offset[1], offset[2])
1079 sourceSize:MTLSizeMake(extent[0], extent[1], extent[2])
1082 destinationLevel:mip
1083 destinationOrigin:MTLOriginMake(offset[0], offset[1], offset[2])];
1088 for (
int i = 0;
i < extent[2];
i++) {
1089 int face_index = offset[2] +
i;
1090 [blit_encoder copyFromTexture:staging_texture
1091 sourceSlice:face_index
1093 sourceOrigin:MTLOriginMake(offset[0], offset[1], 0)
1094 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
1096 destinationSlice:face_index
1097 destinationLevel:mip
1098 destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)];
1107 [staging_texture release];
1111 if (can_use_direct_blit) {
1114 if (texture_.storageMode == MTLStorageModeManaged) {
1115 [blit_encoder synchronizeResource:texture_];
1117 [blit_encoder optimizeContentsForGPUAccess:texture_];
1123 if (texture_.storageMode == MTLStorageModeManaged) {
1125 [blit_encoder synchronizeResource:texture_];
1127 [blit_encoder optimizeContentsForGPUAccess:texture_];
1131 [texture_handle release];
1138 temp_allocation->
free();
1145 GPUPixelBuffer *pixbuf)
1155 if (buffer == nil) {
1160 this->ensure_baked();
1167 size_t bytes_per_row = bits_per_pixel * extent[0];
1168 size_t bytes_per_image = bytes_per_row * extent[1];
1178 [blit_encoder copyFromBuffer:buffer
1180 sourceBytesPerRow:bytes_per_row
1181 sourceBytesPerImage:bytes_per_image
1182 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
1186 destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)];
1188 if (texture_.storageMode == MTLStorageModeManaged) {
1189 [blit_encoder synchronizeResource:texture_];
1191 [blit_encoder optimizeContentsForGPUAccess:texture_];
1198void gpu::MTLTexture::ensure_mipmaps(
int miplvl)
1202 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_TEXTURE_VIEW);
1207 int max_dimension =
max_iii(w_, effective_h, effective_d);
1208 int max_miplvl =
floor(
log2(max_dimension));
1209 miplvl =
min_ii(max_miplvl, miplvl);
1212 if (mipmaps_ < miplvl) {
1216 if (is_baked_ && mipmaps_ > mtl_max_mips_) {
1218 "Texture requires a higher mipmap level count. Please specify the required "
1221 MTL_LOG_WARNING(
"Texture requires regenerating due to increase in mip-count");
1224 this->mip_range_set(0, mipmaps_);
1240 MTL_LOG_ERROR(
"Cannot Generate mip-maps -- metal device invalid\n");
1246 this->ensure_mipmaps(mtl_max_mips_);
1249 this->ensure_baked();
1250 BLI_assert_msg(is_baked_ && texture_,
"MTLTexture is not valid");
1252 if (
mipmaps_ == 1 || mtl_max_mips_ == 1) {
1262 MTL_LOG_WARNING(
"Cannot generate mipmaps for textures using DEPTH formats");
1270 [enc insertDebugSignpost:
@"Generate MipMaps"];
1272 [enc generateMipmapsForTexture:texture_];
1273 has_generated_mips_ =
true;
1283 (mt_dst->
d_ == mt_src->
d_));
1294 this->ensure_baked();
1306 int extent[3] = {1, 1, 1};
1309 switch (mt_dst->
type_) {
1315 [blit_encoder copyFromTexture:this->get_metal_handle_base()
1316 toTexture:mt_dst->get_metal_handle_base()];
1317 [blit_encoder optimizeContentsForGPUAccess:mt_dst->get_metal_handle_base()];
1321 this->blit(blit_encoder,
1344 this->ensure_baked();
1347 bool do_render_pass_clear =
true;
1349 do_render_pass_clear =
false;
1353 if (backing_buffer_ !=
nullptr) {
1356 bool fast_buf_clear =
true;
1358 for (
int i = 1;
i < channel_size * channel_len;
i++) {
1359 fast_buf_clear = fast_buf_clear && (val[
i] == val[0]);
1361 if (fast_buf_clear) {
1367 id<MTLBlitCommandEncoder> blit_encoder =
1369 [blit_encoder fillBuffer:backing_buffer_->get_metal_buffer()
1370 range:NSMakeRange(0, backing_buffer_->get_size())
1375 "Non-repeating-byte-pattern clear for buffer-backed textures not supported!");
1380 if (do_render_pass_clear) {
1408 id<MTLTexture> texture_handle = texture_;
1411 id<MTLComputeCommandEncoder> compute_encoder =
1417 id<MTLComputePipelineState> pso = texture_update_1d_get_kernel(
1418 compute_specialization_kernel);
1419 TextureUpdateParams
params = {0,
1432 [compute_encoder dispatchThreads:MTLSizeMake(
w_, 1, 1)
1433 threadsPerThreadgroup:MTLSizeMake(64, 1, 1)];
1436 id<MTLComputePipelineState> pso = texture_update_1d_array_get_kernel(
1437 compute_specialization_kernel);
1438 TextureUpdateParams
params = {0,
1451 [compute_encoder dispatchThreads:MTLSizeMake(
w_,
h_, 1)
1452 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
1456 "gpu::MTLTexture::clear requires compute pass for texture"
1457 "type: %d, but this is not yet supported",
1465 if (texture_.storageMode == MTLStorageModeManaged) {
1466 [blit_encoder synchronizeResource:texture_];
1468 [blit_encoder optimizeContentsForGPUAccess:texture_];
1477 return MTLTextureSwizzleRed;
1480 return MTLTextureSwizzleGreen;
1483 return MTLTextureSwizzleBlue;
1486 return MTLTextureSwizzleAlpha;
1488 return MTLTextureSwizzleZero;
1490 return MTLTextureSwizzleOne;
1496 if (memcmp(tex_swizzle_mask_, swizzle_mask, 4) != 0) {
1497 memcpy(tex_swizzle_mask_, swizzle_mask, 4);
1500 MTLTextureSwizzleChannels new_swizzle_mask = MTLTextureSwizzleChannelsMake(
1506 mtl_swizzle_mask_ = new_swizzle_mask;
1507 texture_view_dirty_flags_ |= TEXTURE_VIEW_SWIZZLE_DIRTY;
1532 " MTLTexture of type TEXTURE_1D_ARRAY or TEXTURE_BUFFER cannot have a mipcount "
1533 "greater than 1\n");
1541 mip_texture_base_level_ =
mip_min_;
1543 texture_view_dirty_flags_ |= TEXTURE_VIEW_MIP_DIRTY;
1554 int extent[3] = {1, 1, 1};
1557 size_t sample_len = extent[0] *
max_ii(extent[1], 1) *
max_ii(extent[2], 1);
1559 size_t texture_size = sample_len * sample_size;
1566 this->read_internal(
1567 mip, 0, 0, 0, extent[0], extent[1], extent[2], type, num_channels, texture_size + 8,
data);
1571 MTL_LOG_WARNING(
"MTLTexture::read - reading from texture with no image data");
1578void gpu::MTLTexture::read_internal(
int mip,
1586 int num_output_components,
1587 size_t debug_data_size,
1592 MTL_LOG_WARNING(
"gpu::MTLTexture::read_internal - Trying to read from a non-baked texture!");
1601 BLI_assert(num_output_components <= num_channels);
1602 size_t desired_output_bpp = num_output_components *
to_bytesize(desired_output_format);
1611 bool format_conversion_needed = (data_format != desired_output_format);
1612 bool can_use_simple_read = (desired_output_bpp == image_bpp) && (!format_conversion_needed) &&
1613 (num_output_components == image_components);
1617 if (is_depth_format) {
1618 can_use_simple_read =
false;
1620 image_components = 1;
1636 image_bpp =
sizeof(int);
1637 image_components = 1;
1638 desired_output_bpp =
sizeof(int);
1639 num_output_components = 1;
1642 format_conversion_needed =
false;
1643 can_use_simple_read =
true;
1647 size_t bytes_per_row = desired_output_bpp * width;
1648 size_t bytes_per_image = bytes_per_row * height;
1649 size_t total_bytes = bytes_per_image *
max_ii(depth, 1);
1651 if (can_use_simple_read) {
1655 ((num_output_components *
to_bytesize(desired_output_format)) == desired_output_bpp) &&
1656 (desired_output_bpp == image_bpp));
1664 total_bytes, 256,
true);
1667 id<MTLBuffer> destination_buffer = dest_buf->get_metal_buffer();
1669 void *destination_buffer_host_ptr = dest_buf->get_host_ptr();
1670 BLI_assert(destination_buffer_host_ptr !=
nullptr);
1673 int depth_format_mode = 0;
1674 if (is_depth_format) {
1675 depth_format_mode = 1;
1676 switch (desired_output_format) {
1678 depth_format_mode = 1;
1681 depth_format_mode = 2;
1684 depth_format_mode = 4;
1692 TextureReadRoutineSpecialisation compute_specialization_kernel = {
1696 num_output_components,
1699 bool copy_successful =
false;
1707 id<MTLTexture> read_texture = texture_;
1709 if (resource_mode_ == MTL_TEXTURE_MODE_TEXTURE_VIEW) {
1710 read_texture = this->get_metal_handle();
1715 read_texture = [read_texture newTextureViewWithPixelFormat:MTLPixelFormatRGBA8Unorm];
1721 if (can_use_simple_read) {
1723 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1725 [enc insertDebugSignpost:
@"GPUTextureRead1D"];
1727 [enc copyFromTexture:read_texture
1730 sourceOrigin:MTLOriginMake(x_off, 0, 0)
1731 sourceSize:MTLSizeMake(width, 1, 1)
1732 toBuffer:destination_buffer
1734 destinationBytesPerRow:bytes_per_row
1735 destinationBytesPerImage:bytes_per_image];
1736 copy_successful =
true;
1741 id<MTLComputeCommandEncoder> compute_encoder =
1742 ctx->main_command_buffer.ensure_begin_compute_encoder();
1743 id<MTLComputePipelineState> pso = texture_read_1d_get_kernel(
1744 compute_specialization_kernel);
1745 TextureReadParams
params = {
1755 cs.bind_compute_buffer(destination_buffer, 0, 1);
1756 cs.bind_compute_texture(read_texture, 0);
1757 [compute_encoder dispatchThreads:MTLSizeMake(width, 1, 1)
1758 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
1759 copy_successful =
true;
1764 if (can_use_simple_read) {
1766 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1768 [enc insertDebugSignpost:
@"GPUTextureRead1DArray"];
1771 int base_slice = y_off;
1772 int final_slice = base_slice + height;
1773 size_t texture_array_relative_offset = 0;
1775 for (
int array_slice = base_slice; array_slice < final_slice; array_slice++) {
1776 [enc copyFromTexture:read_texture
1777 sourceSlice:base_slice
1779 sourceOrigin:MTLOriginMake(x_off, 0, 0)
1780 sourceSize:MTLSizeMake(width, 1, 1)
1781 toBuffer:destination_buffer
1782 destinationOffset:texture_array_relative_offset
1783 destinationBytesPerRow:bytes_per_row
1784 destinationBytesPerImage:bytes_per_row];
1785 texture_array_relative_offset += bytes_per_row;
1787 copy_successful =
true;
1791 id<MTLComputeCommandEncoder> compute_encoder =
1792 ctx->main_command_buffer.ensure_begin_compute_encoder();
1793 id<MTLComputePipelineState> pso = texture_read_1d_array_get_kernel(
1794 compute_specialization_kernel);
1795 TextureReadParams
params = {
1805 cs.bind_compute_buffer(destination_buffer, 0, 1);
1806 cs.bind_compute_texture(read_texture, 0);
1807 [compute_encoder dispatchThreads:MTLSizeMake(width, height, 1)
1808 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
1809 copy_successful =
true;
1814 if (can_use_simple_read) {
1816 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1818 [enc insertDebugSignpost:
@"GPUTextureRead2D"];
1820 [enc copyFromTexture:read_texture
1823 sourceOrigin:MTLOriginMake(x_off, y_off, 0)
1824 sourceSize:MTLSizeMake(width, height, 1)
1825 toBuffer:destination_buffer
1827 destinationBytesPerRow:bytes_per_row
1828 destinationBytesPerImage:bytes_per_image];
1829 copy_successful =
true;
1834 id<MTLComputeCommandEncoder> compute_encoder =
1835 ctx->main_command_buffer.ensure_begin_compute_encoder();
1836 id<MTLComputePipelineState> pso = texture_read_2d_get_kernel(
1837 compute_specialization_kernel);
1838 TextureReadParams
params = {
1848 cs.bind_compute_buffer(destination_buffer, 0, 1);
1849 cs.bind_compute_texture(read_texture, 0);
1850 [compute_encoder dispatchThreads:MTLSizeMake(width, height, 1)
1851 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
1852 copy_successful =
true;
1857 if (can_use_simple_read) {
1859 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1861 [enc insertDebugSignpost:
@"GPUTextureRead2DArray"];
1863 int base_slice = z_off;
1864 int final_slice = base_slice + depth;
1865 size_t texture_array_relative_offset = 0;
1867 for (
int array_slice = base_slice; array_slice < final_slice; array_slice++) {
1868 [enc copyFromTexture:read_texture
1869 sourceSlice:array_slice
1871 sourceOrigin:MTLOriginMake(x_off, y_off, 0)
1872 sourceSize:MTLSizeMake(width, height, 1)
1873 toBuffer:destination_buffer
1874 destinationOffset:texture_array_relative_offset
1875 destinationBytesPerRow:bytes_per_row
1876 destinationBytesPerImage:bytes_per_image];
1877 texture_array_relative_offset += bytes_per_image;
1879 copy_successful =
true;
1884 id<MTLComputeCommandEncoder> compute_encoder =
1885 ctx->main_command_buffer.ensure_begin_compute_encoder();
1886 id<MTLComputePipelineState> pso = texture_read_2d_array_get_kernel(
1887 compute_specialization_kernel);
1888 TextureReadParams
params = {
1890 {width, height, depth},
1891 {x_off, y_off, z_off},
1898 cs.bind_compute_buffer(destination_buffer, 0, 1);
1899 cs.bind_compute_texture(read_texture, 0);
1901 dispatchThreads:MTLSizeMake(width, height, depth)
1902 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
1903 copy_successful =
true;
1908 if (can_use_simple_read) {
1910 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1912 [enc insertDebugSignpost:
@"GPUTextureRead3D"];
1914 [enc copyFromTexture:read_texture
1917 sourceOrigin:MTLOriginMake(x_off, y_off, z_off)
1918 sourceSize:MTLSizeMake(width, height, depth)
1919 toBuffer:destination_buffer
1921 destinationBytesPerRow:bytes_per_row
1922 destinationBytesPerImage:bytes_per_image];
1923 copy_successful =
true;
1928 id<MTLComputeCommandEncoder> compute_encoder =
1929 ctx->main_command_buffer.ensure_begin_compute_encoder();
1930 id<MTLComputePipelineState> pso = texture_read_3d_get_kernel(
1931 compute_specialization_kernel);
1932 TextureReadParams
params = {
1934 {width, height, depth},
1935 {x_off, y_off, z_off},
1942 cs.bind_compute_buffer(destination_buffer, 0, 1);
1943 cs.bind_compute_texture(read_texture, 0);
1945 dispatchThreads:MTLSizeMake(width, height, depth)
1946 threadsPerThreadgroup:MTLSizeMake(4, 4, 4)];
1947 copy_successful =
true;
1954 "z_off > 0 is only supported by TEXTURE CUBE ARRAY reads.");
1956 "depth > 6 is only supported by TEXTURE CUBE ARRAY reads. ");
1957 if (can_use_simple_read) {
1958 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1960 [enc insertDebugSignpost:
@"GPUTextureReadCubeArray"];
1964 int base_slice = z_off;
1965 int final_slice = base_slice + depth;
1966 size_t texture_array_relative_offset = 0;
1968 for (
int array_slice = base_slice; array_slice < final_slice; array_slice++) {
1969 [enc copyFromTexture:read_texture
1970 sourceSlice:array_slice
1972 sourceOrigin:MTLOriginMake(x_off, y_off, 0)
1973 sourceSize:MTLSizeMake(width, height, 1)
1974 toBuffer:destination_buffer
1975 destinationOffset:texture_array_relative_offset
1976 destinationBytesPerRow:bytes_per_row
1977 destinationBytesPerImage:bytes_per_image];
1979 texture_array_relative_offset += bytes_per_image;
1981 MTL_LOG_INFO(
"Copying texture data to buffer GPU_TEXTURE_CUBE_ARRAY");
1982 copy_successful =
true;
1985 MTL_LOG_ERROR(
"TODO(Metal): unsupported compute copy of texture cube array");
1991 "gpu::MTLTexture::read_internal simple-copy not yet supported for texture "
1997 if (copy_successful) {
2000 if (dest_buf->get_resource_options() == MTLResourceStorageModeManaged) {
2001 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
2003 [enc insertDebugSignpost:
@"GPUTextureRead-syncResource"];
2005 [enc synchronizeResource:destination_buffer];
2012 memcpy(r_data, destination_buffer_host_ptr, total_bytes);
2013 MTL_LOG_INFO(
"gpu::MTLTexture::read_internal success! %lu bytes read", total_bytes);
2017 "gpu::MTLTexture::read_internal not yet supported for this config -- data "
2018 "format different (src %lu bytes, dst %lu bytes) (src format: %d, dst format: %d), or "
2019 "varying component counts (src %d, dst %d)",
2023 (
int)desired_output_format,
2025 num_output_components);
2041 this->prepare_internal();
2064 id<MTLBuffer> source_buffer = mtl_vbo->get_metal_buffer();
2076 size_t bytes_per_row = bytes_per_pixel *
w_;
2079 uint32_t align_requirement = uint32_t(
2080 [mtl_ctx->
device minimumLinearTextureAlignmentForPixelFormat:mtl_format]);
2084 if (
format->stride > bytes_per_pixel &&
format->attr_len > 1) {
2090 if (bytes_per_pixel *
format->attr_len !=
format->stride) {
2092 "Cannot split attributes across multiple pixels as attribute format sizes do "
2099 bytes_per_row *=
format->attr_len;
2106 "Image should contain one pixel for each attribute in every vertex.");
2111 "Pixel format stride MUST match the texture format stride -- These being different "
2112 "is likely caused by Metal's VBO padding to a minimum of 4-bytes per-vertex."
2113 " If multiple attributes are used. Each attribute is to be packed into its own "
2114 "individual pixel when stride length is exceeded. ");
2119 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
2120 texture_descriptor_.pixelFormat = mtl_format;
2121 texture_descriptor_.textureType = MTLTextureTypeTextureBuffer;
2122 texture_descriptor_.width =
w_;
2123 texture_descriptor_.height = 1;
2124 texture_descriptor_.depth = 1;
2125 texture_descriptor_.arrayLength = 1;
2126 texture_descriptor_.mipmapLevelCount = mtl_max_mips_;
2127 texture_descriptor_.usage =
2128 MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite |
2129 MTLTextureUsagePixelFormatView;
2130 texture_descriptor_.storageMode = [source_buffer storageMode];
2131 texture_descriptor_.sampleCount = 1;
2132 texture_descriptor_.cpuCacheMode = [source_buffer cpuCacheMode];
2133 texture_descriptor_.hazardTrackingMode = [source_buffer hazardTrackingMode];
2135 texture_ = [source_buffer
2136 newTextureWithDescriptor:texture_descriptor_
2139 aligned_w_ = bytes_per_row / bytes_per_pixel;
2142 texture_.label = [NSString stringWithUTF8String:this->
get_name()];
2145 resource_mode_ = MTL_TEXTURE_MODE_VBO;
2148 vert_buffer_ = mtl_vbo;
2149 vert_buffer_mtl_ = source_buffer;
2162 this->prepare_internal();
2165 resource_mode_ = MTL_TEXTURE_MODE_TEXTURE_VIEW;
2166 source_texture_ = src;
2167 mip_texture_base_level_ = mip_offset;
2168 mip_texture_base_layer_ = layer_offset;
2169 texture_view_dirty_flags_ |= TEXTURE_VIEW_MIP_DIRTY;
2176 mtltex->ensure_baked();
2177 texture_ = mtltex->texture_;
2186 texture_view_stencil_ =
false;
2189 texture_view_stencil_ =
true;
2193 bake_mip_swizzle_view();
2209void gpu::MTLTexture::prepare_internal()
2213 internal_gpu_image_usage_flags_ = gpu_image_usage_flags_;
2236 mtl_max_mips_ = mipmaps_;
2240void gpu::MTLTexture::ensure_baked()
2244 id<MTLTexture> previous_texture = nil;
2245 bool copy_previous_contents =
false;
2247 if (is_baked_ && is_dirty_) {
2248 copy_previous_contents =
true;
2249 previous_texture = texture_;
2250 [previous_texture retain];
2259 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_EXTERNAL);
2260 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_TEXTURE_VIEW);
2261 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_VBO);
2280 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
2281 texture_descriptor_.pixelFormat = mtl_format;
2284 texture_descriptor_.width = w_;
2285 texture_descriptor_.height = 1;
2286 texture_descriptor_.depth = 1;
2288 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
2290 texture_descriptor_.storageMode = MTLStorageModePrivate;
2291 texture_descriptor_.sampleCount = 1;
2292 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
2293 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
2300 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
2301 texture_descriptor_.pixelFormat = mtl_format;
2304 texture_descriptor_.width = w_;
2305 texture_descriptor_.height = h_;
2306 texture_descriptor_.depth = 1;
2308 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
2310 texture_descriptor_.storageMode = MTLStorageModePrivate;
2311 texture_descriptor_.sampleCount = 1;
2312 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
2313 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
2319 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
2320 texture_descriptor_.pixelFormat = mtl_format;
2321 texture_descriptor_.textureType = MTLTextureType3D;
2322 texture_descriptor_.width = w_;
2323 texture_descriptor_.height = h_;
2324 texture_descriptor_.depth = d_;
2325 texture_descriptor_.arrayLength = 1;
2326 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
2328 texture_descriptor_.storageMode = MTLStorageModePrivate;
2329 texture_descriptor_.sampleCount = 1;
2330 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
2331 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
2340 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
2341 texture_descriptor_.pixelFormat = mtl_format;
2343 MTLTextureTypeCubeArray :
2345 texture_descriptor_.width = w_;
2346 texture_descriptor_.height = h_;
2347 texture_descriptor_.depth = 1;
2349 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
2351 texture_descriptor_.storageMode = MTLStorageModePrivate;
2352 texture_descriptor_.sampleCount = 1;
2353 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
2354 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
2359 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
2360 texture_descriptor_.pixelFormat = mtl_format;
2361 texture_descriptor_.textureType = MTLTextureTypeTextureBuffer;
2362 texture_descriptor_.width = w_;
2363 texture_descriptor_.height = 1;
2364 texture_descriptor_.depth = 1;
2365 texture_descriptor_.arrayLength = 1;
2366 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
2368 texture_descriptor_.storageMode = MTLStorageModePrivate;
2369 texture_descriptor_.sampleCount = 1;
2370 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
2371 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
2375 MTL_LOG_ERROR(
"[METAL] Error: Cannot create texture with unknown type: %d\n", type_);
2381 resource_mode_ = MTL_TEXTURE_MODE_DEFAULT;
2387 if (is_tile_based_arch) {
2388 texture_descriptor_.storageMode = MTLStorageModeMemoryless;
2401 "Texture atomic fallback support is only available for GPU_TEXTURE_2D, "
2402 "GPU_TEXTURE_2D_ARRAY and GPU_TEXTURE_3D.");
2411 const uint max_width = 16384;
2412 const uint max_height = 16384;
2413 const uint pixels_res = w_ * h_ * d_;
2415 uint new_w = 0, new_h = 0;
2416 if (pixels_res <= max_width) {
2422 new_h = ((pixels_res % new_w) == 0) ? (pixels_res / new_w) : ((pixels_res / new_w) + 1);
2425 texture_descriptor_.width = new_w;
2426 texture_descriptor_.height = new_h;
2430 texture_descriptor_.height <= max_height,
2431 "Atomic fallback support texture is too large.");
2436 size_t bytes_per_row = bytes_per_pixel * texture_descriptor_.width;
2437 size_t total_bytes = bytes_per_row * texture_descriptor_.height;
2444 texture_descriptor_.textureType = MTLTextureType2D;
2445 texture_descriptor_.depth = 1;
2446 texture_descriptor_.arrayLength = 1;
2450 tex_buffer_metadata_[0] = w_;
2451 tex_buffer_metadata_[1] = h_;
2452 tex_buffer_metadata_[2] = d_;
2457 [ctx->device minimumLinearTextureAlignmentForPixelFormat:mtl_format]);
2459 texture_ = [backing_buffer_->get_metal_buffer()
2460 newTextureWithDescriptor:texture_descriptor_
2462 bytesPerRow:aligned_bytes_per_row];
2464 tex_buffer_metadata_[3] = bytes_per_row / bytes_per_pixel;
2467 texture_.label = [NSString
2468 stringWithFormat:
@"AtomicBufferBackedTexture_%s", this->
get_name()];
2474 texture_ = [ctx->device newTextureWithDescriptor:texture_descriptor_];
2478 texture_.label = [NSString stringWithFormat:
@"MemorylessTexture_%s", this->
get_name()];
2481 texture_.label = [NSString stringWithFormat:
@"Texture_%s", this->
get_name()];
2492 if (copy_previous_contents) {
2494 [previous_texture release];
2498void gpu::MTLTexture::reset()
2502 if (texture_ != nil) {
2510 if (backing_buffer_ !=
nullptr) {
2511 backing_buffer_->free();
2512 backing_buffer_ =
nullptr;
2516 if (storage_buffer_ !=
nullptr) {
2517 delete storage_buffer_;
2518 storage_buffer_ =
nullptr;
2521 if (texture_no_srgb_ != nil) {
2522 [texture_no_srgb_ release];
2523 texture_no_srgb_ = nil;
2526 if (mip_swizzle_view_ != nil) {
2527 [mip_swizzle_view_ release];
2528 mip_swizzle_view_ = nil;
2538 if (texture_descriptor_ !=
nullptr) {
2539 [texture_descriptor_ release];
2540 texture_descriptor_ =
nullptr;
2544 has_generated_mips_ =
false;
2558 backing_buffer_ !=
nullptr,
2559 "Resource must have been created as a buffer backed resource to support SSBO wrapping.");
2561 this->ensure_baked();
2562 if (storage_buffer_ == nil) {
2564 id<MTLBuffer> backing_buffer = [texture_ buffer];
2568 return storage_buffer_;
2580id<MTLTexture> MTLTexture::get_non_srgb_handle()
2582 id<MTLTexture> base_tex = get_metal_handle_base();
2584 if (texture_no_srgb_ == nil) {
2585 texture_no_srgb_ = [base_tex newTextureViewWithPixelFormat:MTLPixelFormatRGBA8Unorm];
2587 return texture_no_srgb_;
2618 MTLResourceOptions resource_options = ([ctx->
device hasUnifiedMemory]) ?
2619 MTLResourceStorageModeShared :
2620 MTLResourceStorageModeManaged;
2622 if (buffer_ != nil) {
2623 id<MTLBuffer> new_buffer = [ctx->
device newBufferWithBytes:[buffer_ contents]
2627 buffer_ = new_buffer;
2633 return [buffer_ contents];
2638 if (buffer_ == nil) {
2643 if (buffer_.resourceOptions & MTLResourceStorageModeManaged) {
2644 [buffer_ didModifyRange:NSMakeRange(0,
size_)];
2655 if (![ctx->
device hasUnifiedMemory]) {
2656 return native_handle;
2664 return native_handle;
#define BLI_assert_unreachable()
#define BLI_assert_msg(a, msg)
MINLINE int min_ii(int a, int b)
MINLINE uint divide_ceil_u(uint a, uint b)
MINLINE int max_ii(int a, int b)
MINLINE int max_iii(int a, int b, int c)
MINLINE uint64_t ceil_to_multiple_ul(uint64_t a, uint64_t b)
#define UNUSED_VARS_NDEBUG(...)
GHOST C-API function and type declarations.
#define GPU_batch_texture_bind(batch, name, tex)
void GPU_batch_draw(blender::gpu::Batch *batch)
void GPU_batch_set_shader(blender::gpu::Batch *batch, GPUShader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
blender::gpu::Batch * GPU_batch_preset_quad()
int GPU_max_texture_3d_size()
GPUFrameBuffer * GPU_framebuffer_create(const char *name)
GPUFrameBuffer * GPU_framebuffer_active_get()
void GPU_framebuffer_restore()
#define GPU_ATTACHMENT_NONE
void GPU_framebuffer_free(GPUFrameBuffer *fb)
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
#define GPU_framebuffer_ensure_config(_fb,...)
#define GPU_ATTACHMENT_TEXTURE_LAYER_MIP(_texture, _layer, _mip)
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)
eGPUFaceCullTest GPU_face_culling_get()
void GPU_blend(eGPUBlend blend)
void GPU_scissor_test(bool enable)
eGPUBlend GPU_blend_get()
void GPU_depth_mask(bool depth)
eGPUDepthTest GPU_depth_test_get()
void GPU_stencil_test(eGPUStencilTest test)
void GPU_stencil_write_mask_set(uint write_mask)
void GPU_stencil_reference_set(uint reference)
eGPUStencilTest GPU_stencil_test_get()
uint GPU_stencil_mask_get()
void GPU_depth_test(eGPUDepthTest test)
bool GPU_depth_mask_get()
@ GPU_DATA_2_10_10_10_REV
@ GPU_TEXTURE_USAGE_SHADER_WRITE
@ GPU_TEXTURE_USAGE_HOST_READ
@ GPU_TEXTURE_USAGE_MEMORYLESS
@ GPU_TEXTURE_USAGE_ATTACHMENT
@ GPU_TEXTURE_USAGE_ATOMIC
@ GPU_TEXTURE_USAGE_FORMAT_VIEW
eGPUTextureUsage GPU_texture_usage(const GPUTexture *texture)
const GPUVertFormat * GPU_vertbuf_get_format(const blender::gpu::VertBuf *verts)
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
void reset()
clear internal cached data and reset random seed
StateManager * state_manager
static MTLCapabilities & get_capabilities()
gpu::MTLBuffer * allocate_with_data(uint64_t size, bool cpu_visible, const void *data=nullptr)
gpu::MTLBuffer * allocate(uint64_t size, bool cpu_visible)
gpu::MTLBuffer * allocate_aligned(uint64_t size, uint alignment, bool cpu_visible)
id< MTLBuffer > get_metal_buffer() const
id< MTLComputeCommandEncoder > ensure_begin_compute_encoder()
MTLComputeState & get_compute_state()
id< MTLBlitCommandEncoder > ensure_begin_blit_encoder()
void bind_compute_bytes(const void *bytes, uint64_t length, uint index)
void bind_compute_texture(id< MTLTexture > tex, uint slot)
void bind_compute_buffer(id< MTLBuffer > buffer, uint64_t buffer_offset, uint index)
void bind_pso(id< MTLComputePipelineState > pso)
static MTLContext * get()
MTLContextGlobalShaderPipelineState pipeline_state
MTLCommandBufferManager main_command_buffer
static MTLBufferPool * get_global_memory_manager()
GPUPixelBufferNativeHandle get_native_handle() override
id< MTLBuffer > get_metal_buffer()
size_t get_size() override
MTLPixelBuffer(size_t size)
void * read(int mip, eGPUDataFormat type) override
void copy_to(Texture *dst) override
void update_sub(int mip, int offset[3], int extent[3], eGPUDataFormat type, const void *data) override
MTLTexture(const char *name)
void clear(eGPUDataFormat format, const void *data) override
friend class MTLStorageBuf
MTLStorageBuf * get_storagebuf()
void mip_range_set(int min, int max) override
void generate_mipmap() override
bool init_internal() override
void swizzle_set(const char swizzle_mask[4]) override
uint gl_bindcode_get() const override
virtual void texture_unbind(Texture *tex)=0
eGPUTextureFormat format_
eGPUTextureFormatFlag format_flag_
eGPUTextureUsage gpu_image_usage_flags_
char name_[DEBUG_NAME_LEN]
int dimensions_count() const
GPUAttachmentType attachment_type(int slot) const
void mip_size_get(int mip, int r_size[3]) const
Texture(const char *name)
bool init_2D(int w, int h, int layers, int mip_len, eGPUTextureFormat format)
CCL_NAMESPACE_BEGIN struct Options options
blender::gpu::Batch * quad
float length(VecOp< float, D >) RET
BLI_INLINE float fb(float length, float L)
void * MEM_mallocN(size_t len, const char *str)
MINLINE unsigned long long max_ulul(unsigned long long a, unsigned long long b)
#define MTL_LOG_INFO(info,...)
#define MTL_LOG_WARNING(info,...)
#define MTL_LOG_ERROR(info,...)
std::string get_name(const VolumeGridData &grid)
size_t get_mtl_format_bytesize(MTLPixelFormat tex_format)
static Context * unwrap(GPUContext *ctx)
MTLPixelFormat gpu_texture_format_to_metal(eGPUTextureFormat tex_format)
std::string tex_data_format_to_msl_type_str(eGPUDataFormat type)
size_t to_block_size(eGPUTextureFormat data_type)
static GPUContext * wrap(Context *ctx)
constexpr bool validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat data_format)
std::string tex_data_format_to_msl_texture_template_type(eGPUDataFormat type)
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)
int to_bytesize(const DataFormat format)
MTLTextureUsage mtl_usage_from_gpu(eGPUTextureUsage usage)
MTLTextureType to_metal_type(eGPUTextureType type)
int to_component_len(eGPUTextureFormat format)
constexpr DataFormat to_data_format(TextureFormat format)
eGPUTextureUsage gpu_usage_from_mtl(MTLTextureUsage mtl_usage)
static void init(bNodeTree *, bNode *node)
bool supports_texture_atomics