Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpu/metal/mtl_texture.mm
| Show First 20 Lines • Show All 451 Lines • ▼ Show 20 Lines | |||||
| #endif | #endif | ||||
| /* DEPTH FLAG - Depth formats cannot use direct BLIT - pass off to their own routine which will | /* DEPTH FLAG - Depth formats cannot use direct BLIT - pass off to their own routine which will | ||||
| * do a depth-only render. */ | * do a depth-only render. */ | ||||
| bool is_depth_format = (format_flag_ & GPU_FORMAT_DEPTH); | bool is_depth_format = (format_flag_ & GPU_FORMAT_DEPTH); | ||||
| if (is_depth_format) { | if (is_depth_format) { | ||||
| switch (type_) { | switch (type_) { | ||||
| case GPU_TEXTURE_2D: { | case GPU_TEXTURE_2D: | ||||
| update_sub_depth_2d(mip, offset, extent, type, data); | update_sub_depth_2d(mip, offset, extent, type, data); | ||||
| return; | return; | ||||
| } | |||||
| default: | default: | ||||
| MTL_LOG_ERROR( | MTL_LOG_ERROR( | ||||
| "[Error] gpu::MTLTexture::update_sub not yet supported for other depth " | "[Error] gpu::MTLTexture::update_sub not yet supported for other depth " | ||||
| "configurations\n"); | "configurations\n"); | ||||
| return; | return; | ||||
| return; | |||||
| } | } | ||||
| } | } | ||||
| @autoreleasepool { | @autoreleasepool { | ||||
| /* Determine totalsize of INPUT Data. */ | /* Determine totalsize of INPUT Data. */ | ||||
| int num_channels = to_component_len(format_); | int num_channels = to_component_len(format_); | ||||
| int input_bytes_per_pixel = to_bytesize(format_, type); | int input_bytes_per_pixel = to_bytesize(format_, type); | ||||
| int totalsize = 0; | int totalsize = 0; | ||||
| /* If unpack row length is used, size of input data uses the unpack row length, rather than the | /* If unpack row length is used, size of input data uses the unpack row length, rather than the | ||||
| * image length. */ | * image length. */ | ||||
| int expected_update_w = ((ctx->pipeline_state.unpack_row_length == 0) ? | int expected_update_w = ((ctx->pipeline_state.unpack_row_length == 0) ? | ||||
| extent[0] : | extent[0] : | ||||
| ctx->pipeline_state.unpack_row_length); | ctx->pipeline_state.unpack_row_length); | ||||
| /* Ensure calculated total size isn't larger than remaining image data size */ | /* Ensure calculated total size isn't larger than remaining image data size */ | ||||
| switch (this->dimensions_count()) { | switch (this->dimensions_count()) { | ||||
| case 1: | case 1: | ||||
| totalsize = input_bytes_per_pixel * max_ii(expected_update_w, 1); | totalsize = input_bytes_per_pixel * max_ii(expected_update_w, 1); | ||||
| break; | break; | ||||
| case 2: | case 2: | ||||
| totalsize = input_bytes_per_pixel * max_ii(expected_update_w, 1) * max_ii(extent[1], 1); | totalsize = input_bytes_per_pixel * max_ii(expected_update_w, 1) * extent[1]; | ||||
| break; | break; | ||||
| case 3: | case 3: | ||||
| totalsize = input_bytes_per_pixel * max_ii(expected_update_w, 1) * max_ii(extent[1], 1) * | totalsize = input_bytes_per_pixel * max_ii(expected_update_w, 1) * extent[1] * extent[2]; | ||||
| max_ii(extent[2], 1); | |||||
| break; | break; | ||||
| default: | default: | ||||
| BLI_assert(false); | BLI_assert(false); | ||||
| break; | break; | ||||
| } | } | ||||
| /* Early exit if update size is zero. update_sub sometimes has a zero-sized | |||||
| * extent when called from texture painting. */ | |||||
| if (totalsize <= 0 || extent[0] <= 0) { | |||||
| MTL_LOG_WARNING( | |||||
| "MTLTexture::update_sub called with extent size of zero for one or more dimensions. " | |||||
| "(%d, %d, %d) - DimCount: %u\n", | |||||
| extent[0], | |||||
| extent[1], | |||||
| extent[2], | |||||
| this->dimensions_count()); | |||||
| return; | |||||
| } | |||||
| /* When unpack row length is used, provided data does not necessarily contain padding for last | /* When unpack row length is used, provided data does not necessarily contain padding for last | ||||
| * row, so we only include up to the end of updated data. */ | * row, so we only include up to the end of updated data. */ | ||||
| if (ctx->pipeline_state.unpack_row_length > 0) { | if (ctx->pipeline_state.unpack_row_length > 0) { | ||||
| BLI_assert(ctx->pipeline_state.unpack_row_length >= extent[0]); | BLI_assert(ctx->pipeline_state.unpack_row_length >= extent[0]); | ||||
| totalsize -= (ctx->pipeline_state.unpack_row_length - extent[0]) * input_bytes_per_pixel; | totalsize -= (ctx->pipeline_state.unpack_row_length - extent[0]) * input_bytes_per_pixel; | ||||
| } | } | ||||
| /* Check */ | /* Check */ | ||||
| ▲ Show 20 Lines • Show All 427 Lines • ▼ Show 20 Lines | switch (type_) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* If staging texture was used, copy contents to original texture. */ | /* If staging texture was used, copy contents to original texture. */ | ||||
| if (use_staging_texture) { | if (use_staging_texture) { | ||||
| /* When using staging texture, copy results into existing texture. */ | /* When using staging texture, copy results into existing texture. */ | ||||
| BLI_assert(staging_texture != nil); | BLI_assert(staging_texture != nil); | ||||
| blit_encoder = ctx->main_command_buffer.ensure_begin_blit_encoder(); | blit_encoder = ctx->main_command_buffer.ensure_begin_blit_encoder(); | ||||
| [blit_encoder copyFromTexture:staging_texture toTexture:texture_]; | |||||
| /* Copy modified staging texture region back to original texture. | |||||
| * Differing blit dimensions based on type. */ | |||||
| switch (type_) { | |||||
| case GPU_TEXTURE_1D: | |||||
| case GPU_TEXTURE_1D_ARRAY: { | |||||
| int base_slice = (type_ == GPU_TEXTURE_1D_ARRAY) ? offset[1] : 0; | |||||
| int final_slice = base_slice + ((type_ == GPU_TEXTURE_1D_ARRAY) ? extent[1] : 1); | |||||
| for (int array_index = base_slice; array_index < final_slice; array_index++) { | |||||
| [blit_encoder copyFromTexture:staging_texture | |||||
| sourceSlice:array_index | |||||
| sourceLevel:mip | |||||
| sourceOrigin:MTLOriginMake(offset[0], 0, 0) | |||||
| sourceSize:MTLSizeMake(extent[0], 1, 1) | |||||
| toTexture:texture_ | |||||
| destinationSlice:array_index | |||||
| destinationLevel:mip | |||||
| destinationOrigin:MTLOriginMake(offset[0], 0, 0)]; | |||||
| } | |||||
| } break; | |||||
| case GPU_TEXTURE_2D: | |||||
| case GPU_TEXTURE_2D_ARRAY: { | |||||
| int base_slice = (type_ == GPU_TEXTURE_2D_ARRAY) ? offset[2] : 0; | |||||
| int final_slice = base_slice + ((type_ == GPU_TEXTURE_2D_ARRAY) ? extent[2] : 1); | |||||
| for (int array_index = base_slice; array_index < final_slice; array_index++) { | |||||
| [blit_encoder copyFromTexture:staging_texture | |||||
| sourceSlice:array_index | |||||
| sourceLevel:mip | |||||
| sourceOrigin:MTLOriginMake(offset[0], offset[1], 0) | |||||
| sourceSize:MTLSizeMake(extent[0], extent[1], 1) | |||||
| toTexture:texture_ | |||||
| destinationSlice:array_index | |||||
| destinationLevel:mip | |||||
| destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)]; | |||||
| } | |||||
| } break; | |||||
| case GPU_TEXTURE_3D: { | |||||
| [blit_encoder copyFromTexture:staging_texture | |||||
| sourceSlice:0 | |||||
| sourceLevel:mip | |||||
| sourceOrigin:MTLOriginMake(offset[0], offset[1], offset[2]) | |||||
| sourceSize:MTLSizeMake(extent[0], extent[1], extent[2]) | |||||
| toTexture:texture_ | |||||
| destinationSlice:0 | |||||
| destinationLevel:mip | |||||
| destinationOrigin:MTLOriginMake(offset[0], offset[1], offset[2])]; | |||||
| } break; | |||||
| case GPU_TEXTURE_CUBE: | |||||
| case GPU_TEXTURE_CUBE_ARRAY: { | |||||
| /* Iterate over all cube faces in range (offset[2], offset[2] + extent[2]). */ | |||||
| for (int i = 0; i < extent[2]; i++) { | |||||
| int face_index = offset[2] + i; | |||||
| [blit_encoder copyFromTexture:staging_texture | |||||
| sourceSlice:face_index | |||||
| sourceLevel:mip | |||||
| sourceOrigin:MTLOriginMake(offset[0], offset[1], 0) | |||||
| sourceSize:MTLSizeMake(extent[0], extent[1], 1) | |||||
| toTexture:texture_ | |||||
| destinationSlice:face_index | |||||
| destinationLevel:mip | |||||
| destinationOrigin:MTLOriginMake(offset[0], offset[1], 0)]; | |||||
| } | |||||
| } break; | |||||
| case GPU_TEXTURE_ARRAY: | |||||
| case GPU_TEXTURE_BUFFER: | |||||
| BLI_assert_unreachable(); | |||||
| break; | |||||
| } | |||||
| [staging_texture release]; | [staging_texture release]; | ||||
| } | } | ||||
| /* Finalize Blit Encoder. */ | /* Finalize Blit Encoder. */ | ||||
| if (can_use_direct_blit) { | if (can_use_direct_blit) { | ||||
| /* Textures which use MTLStorageModeManaged need to have updated contents | /* Textures which use MTLStorageModeManaged need to have updated contents | ||||
| * synced back to CPU to avoid an automatic flush overwriting contents. */ | * synced back to CPU to avoid an automatic flush overwriting contents. */ | ||||
| if (texture_.storageMode == MTLStorageModeManaged) { | if (texture_.storageMode == MTLStorageModeManaged) { | ||||
| ▲ Show 20 Lines • Show All 1,107 Lines • Show Last 20 Lines | |||||