38void gpu::MTLTexture::mtl_texture_init()
45 resource_mode_ = MTL_TEXTURE_MODE_DEFAULT;
50 mip_swizzle_view_ = nil;
56 vert_buffer_ =
nullptr;
57 vert_buffer_mtl_ = nil;
60 tex_swizzle_mask_[0] =
'r';
61 tex_swizzle_mask_[1] =
'g';
62 tex_swizzle_mask_[2] =
'b';
63 tex_swizzle_mask_[3] =
'a';
64 mtl_swizzle_mask_ = MTLTextureSwizzleChannelsMake(
65 MTLTextureSwizzleRed, MTLTextureSwizzleGreen, MTLTextureSwizzleBlue, MTLTextureSwizzleAlpha);
77 id<MTLTexture> metal_texture)
87 init_2D((
int)metal_texture.width, (
int)metal_texture.height, 0, 1,
format);
90 texture_ = metal_texture;
98 resource_mode_ = MTL_TEXTURE_MODE_EXTERNAL;
106 if (ctx !=
nullptr) {
118void gpu::MTLTexture::bake_mip_swizzle_view()
120 if (texture_view_dirty_flags_) {
126 if (resource_mode_ != MTL_TEXTURE_MODE_TEXTURE_VIEW &&
127 texture_view_dirty_flags_ == TEXTURE_VIEW_MIP_DIRTY && mip_swizzle_view_ == nil)
130 if (mip_texture_base_level_ == 0 && mip_texture_max_level_ == mtl_max_mips_) {
131 texture_view_dirty_flags_ = TEXTURE_VIEW_NOT_DIRTY;
137 if (mip_swizzle_view_ != nil) {
138 [mip_swizzle_view_ release];
139 mip_swizzle_view_ = nil;
144 const gpu::Texture *tex_view_src =
this;
145 if (resource_mode_ == MTL_TEXTURE_MODE_TEXTURE_VIEW) {
146 tex_view_src = source_texture_;
154 max_slices = tex_view_src->height_get();
158 max_slices = tex_view_src->depth_get();
167 max_slices = tex_view_src->depth_get();
178 if (texture_view_stencil_) {
179 switch (texture_view_pixel_format) {
180 case MTLPixelFormatDepth24Unorm_Stencil8:
181 texture_view_pixel_format = MTLPixelFormatX24_Stencil8;
183 case MTLPixelFormatDepth32Float_Stencil8:
184 texture_view_pixel_format = MTLPixelFormatX32_Stencil8;
187 BLI_assert_msg(
false,
"Texture format does not support stencil views.");
194 MTLTextureType texture_view_texture_type =
to_metal_type(type_);
201 (texture_view_pixel_format == texture_.pixelFormat) ||
203 "Usage Flag GPU_TEXTURE_USAGE_FORMAT_VIEW must be specified if a texture view is "
204 "created with a different format to its source texture.");
206 int range_len =
min_ii((mip_texture_max_level_ - mip_texture_base_level_) + 1,
207 (
int)texture_.mipmapLevelCount - mip_texture_base_level_);
209 BLI_assert(mip_texture_base_level_ < texture_.mipmapLevelCount);
210 BLI_assert(mip_texture_base_layer_ < max_slices);
212 mip_swizzle_view_ = [texture_
213 newTextureViewWithPixelFormat:texture_view_pixel_format
214 textureType:texture_view_texture_type
215 levels:NSMakeRange(mip_texture_base_level_, range_len)
216 slices:NSMakeRange(mip_texture_base_layer_, num_slices)
217 swizzle:mtl_swizzle_mask_];
219 "Updating texture view - MIP TEXTURE BASE LEVEL: %d, MAX LEVEL: %d (Range len: %d)",
220 mip_texture_base_level_,
221 min_ii(mip_texture_max_level_, (
int)texture_.mipmapLevelCount),
224 mip_swizzle_view_.label = [NSString
226 @"MipSwizzleView_%s__format=%u_type=%u_baselevel=%u_numlevels=%u_swizzle='%c%c%c%c'",
227 [[texture_ label] UTF8String],
228 (
uint)texture_view_pixel_format,
229 (
uint)texture_view_texture_type,
230 (
uint)mip_texture_base_level_,
232 tex_swizzle_mask_[0],
233 tex_swizzle_mask_[1],
234 tex_swizzle_mask_[2],
235 tex_swizzle_mask_[3]];
237 mip_swizzle_view_.label = [texture_ label];
239 texture_view_dirty_flags_ = TEXTURE_VIEW_NOT_DIRTY;
246id<MTLTexture> gpu::MTLTexture::get_metal_handle()
250 if (resource_mode_ == MTL_TEXTURE_MODE_VBO) {
251 id<MTLBuffer> buf = vert_buffer_->get_metal_buffer();
254 if (buf != vert_buffer_mtl_) {
256 "MTLTexture '%p' using MTL_TEXTURE_MODE_VBO requires re-generation due to updated "
263 this->init_internal(vert_buffer_);
266 buf = vert_buffer_->get_metal_buffer();
272 BLI_assert(vert_buffer_->get_metal_buffer() == vert_buffer_mtl_);
276 this->ensure_baked();
280 if (resource_mode_ == MTL_TEXTURE_MODE_TEXTURE_VIEW) {
281 BLI_assert_msg(mip_swizzle_view_,
"Texture view should always have a valid handle.");
284 if (mip_swizzle_view_ != nil || texture_view_dirty_flags_) {
285 bake_mip_swizzle_view();
290 if (mip_swizzle_view_ != nil) {
291 return mip_swizzle_view_;
299id<MTLTexture> gpu::MTLTexture::get_metal_handle_base()
303 this->ensure_baked();
306 if (resource_mode_ == MTL_TEXTURE_MODE_TEXTURE_VIEW) {
307 BLI_assert_msg(mip_swizzle_view_,
"Texture view should always have a valid handle.");
308 if (mip_swizzle_view_ != nil || texture_view_dirty_flags_) {
309 bake_mip_swizzle_view();
312 return mip_swizzle_view_;
322void gpu::MTLTexture::blit(id<MTLBlitCommandEncoder> blit_encoder,
328 gpu::MTLTexture *dst,
340 BLI_assert(width > 0 && height > 0 && depth > 0);
341 MTLSize src_size = MTLSizeMake(width, height, depth);
342 MTLOrigin src_origin = MTLOriginMake(src_x_offset, src_y_offset, src_z_offset);
343 MTLOrigin dst_origin = MTLOriginMake(dst_x_offset, dst_y_offset, dst_z_offset);
345 if (this->format_get() != dst->format_get()) {
347 "gpu::MTLTexture: Cannot copy between two textures of different types using a "
348 "blit encoder. TODO: Support this operation");
354 [blit_encoder copyFromTexture:this->get_metal_handle_base()
355 sourceSlice:src_slice
357 sourceOrigin:src_origin
359 toTexture:dst->get_metal_handle_base()
360 destinationSlice:dst_slice
361 destinationLevel:dst_mip
362 destinationOrigin:dst_origin];
376 BLI_assert(this->type_get() == dst->type_get());
378 gpu::Shader *
shader = fullscreen_blit_sh_get();
384 gpu::FrameBuffer *blit_target_fb = dst->get_blit_framebuffer(dst_slice, dst_mip);
392 float w = dst->width_get();
393 float h = dst->height_get();
432 if (restore_fb !=
nullptr) {
440gpu::FrameBuffer *gpu::MTLTexture::get_blit_framebuffer(
int dst_slice,
uint dst_mip)
444 bool update_attachments =
false;
447 update_attachments =
true;
452 if (blit_fb_slice_ != dst_slice || blit_fb_mip_ != dst_mip) {
453 update_attachments =
true;
457 if (update_attachments) {
472 blit_fb_slice_ = dst_slice;
473 blit_fb_mip_ = dst_mip;
483 sampler_state.
state = this->sampler_state;
485 return sampler_state;
496 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_TEXTURE_VIEW);
499 this->ensure_mipmaps(mip);
502 this->ensure_baked();
509 std::unique_ptr<uint16_t, MEM_freeN_smart_ptr_deleter> clamped_half_buffer =
nullptr;
512 size_t pixel_count =
max_ii(extent[0], 1) *
max_ii(extent[1], 1) *
max_ii(extent[2], 1);
515 clamped_half_buffer.reset(
518 Span<float> src(
static_cast<const float *
>(
data), total_component_count);
520 total_component_count);
522 constexpr int64_t chunk_size = 4 * 1024 * 1024;
533 data = clamped_half_buffer.get();
540 if (is_depth_format) {
544 update_sub_depth_2d(mip, offset, extent, type,
data);
548 "gpu::MTLTexture::update_sub not yet supported for other depth "
560 size_t totalsize = 0;
576 totalsize = input_bytes_per_pixel *
max_ulul(expected_update_w, 1);
579 totalsize = input_bytes_per_pixel *
max_ulul(expected_update_w, 1) * (size_t)extent[1];
582 totalsize = input_bytes_per_pixel *
max_ulul(expected_update_w, 1) * (size_t)extent[1] *
593 if (totalsize <= 0 || extent[0] <= 0) {
595 "MTLTexture::update_sub called with extent size of zero for one or more dimensions. "
596 "(%d, %d, %d) - DimCount: %u",
624 destination_num_channels,
631 bool can_use_direct_blit =
true;
632 if (!is_compressed && (expected_dst_bytes_per_pixel != input_bytes_per_pixel ||
633 num_channels != destination_num_channels))
635 can_use_direct_blit =
false;
638 if (is_depth_format) {
642 if (extent[0] == 1 && extent[1] == 1 && extent[2] == 1 && totalsize == 4) {
643 can_use_direct_blit =
false;
648 if (
format_ == TextureFormat::SRGBA_8_8_8_8 && !can_use_direct_blit) {
650 "SRGB data upload does not work correctly using compute upload. "
660 "Special input data type must be a 1-1 mapping with destination texture as it "
661 "cannot easily be split");
665 if (!can_use_direct_blit) {
669 "Updating texture layers other than mip=0 when data is mismatched is not "
670 "possible in METAL on macOS using texture->write\n");
677 "Updating texture -- destination MTLPixelFormat '%d' does not support write "
678 "operations, and no suitable TextureView format exists.\n",
679 *(
int *)(&destination_format));
689 if (compatible_write_format == MTLPixelFormatInvalid) {
690 MTL_LOG_ERROR(
"Cannot use compute update blit with texture-view format: %d\n",
691 *((
int *)&compatible_write_format));
697 totalsize,
true,
data);
702 id<MTLBlitCommandEncoder> blit_encoder = nil;
703 id<MTLComputeCommandEncoder> compute_encoder = nil;
704 id<MTLTexture> staging_texture = nil;
705 id<MTLTexture> texture_handle = nil;
708 bool use_staging_texture =
false;
710 if (can_use_direct_blit) {
717 if ((compatible_write_format != destination_format) &&
720 use_staging_texture =
true;
731 use_staging_texture =
true;
733 if (compatible_write_format != destination_format) {
735 use_staging_texture =
true;
741 if (use_staging_texture) {
744 MTLTextureUsage original_usage = texture_descriptor_.usage;
745 texture_descriptor_.usage = original_usage | MTLTextureUsageShaderWrite |
746 MTLTextureUsagePixelFormatView;
747 staging_texture = [ctx->
device newTextureWithDescriptor:texture_descriptor_];
748 staging_texture.label =
@"Staging texture";
749 texture_descriptor_.usage = original_usage;
752 texture_handle = ((compatible_write_format == destination_format)) ?
753 [staging_texture retain] :
754 [staging_texture newTextureViewWithPixelFormat:compatible_write_format];
758 if (compatible_write_format != destination_format) {
760 texture_handle = [texture_ newTextureViewWithPixelFormat:compatible_write_format];
763 texture_handle = texture_;
764 [texture_handle retain];
773 if (can_use_direct_blit) {
775 size_t bytes_per_row = expected_dst_bytes_per_pixel *
779 size_t bytes_per_image = bytes_per_row;
783 bytes_per_row = blocks_x * block_size;
784 bytes_per_image = bytes_per_row;
787 for (
int array_index = 0; array_index < max_array_index; array_index++) {
789 size_t buffer_array_offset = (bytes_per_image * (size_t)array_index);
791 copyFromBuffer:staging_buffer
792 sourceOffset:buffer_array_offset
793 sourceBytesPerRow:bytes_per_row
794 sourceBytesPerImage:bytes_per_image
795 sourceSize:MTLSizeMake(extent[0], 1, 1)
796 toTexture:texture_handle
800 destinationOrigin:MTLOriginMake(offset[0], 0, 0)];
806 id<MTLComputePipelineState> pso = texture_update_1d_get_kernel(
807 compute_specialization_kernel);
808 TextureUpdateParams
params = {mip,
822 dispatchThreads:MTLSizeMake(extent[0], 1, 1)
823 threadsPerThreadgroup:MTLSizeMake(64, 1, 1)];
826 id<MTLComputePipelineState> pso = texture_update_1d_array_get_kernel(
827 compute_specialization_kernel);
828 TextureUpdateParams
params = {mip,
829 {extent[0], extent[1], 1},
830 {offset[0], offset[1], 0},
842 dispatchThreads:MTLSizeMake(extent[0], extent[1], 1)
843 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
851 if (can_use_direct_blit) {
853 size_t bytes_per_row = expected_dst_bytes_per_pixel *
857 size_t bytes_per_image = bytes_per_row * extent[1];
862 bytes_per_row = blocks_x * block_size;
863 bytes_per_image = bytes_per_row * blocks_y;
866 size_t texture_array_relative_offset = 0;
870 for (
int array_slice = base_slice; array_slice < final_slice; array_slice++) {
872 if (array_slice > 0) {
877 [blit_encoder copyFromBuffer:staging_buffer
878 sourceOffset:texture_array_relative_offset
879 sourceBytesPerRow:bytes_per_row
880 sourceBytesPerImage:bytes_per_image
881 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
882 toTexture:texture_handle
883 destinationSlice:array_slice
885 destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)];
887 texture_array_relative_offset += bytes_per_image;
893 id<MTLComputePipelineState> pso = texture_update_2d_get_kernel(
894 compute_specialization_kernel);
895 TextureUpdateParams
params = {mip,
896 {extent[0], extent[1], 1},
897 {offset[0], offset[1], 0},
909 dispatchThreads:MTLSizeMake(
910 extent[0], extent[1], 1)
911 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
914 id<MTLComputePipelineState> pso = texture_update_2d_array_get_kernel(
915 compute_specialization_kernel);
916 TextureUpdateParams
params = {mip,
917 {extent[0], extent[1], extent[2]},
918 {offset[0], offset[1], offset[2]},
929 [compute_encoder dispatchThreads:MTLSizeMake(extent[0],
932 threadsPerThreadgroup:MTLSizeMake(4, 4, 4)];
940 if (can_use_direct_blit) {
941 size_t bytes_per_row = expected_dst_bytes_per_pixel *
945 size_t bytes_per_image = bytes_per_row * extent[1];
946 [blit_encoder copyFromBuffer:staging_buffer
948 sourceBytesPerRow:bytes_per_row
949 sourceBytesPerImage:bytes_per_image
950 sourceSize:MTLSizeMake(extent[0], extent[1], extent[2])
951 toTexture:texture_handle
954 destinationOrigin:MTLOriginMake(offset[0], offset[1], offset[2])];
957 id<MTLComputePipelineState> pso = texture_update_3d_get_kernel(
958 compute_specialization_kernel);
959 TextureUpdateParams
params = {mip,
960 {extent[0], extent[1], extent[2]},
961 {offset[0], offset[1], offset[2]},
973 dispatchThreads:MTLSizeMake(
974 extent[0], extent[1], extent[2])
975 threadsPerThreadgroup:MTLSizeMake(4, 4, 4)];
981 if (can_use_direct_blit) {
982 size_t bytes_per_row = expected_dst_bytes_per_pixel *
986 size_t bytes_per_image = bytes_per_row * extent[1];
987 size_t texture_array_relative_offset = 0;
990 for (
int i = 0;
i < extent[2];
i++) {
991 int face_index = offset[2] +
i;
993 [blit_encoder copyFromBuffer:staging_buffer
994 sourceOffset:texture_array_relative_offset
995 sourceBytesPerRow:bytes_per_row
996 sourceBytesPerImage:bytes_per_image
997 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
998 toTexture:texture_handle
999 destinationSlice:face_index
1000 destinationLevel:mip
1001 destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)];
1002 texture_array_relative_offset += bytes_per_image;
1007 "TODO(Metal): Support compute texture update for GPU_TEXTURE_CUBE %d, %d, %d\n",
1015 if (can_use_direct_blit) {
1017 size_t bytes_per_row = expected_dst_bytes_per_pixel *
1021 size_t bytes_per_image = bytes_per_row * extent[1];
1024 size_t texture_array_relative_offset = 0;
1025 for (
int i = 0;
i < extent[2];
i++) {
1026 int face_index = offset[2] +
i;
1027 [blit_encoder copyFromBuffer:staging_buffer
1028 sourceOffset:texture_array_relative_offset
1029 sourceBytesPerRow:bytes_per_row
1030 sourceBytesPerImage:bytes_per_image
1031 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
1032 toTexture:texture_handle
1033 destinationSlice:face_index
1034 destinationLevel:mip
1035 destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)];
1036 texture_array_relative_offset += bytes_per_image;
1041 "TODO(Metal): Support compute texture update for GPU_TEXTURE_CUBE_ARRAY %d, %d, "
1061 if (use_staging_texture) {
1073 for (
int array_index = base_slice; array_index < final_slice; array_index++) {
1074 [blit_encoder copyFromTexture:staging_texture
1075 sourceSlice:array_index
1077 sourceOrigin:MTLOriginMake(offset[0], 0, 0)
1078 sourceSize:MTLSizeMake(extent[0], 1, 1)
1080 destinationSlice:array_index
1081 destinationLevel:mip
1082 destinationOrigin:MTLOriginMake(offset[0], 0, 0)];
1089 for (
int array_index = base_slice; array_index < final_slice; array_index++) {
1090 [blit_encoder copyFromTexture:staging_texture
1091 sourceSlice:array_index
1093 sourceOrigin:MTLOriginMake(offset[0], offset[1], 0)
1094 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
1096 destinationSlice:array_index
1097 destinationLevel:mip
1098 destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)];
1102 [blit_encoder copyFromTexture:staging_texture
1105 sourceOrigin:MTLOriginMake(offset[0], offset[1], offset[2])
1106 sourceSize:MTLSizeMake(extent[0], extent[1], extent[2])
1109 destinationLevel:mip
1110 destinationOrigin:MTLOriginMake(offset[0], offset[1], offset[2])];
1115 for (
int i = 0;
i < extent[2];
i++) {
1116 int face_index = offset[2] +
i;
1117 [blit_encoder copyFromTexture:staging_texture
1118 sourceSlice:face_index
1120 sourceOrigin:MTLOriginMake(offset[0], offset[1], 0)
1121 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
1123 destinationSlice:face_index
1124 destinationLevel:mip
1125 destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)];
1134 [staging_texture release];
1138 if (can_use_direct_blit) {
1141 if (texture_.storageMode == MTLStorageModeManaged) {
1142 [blit_encoder synchronizeResource:texture_];
1144 [blit_encoder optimizeContentsForGPUAccess:texture_];
1150 if (texture_.storageMode == MTLStorageModeManaged) {
1152 [blit_encoder synchronizeResource:texture_];
1154 [blit_encoder optimizeContentsForGPUAccess:texture_];
1158 [texture_handle release];
1165 temp_allocation->
free();
1172 GPUPixelBuffer *pixbuf)
1182 if (buffer == nil) {
1187 this->ensure_baked();
1194 size_t bytes_per_row = bits_per_pixel * extent[0];
1195 size_t bytes_per_image = bytes_per_row * extent[1];
1205 [blit_encoder copyFromBuffer:buffer
1207 sourceBytesPerRow:bytes_per_row
1208 sourceBytesPerImage:bytes_per_image
1209 sourceSize:MTLSizeMake(extent[0], extent[1], 1)
1213 destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)];
1215 if (texture_.storageMode == MTLStorageModeManaged) {
1216 [blit_encoder synchronizeResource:texture_];
1218 [blit_encoder optimizeContentsForGPUAccess:texture_];
1225void gpu::MTLTexture::ensure_mipmaps(
int miplvl)
1229 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_TEXTURE_VIEW);
1234 int max_dimension =
max_iii(w_, effective_h, effective_d);
1235 int max_miplvl =
floor(
log2(max_dimension));
1236 miplvl =
min_ii(max_miplvl, miplvl);
1239 if (mipmaps_ < miplvl) {
1243 if (is_baked_ && mipmaps_ > mtl_max_mips_) {
1245 "Texture requires a higher mipmap level count. Please specify the required "
1248 MTL_LOG_WARNING(
"Texture requires regenerating due to increase in mip-count");
1251 this->mip_range_set(0, mipmaps_);
1267 MTL_LOG_ERROR(
"Cannot Generate mip-maps -- metal device invalid\n");
1273 this->ensure_mipmaps(mtl_max_mips_);
1276 this->ensure_baked();
1277 BLI_assert_msg(is_baked_ && texture_,
"MTLTexture is not valid");
1279 if (
mipmaps_ == 1 || mtl_max_mips_ == 1) {
1285 if (
format_ == TextureFormat::SFLOAT_32_DEPTH ||
format_ == TextureFormat::UNORM_16_DEPTH ||
1286 format_ == TextureFormat::SFLOAT_32_DEPTH_UINT_8)
1288 MTL_LOG_WARNING(
"Cannot generate mipmaps for textures using DEPTH formats");
1296 [enc insertDebugSignpost:
@"Generate MipMaps"];
1298 [enc generateMipmapsForTexture:texture_];
1299 has_generated_mips_ =
true;
1309 (mt_dst->
d_ == mt_src->
d_));
1320 this->ensure_baked();
1332 int extent[3] = {1, 1, 1};
1335 switch (mt_dst->
type_) {
1341 [blit_encoder copyFromTexture:this->get_metal_handle_base()
1342 toTexture:mt_dst->get_metal_handle_base()];
1343 [blit_encoder optimizeContentsForGPUAccess:mt_dst->get_metal_handle_base()];
1347 this->blit(blit_encoder,
1370 this->ensure_baked();
1373 bool do_render_pass_clear =
true;
1375 do_render_pass_clear =
false;
1379 if (backing_buffer_ !=
nullptr) {
1382 bool fast_buf_clear =
true;
1384 for (
int i = 1;
i < channel_size * channel_len;
i++) {
1385 fast_buf_clear = fast_buf_clear && (val[
i] == val[0]);
1387 if (fast_buf_clear) {
1393 id<MTLBlitCommandEncoder> blit_encoder =
1395 [blit_encoder fillBuffer:backing_buffer_->get_metal_buffer()
1396 range:NSMakeRange(0, backing_buffer_->get_size())
1401 "Non-repeating-byte-pattern clear for buffer-backed textures not supported!");
1406 if (do_render_pass_clear) {
1434 id<MTLTexture> texture_handle = texture_;
1437 id<MTLComputeCommandEncoder> compute_encoder =
1443 id<MTLComputePipelineState> pso = texture_update_1d_get_kernel(
1444 compute_specialization_kernel);
1445 TextureUpdateParams
params = {0,
1458 [compute_encoder dispatchThreads:MTLSizeMake(
w_, 1, 1)
1459 threadsPerThreadgroup:MTLSizeMake(64, 1, 1)];
1462 id<MTLComputePipelineState> pso = texture_update_1d_array_get_kernel(
1463 compute_specialization_kernel);
1464 TextureUpdateParams
params = {0,
1477 [compute_encoder dispatchThreads:MTLSizeMake(
w_,
h_, 1)
1478 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
1482 "gpu::MTLTexture::clear requires compute pass for texture"
1483 "type: %d, but this is not yet supported",
1491 if (texture_.storageMode == MTLStorageModeManaged) {
1492 [blit_encoder synchronizeResource:texture_];
1494 [blit_encoder optimizeContentsForGPUAccess:texture_];
1503 return MTLTextureSwizzleRed;
1506 return MTLTextureSwizzleGreen;
1509 return MTLTextureSwizzleBlue;
1512 return MTLTextureSwizzleAlpha;
1514 return MTLTextureSwizzleZero;
1516 return MTLTextureSwizzleOne;
1522 if (memcmp(tex_swizzle_mask_, swizzle_mask, 4) != 0) {
1523 memcpy(tex_swizzle_mask_, swizzle_mask, 4);
1526 MTLTextureSwizzleChannels new_swizzle_mask = MTLTextureSwizzleChannelsMake(
1532 mtl_swizzle_mask_ = new_swizzle_mask;
1533 texture_view_dirty_flags_ |= TEXTURE_VIEW_SWIZZLE_DIRTY;
1556 " MTLTexture of type TEXTURE_1D_ARRAY or TEXTURE_BUFFER cannot have a mipcount "
1557 "greater than 1\n");
1565 mip_texture_base_level_ =
mip_min_;
1567 texture_view_dirty_flags_ |= TEXTURE_VIEW_MIP_DIRTY;
1578 int extent[3] = {1, 1, 1};
1581 size_t sample_len = extent[0] *
max_ii(extent[1], 1) *
max_ii(extent[2], 1);
1583 size_t texture_size = sample_len * sample_size;
1590 this->read_internal(
1591 mip, 0, 0, 0, extent[0], extent[1], extent[2], type, num_channels, texture_size + 8,
data);
1595 MTL_LOG_WARNING(
"MTLTexture::read - reading from texture with no image data");
1602void gpu::MTLTexture::read_internal(
int mip,
1610 int num_output_components,
1611 size_t debug_data_size,
1616 MTL_LOG_WARNING(
"gpu::MTLTexture::read_internal - Trying to read from a non-baked texture!");
1625 BLI_assert(num_output_components <= num_channels);
1626 size_t desired_output_bpp = num_output_components *
to_bytesize(desired_output_format);
1635 bool format_conversion_needed = (data_format != desired_output_format);
1636 bool can_use_simple_read = (desired_output_bpp == image_bpp) && (!format_conversion_needed) &&
1637 (num_output_components == image_components);
1641 if (is_depth_format) {
1642 can_use_simple_read =
false;
1644 image_components = 1;
1657 BLI_assert(format_ == TextureFormat::UFLOAT_11_11_10 ||
1658 format_ == TextureFormat::UNORM_10_10_10_2 ||
1659 format_ == TextureFormat::UINT_10_10_10_2);
1662 image_bpp =
sizeof(int);
1663 image_components = 1;
1664 desired_output_bpp =
sizeof(int);
1665 num_output_components = 1;
1668 format_conversion_needed =
false;
1669 can_use_simple_read =
true;
1673 size_t bytes_per_row = desired_output_bpp * width;
1674 size_t bytes_per_image = bytes_per_row * height;
1675 size_t total_bytes = bytes_per_image *
max_ii(depth, 1);
1677 if (can_use_simple_read) {
1681 ((num_output_components *
to_bytesize(desired_output_format)) == desired_output_bpp) &&
1682 (desired_output_bpp == image_bpp));
1690 total_bytes, 256,
true);
1693 id<MTLBuffer> destination_buffer = dest_buf->get_metal_buffer();
1695 void *destination_buffer_host_ptr = dest_buf->get_host_ptr();
1696 BLI_assert(destination_buffer_host_ptr !=
nullptr);
1699 int depth_format_mode = 0;
1700 if (is_depth_format) {
1701 depth_format_mode = 1;
1702 switch (desired_output_format) {
1704 depth_format_mode = 1;
1707 depth_format_mode = 2;
1710 depth_format_mode = 4;
1718 TextureReadRoutineSpecialisation compute_specialization_kernel = {
1722 num_output_components,
1725 bool copy_successful =
false;
1733 id<MTLTexture> read_texture = texture_;
1735 if (resource_mode_ == MTL_TEXTURE_MODE_TEXTURE_VIEW) {
1736 read_texture = this->get_metal_handle();
1739 if (format_ == TextureFormat::SRGBA_8_8_8_8) {
1741 read_texture = [read_texture newTextureViewWithPixelFormat:MTLPixelFormatRGBA8Unorm];
1747 if (can_use_simple_read) {
1749 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1751 [enc insertDebugSignpost:
@"GPUTextureRead1D"];
1753 [enc copyFromTexture:read_texture
1756 sourceOrigin:MTLOriginMake(x_off, 0, 0)
1757 sourceSize:MTLSizeMake(width, 1, 1)
1758 toBuffer:destination_buffer
1760 destinationBytesPerRow:bytes_per_row
1761 destinationBytesPerImage:bytes_per_image];
1762 copy_successful =
true;
1767 id<MTLComputeCommandEncoder> compute_encoder =
1768 ctx->main_command_buffer.ensure_begin_compute_encoder();
1769 id<MTLComputePipelineState> pso = texture_read_1d_get_kernel(
1770 compute_specialization_kernel);
1771 TextureReadParams
params = {
1781 cs.bind_compute_buffer(destination_buffer, 0, 1);
1782 cs.bind_compute_texture(read_texture, 0);
1783 [compute_encoder dispatchThreads:MTLSizeMake(width, 1, 1)
1784 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
1785 copy_successful =
true;
1790 if (can_use_simple_read) {
1792 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1794 [enc insertDebugSignpost:
@"GPUTextureRead1DArray"];
1797 int base_slice = y_off;
1798 int final_slice = base_slice + height;
1799 size_t texture_array_relative_offset = 0;
1801 for (
int array_slice = base_slice; array_slice < final_slice; array_slice++) {
1802 [enc copyFromTexture:read_texture
1803 sourceSlice:base_slice
1805 sourceOrigin:MTLOriginMake(x_off, 0, 0)
1806 sourceSize:MTLSizeMake(width, 1, 1)
1807 toBuffer:destination_buffer
1808 destinationOffset:texture_array_relative_offset
1809 destinationBytesPerRow:bytes_per_row
1810 destinationBytesPerImage:bytes_per_row];
1811 texture_array_relative_offset += bytes_per_row;
1813 copy_successful =
true;
1817 id<MTLComputeCommandEncoder> compute_encoder =
1818 ctx->main_command_buffer.ensure_begin_compute_encoder();
1819 id<MTLComputePipelineState> pso = texture_read_1d_array_get_kernel(
1820 compute_specialization_kernel);
1821 TextureReadParams
params = {
1831 cs.bind_compute_buffer(destination_buffer, 0, 1);
1832 cs.bind_compute_texture(read_texture, 0);
1833 [compute_encoder dispatchThreads:MTLSizeMake(width, height, 1)
1834 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
1835 copy_successful =
true;
1840 if (can_use_simple_read) {
1842 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1844 [enc insertDebugSignpost:
@"GPUTextureRead2D"];
1846 [enc copyFromTexture:read_texture
1849 sourceOrigin:MTLOriginMake(x_off, y_off, 0)
1850 sourceSize:MTLSizeMake(width, height, 1)
1851 toBuffer:destination_buffer
1853 destinationBytesPerRow:bytes_per_row
1854 destinationBytesPerImage:bytes_per_image];
1855 copy_successful =
true;
1860 id<MTLComputeCommandEncoder> compute_encoder =
1861 ctx->main_command_buffer.ensure_begin_compute_encoder();
1862 id<MTLComputePipelineState> pso = texture_read_2d_get_kernel(
1863 compute_specialization_kernel);
1864 TextureReadParams
params = {
1874 cs.bind_compute_buffer(destination_buffer, 0, 1);
1875 cs.bind_compute_texture(read_texture, 0);
1876 [compute_encoder dispatchThreads:MTLSizeMake(width, height, 1)
1877 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
1878 copy_successful =
true;
1883 if (can_use_simple_read) {
1885 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1887 [enc insertDebugSignpost:
@"GPUTextureRead2DArray"];
1889 int base_slice = z_off;
1890 int final_slice = base_slice + depth;
1891 size_t texture_array_relative_offset = 0;
1893 for (
int array_slice = base_slice; array_slice < final_slice; array_slice++) {
1894 [enc copyFromTexture:read_texture
1895 sourceSlice:array_slice
1897 sourceOrigin:MTLOriginMake(x_off, y_off, 0)
1898 sourceSize:MTLSizeMake(width, height, 1)
1899 toBuffer:destination_buffer
1900 destinationOffset:texture_array_relative_offset
1901 destinationBytesPerRow:bytes_per_row
1902 destinationBytesPerImage:bytes_per_image];
1903 texture_array_relative_offset += bytes_per_image;
1905 copy_successful =
true;
1910 id<MTLComputeCommandEncoder> compute_encoder =
1911 ctx->main_command_buffer.ensure_begin_compute_encoder();
1912 id<MTLComputePipelineState> pso = texture_read_2d_array_get_kernel(
1913 compute_specialization_kernel);
1914 TextureReadParams
params = {
1916 {width, height, depth},
1917 {x_off, y_off, z_off},
1924 cs.bind_compute_buffer(destination_buffer, 0, 1);
1925 cs.bind_compute_texture(read_texture, 0);
1927 dispatchThreads:MTLSizeMake(width, height, depth)
1928 threadsPerThreadgroup:MTLSizeMake(8, 8, 1)];
1929 copy_successful =
true;
1934 if (can_use_simple_read) {
1936 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1938 [enc insertDebugSignpost:
@"GPUTextureRead3D"];
1940 [enc copyFromTexture:read_texture
1943 sourceOrigin:MTLOriginMake(x_off, y_off, z_off)
1944 sourceSize:MTLSizeMake(width, height, depth)
1945 toBuffer:destination_buffer
1947 destinationBytesPerRow:bytes_per_row
1948 destinationBytesPerImage:bytes_per_image];
1949 copy_successful =
true;
1954 id<MTLComputeCommandEncoder> compute_encoder =
1955 ctx->main_command_buffer.ensure_begin_compute_encoder();
1956 id<MTLComputePipelineState> pso = texture_read_3d_get_kernel(
1957 compute_specialization_kernel);
1958 TextureReadParams
params = {
1960 {width, height, depth},
1961 {x_off, y_off, z_off},
1968 cs.bind_compute_buffer(destination_buffer, 0, 1);
1969 cs.bind_compute_texture(read_texture, 0);
1971 dispatchThreads:MTLSizeMake(width, height, depth)
1972 threadsPerThreadgroup:MTLSizeMake(4, 4, 4)];
1973 copy_successful =
true;
1980 "z_off > 0 is only supported by TEXTURE CUBE ARRAY reads.");
1982 "depth > 6 is only supported by TEXTURE CUBE ARRAY reads. ");
1983 if (can_use_simple_read) {
1984 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
1986 [enc insertDebugSignpost:
@"GPUTextureReadCubeArray"];
1990 int base_slice = z_off;
1991 int final_slice = base_slice + depth;
1992 size_t texture_array_relative_offset = 0;
1994 for (
int array_slice = base_slice; array_slice < final_slice; array_slice++) {
1995 [enc copyFromTexture:read_texture
1996 sourceSlice:array_slice
1998 sourceOrigin:MTLOriginMake(x_off, y_off, 0)
1999 sourceSize:MTLSizeMake(width, height, 1)
2000 toBuffer:destination_buffer
2001 destinationOffset:texture_array_relative_offset
2002 destinationBytesPerRow:bytes_per_row
2003 destinationBytesPerImage:bytes_per_image];
2005 texture_array_relative_offset += bytes_per_image;
2007 MTL_LOG_DEBUG(
"Copying texture data to buffer GPU_TEXTURE_CUBE_ARRAY");
2008 copy_successful =
true;
2011 MTL_LOG_ERROR(
"TODO(Metal): unsupported compute copy of texture cube array");
2017 "gpu::MTLTexture::read_internal simple-copy not yet supported for texture "
2023 if (copy_successful) {
2026 if (dest_buf->get_resource_options() == MTLResourceStorageModeManaged) {
2027 id<MTLBlitCommandEncoder> enc = ctx->main_command_buffer.ensure_begin_blit_encoder();
2029 [enc insertDebugSignpost:
@"GPUTextureRead-syncResource"];
2031 [enc synchronizeResource:destination_buffer];
2038 memcpy(r_data, destination_buffer_host_ptr, total_bytes);
2039 MTL_LOG_DEBUG(
"gpu::MTLTexture::read_internal success! %lu bytes read", total_bytes);
2043 "gpu::MTLTexture::read_internal not yet supported for this config -- data "
2044 "format different (src %lu bytes, dst %lu bytes) (src format: %d, dst format: %d), or "
2045 "varying component counts (src %d, dst %d)",
2049 (
int)desired_output_format,
2051 num_output_components);
2061 this->prepare_internal();
2084 id<MTLBuffer> source_buffer = mtl_vbo->get_metal_buffer();
2096 size_t bytes_per_row = bytes_per_pixel *
w_;
2099 uint32_t align_requirement = uint32_t(
2100 [mtl_ctx->
device minimumLinearTextureAlignmentForPixelFormat:mtl_format]);
2104 if (
format->stride > bytes_per_pixel &&
format->attr_len > 1) {
2110 if (bytes_per_pixel *
format->attr_len !=
format->stride) {
2112 "Cannot split attributes across multiple pixels as attribute format sizes do "
2119 bytes_per_row *=
format->attr_len;
2126 "Image should contain one pixel for each attribute in every vertex.");
2131 "Pixel format stride MUST match the texture format stride -- These being different "
2132 "is likely caused by Metal's VBO padding to a minimum of 4-bytes per-vertex."
2133 " If multiple attributes are used. Each attribute is to be packed into its own "
2134 "individual pixel when stride length is exceeded. ");
2139 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
2140 texture_descriptor_.pixelFormat = mtl_format;
2141 texture_descriptor_.textureType = MTLTextureTypeTextureBuffer;
2142 texture_descriptor_.width =
w_;
2143 texture_descriptor_.height = 1;
2144 texture_descriptor_.depth = 1;
2145 texture_descriptor_.arrayLength = 1;
2146 texture_descriptor_.mipmapLevelCount = mtl_max_mips_;
2147 texture_descriptor_.usage =
2148 MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite |
2149 MTLTextureUsagePixelFormatView;
2150 texture_descriptor_.storageMode = [source_buffer storageMode];
2151 texture_descriptor_.sampleCount = 1;
2152 texture_descriptor_.cpuCacheMode = [source_buffer cpuCacheMode];
2153 texture_descriptor_.hazardTrackingMode = [source_buffer hazardTrackingMode];
2155 texture_ = [source_buffer
2156 newTextureWithDescriptor:texture_descriptor_
2159 aligned_w_ = bytes_per_row / bytes_per_pixel;
2162 texture_.label = [NSString stringWithUTF8String:this->
get_name()];
2165 resource_mode_ = MTL_TEXTURE_MODE_VBO;
2168 vert_buffer_ = mtl_vbo;
2169 vert_buffer_mtl_ = source_buffer;
2182 this->prepare_internal();
2185 resource_mode_ = MTL_TEXTURE_MODE_TEXTURE_VIEW;
2186 source_texture_ = src;
2187 mip_texture_base_level_ = mip_offset;
2188 mip_texture_base_layer_ = layer_offset;
2189 texture_view_dirty_flags_ |= TEXTURE_VIEW_MIP_DIRTY;
2196 mtltex->ensure_baked();
2197 texture_ = mtltex->texture_;
2206 texture_view_stencil_ =
false;
2209 texture_view_stencil_ =
true;
2213 bake_mip_swizzle_view();
2229void gpu::MTLTexture::prepare_internal()
2233 internal_gpu_image_usage_flags_ = gpu_image_usage_flags_;
2256 mtl_max_mips_ = mipmaps_;
2260void gpu::MTLTexture::ensure_baked()
2264 id<MTLTexture> previous_texture = nil;
2265 bool copy_previous_contents =
false;
2267 if (is_baked_ && is_dirty_) {
2268 copy_previous_contents =
true;
2269 previous_texture = texture_;
2270 [previous_texture retain];
2279 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_EXTERNAL);
2280 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_TEXTURE_VIEW);
2281 BLI_assert(resource_mode_ != MTL_TEXTURE_MODE_VBO);
2289 if (format_ == TextureFormat::SRGBA_8_8_8_8) {
2300 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
2301 texture_descriptor_.pixelFormat = mtl_format;
2304 texture_descriptor_.width = w_;
2305 texture_descriptor_.height = 1;
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;
2320 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
2321 texture_descriptor_.pixelFormat = mtl_format;
2324 texture_descriptor_.width = w_;
2325 texture_descriptor_.height = h_;
2326 texture_descriptor_.depth = 1;
2328 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
2330 texture_descriptor_.storageMode = MTLStorageModePrivate;
2331 texture_descriptor_.sampleCount = 1;
2332 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
2333 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
2339 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
2340 texture_descriptor_.pixelFormat = mtl_format;
2341 texture_descriptor_.textureType = MTLTextureType3D;
2342 texture_descriptor_.width = w_;
2343 texture_descriptor_.height = h_;
2344 texture_descriptor_.depth = d_;
2345 texture_descriptor_.arrayLength = 1;
2346 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
2348 texture_descriptor_.storageMode = MTLStorageModePrivate;
2349 texture_descriptor_.sampleCount = 1;
2350 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
2351 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
2360 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
2361 texture_descriptor_.pixelFormat = mtl_format;
2363 MTLTextureTypeCubeArray :
2365 texture_descriptor_.width = w_;
2366 texture_descriptor_.height = h_;
2367 texture_descriptor_.depth = 1;
2369 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
2371 texture_descriptor_.storageMode = MTLStorageModePrivate;
2372 texture_descriptor_.sampleCount = 1;
2373 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
2374 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
2379 texture_descriptor_ = [[MTLTextureDescriptor alloc]
init];
2380 texture_descriptor_.pixelFormat = mtl_format;
2381 texture_descriptor_.textureType = MTLTextureTypeTextureBuffer;
2382 texture_descriptor_.width = w_;
2383 texture_descriptor_.height = 1;
2384 texture_descriptor_.depth = 1;
2385 texture_descriptor_.arrayLength = 1;
2386 texture_descriptor_.mipmapLevelCount = (mtl_max_mips_ > 0) ? mtl_max_mips_ : 1;
2388 texture_descriptor_.storageMode = MTLStorageModePrivate;
2389 texture_descriptor_.sampleCount = 1;
2390 texture_descriptor_.cpuCacheMode = MTLCPUCacheModeDefaultCache;
2391 texture_descriptor_.hazardTrackingMode = MTLHazardTrackingModeDefault;
2395 MTL_LOG_ERROR(
"[METAL] Error: Cannot create texture with unknown type: %d\n", type_);
2401 resource_mode_ = MTL_TEXTURE_MODE_DEFAULT;
2407 if (is_tile_based_arch) {
2408 texture_descriptor_.storageMode = MTLStorageModeMemoryless;
2421 "Texture atomic fallback support is only available for GPU_TEXTURE_2D, "
2422 "GPU_TEXTURE_2D_ARRAY and GPU_TEXTURE_3D.");
2431 const uint max_width = 16384;
2432 const uint max_height = 16384;
2433 const uint pixels_res = w_ * h_ * d_;
2435 uint new_w = 0, new_h = 0;
2436 if (pixels_res <= max_width) {
2442 new_h = ((pixels_res % new_w) == 0) ? (pixels_res / new_w) : ((pixels_res / new_w) + 1);
2445 texture_descriptor_.width = new_w;
2446 texture_descriptor_.height = new_h;
2450 texture_descriptor_.height <= max_height,
2451 "Atomic fallback support texture is too large.");
2456 size_t bytes_per_row = bytes_per_pixel * texture_descriptor_.width;
2457 size_t total_bytes = bytes_per_row * texture_descriptor_.height;
2464 texture_descriptor_.textureType = MTLTextureType2D;
2465 texture_descriptor_.depth = 1;
2466 texture_descriptor_.arrayLength = 1;
2470 tex_buffer_metadata_[0] = w_;
2471 tex_buffer_metadata_[1] = h_;
2472 tex_buffer_metadata_[2] = d_;
2477 [ctx->device minimumLinearTextureAlignmentForPixelFormat:mtl_format]);
2479 texture_ = [backing_buffer_->get_metal_buffer()
2480 newTextureWithDescriptor:texture_descriptor_
2482 bytesPerRow:aligned_bytes_per_row];
2484 tex_buffer_metadata_[3] = bytes_per_row / bytes_per_pixel;
2487 texture_.label = [NSString
2488 stringWithFormat:
@"AtomicBufferBackedTexture_%s", this->
get_name()];
2494 texture_ = [ctx->device newTextureWithDescriptor:texture_descriptor_];
2498 texture_.label = [NSString stringWithFormat:
@"MemorylessTexture_%s", this->
get_name()];
2501 texture_.label = [NSString stringWithFormat:
@"Texture_%s", this->
get_name()];
2512 if (copy_previous_contents) {
2514 [previous_texture release];
2518void gpu::MTLTexture::reset()
2522 if (texture_ != nil) {
2530 if (backing_buffer_ !=
nullptr) {
2531 backing_buffer_->free();
2532 backing_buffer_ =
nullptr;
2536 if (storage_buffer_ !=
nullptr) {
2537 delete storage_buffer_;
2538 storage_buffer_ =
nullptr;
2541 if (texture_no_srgb_ != nil) {
2542 [texture_no_srgb_ release];
2543 texture_no_srgb_ = nil;
2546 if (mip_swizzle_view_ != nil) {
2547 [mip_swizzle_view_ release];
2548 mip_swizzle_view_ = nil;
2558 if (texture_descriptor_ !=
nullptr) {
2559 [texture_descriptor_ release];
2560 texture_descriptor_ =
nullptr;
2564 has_generated_mips_ =
false;
2578 backing_buffer_ !=
nullptr,
2579 "Resource must have been created as a buffer backed resource to support SSBO wrapping.");
2581 this->ensure_baked();
2582 if (storage_buffer_ == nil) {
2584 id<MTLBuffer> backing_buffer = [texture_ buffer];
2588 return storage_buffer_;
2597 return (
format_ == TextureFormat::SRGBA_8_8_8_8);
2600id<MTLTexture> MTLTexture::get_non_srgb_handle()
2602 id<MTLTexture> base_tex = get_metal_handle_base();
2604 if (texture_no_srgb_ == nil) {
2605 texture_no_srgb_ = [base_tex newTextureViewWithPixelFormat:MTLPixelFormatRGBA8Unorm];
2607 return texture_no_srgb_;
2638 MTLResourceOptions resource_options = ([ctx->
device hasUnifiedMemory]) ?
2639 MTLResourceStorageModeShared :
2640 MTLResourceStorageModeManaged;
2642 if (buffer_ != nil) {
2643 id<MTLBuffer> new_buffer = [ctx->
device newBufferWithBytes:[buffer_ contents]
2647 buffer_ = new_buffer;
2653 return [buffer_ contents];
2658 if (buffer_ == nil) {
2663 if (buffer_.resourceOptions & MTLResourceStorageModeManaged) {
2664 [buffer_ didModifyRange:NSMakeRange(0,
size_)];
2675 if (![ctx->
device hasUnifiedMemory]) {
2676 return native_handle;
2684 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, blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
blender::gpu::Batch * GPU_batch_preset_quad()
int GPU_max_texture_3d_size()
blender::gpu::FrameBuffer * GPU_framebuffer_create(const char *name)
void GPU_framebuffer_restore()
#define GPU_ATTACHMENT_NONE
void GPU_framebuffer_free(blender::gpu::FrameBuffer *fb)
#define GPU_framebuffer_ensure_config(_fb,...)
#define GPU_ATTACHMENT_TEXTURE_LAYER_MIP(_texture, _layer, _mip)
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
blender::gpu::FrameBuffer * GPU_framebuffer_active_get()
void GPU_shader_uniform_1i(blender::gpu::Shader *sh, const char *name, int value)
void GPU_shader_uniform_2f(blender::gpu::Shader *sh, const char *name, float x, float y)
GPUStencilTest GPU_stencil_test_get()
void GPU_scissor_test(bool enable)
void GPU_depth_mask(bool depth)
void GPU_face_culling(GPUFaceCullTest culling)
void GPU_blend(GPUBlend blend)
void GPU_stencil_write_mask_set(uint write_mask)
void GPU_depth_test(GPUDepthTest test)
void GPU_stencil_test(GPUStencilTest test)
void GPU_stencil_reference_set(uint reference)
GPUDepthTest GPU_depth_test_get()
GPUFaceCullTest GPU_face_culling_get()
uint GPU_stencil_mask_get()
bool GPU_depth_mask_get()
@ GPU_DATA_UINT_24_8_DEPRECATED
@ 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 blender::gpu::Texture *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
constexpr int64_t size() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr T * data() const
constexpr Span slice(int64_t start, int64_t size) const
constexpr const T * data() const
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
virtual void texture_unbind(Texture *tex)=0
eGPUTextureUsage gpu_image_usage_flags_
char name_[DEBUG_NAME_LEN]
bool init_2D(int w, int h, int layers, int mip_len, TextureFormat format)
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)
GPUTextureFormatFlag format_flag_
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)
void * MEM_mallocN_aligned(size_t len, size_t alignment, const char *str)
MINLINE unsigned long long max_ulul(unsigned long long a, unsigned long long b)
#define MTL_LOG_WARNING(info,...)
#define MTL_LOG_DEBUG(info,...)
#define MTL_LOG_ERROR(info,...)
std::string get_name(const VolumeGridData &grid)
size_t get_mtl_format_bytesize(MTLPixelFormat tex_format)
MTLPixelFormat gpu_texture_format_to_metal(TextureFormat tex_format)
static Context * unwrap(GPUContext *ctx)
bool is_half_float(TextureFormat format)
std::string tex_data_format_to_msl_type_str(eGPUDataFormat type)
eGPUDataFormat to_texture_data_format(TextureFormat tex_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)
size_t to_block_size(TextureFormat data_type)
int get_mtl_format_num_components(MTLPixelFormat tex_format)
int to_bytesize(const DataFormat format)
MTLTextureUsage mtl_usage_from_gpu(eGPUTextureUsage usage)
int to_component_len(TextureFormat format)
constexpr bool validate_data_format(TextureFormat tex_format, eGPUDataFormat data_format)
MTLTextureType to_metal_type(GPUTextureType type)
eGPUTextureUsage gpu_usage_from_mtl(MTLTextureUsage mtl_usage)
void float_to_half_make_finite_array(const float *src, uint16_t *dst, size_t length)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
static void init(bNodeTree *, bNode *node)
bool supports_texture_atomics