diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index dc5a9885e16..b68d7886716 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -147,6 +147,18 @@ void immDrawPixelsTexTiled_scaling_clipping(IMMDrawPixelsTexState *state, const float color[4]) { int subpart_x, subpart_y, tex_w = 256, tex_h = 256; +#ifdef __APPLE__ + if (GPU_backend_get_type() == GPU_BACKEND_METAL) { + /* NOTE(Metal): The Metal backend will keep all temporary texture memory within a command + * submission in-flight, so using a partial tile size does not provide any tangible memory + * reduction, but does incur additional API overhead and significant cache inefficiency on AMD + * platforms. + * The Metal API also provides smart resource paging such that the application can + * still efficiently swap memory, even if system is low in physical memory. */ + tex_w = img_w; + tex_h = img_h; + } +#endif int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y; int components; const bool use_clipping = ((clip_min_x < clip_max_x) && (clip_min_y < clip_max_y)); diff --git a/source/blender/gpu/metal/mtl_texture.mm b/source/blender/gpu/metal/mtl_texture.mm index eb8949e2c66..54b6cad6542 100644 --- a/source/blender/gpu/metal/mtl_texture.mm +++ b/source/blender/gpu/metal/mtl_texture.mm @@ -594,17 +594,6 @@ void gpu::MTLTexture::update_sub( } } - /* Prepare staging buffer for data. */ - id staging_buffer = nil; - uint64_t staging_buffer_offset = 0; - - /* Fetch allocation from scratch buffer. */ - MTLTemporaryBuffer allocation = - ctx->get_scratchbuffer_manager().scratch_buffer_allocate_range_aligned(totalsize, 256); - memcpy(allocation.data, data, totalsize); - staging_buffer = allocation.metal_buffer; - staging_buffer_offset = allocation.buffer_offset; - /* Common Properties. */ MTLPixelFormat compatible_write_format = mtl_format_get_writeable_view_format( destination_format); @@ -616,6 +605,12 @@ void gpu::MTLTexture::update_sub( return; } + /* Fetch allocation from memory pool. */ + MTLBuffer *temp_allocation = MTLContext::get_global_memory_manager()->allocate_with_data( + totalsize, true, data); + id staging_buffer = temp_allocation->get_metal_buffer(); + BLI_assert(staging_buffer != nil); + /* Prepare command encoders. */ id blit_encoder = nil; id compute_encoder = nil; @@ -697,7 +692,7 @@ void gpu::MTLTexture::update_sub( int max_array_index = ((type_ == GPU_TEXTURE_1D_ARRAY) ? extent[1] : 1); for (int array_index = 0; array_index < max_array_index; array_index++) { - int buffer_array_offset = staging_buffer_offset + (bytes_per_image * array_index); + int buffer_array_offset = (bytes_per_image * array_index); [blit_encoder copyFromBuffer:staging_buffer sourceOffset:buffer_array_offset @@ -727,7 +722,7 @@ void gpu::MTLTexture::update_sub( MTLComputeState &cs = ctx->main_command_buffer.get_compute_state(); cs.bind_pso(pso); cs.bind_compute_bytes(¶ms, sizeof(params), 0); - cs.bind_compute_buffer(staging_buffer, staging_buffer_offset, 1); + cs.bind_compute_buffer(staging_buffer, 0, 1); cs.bind_compute_texture(texture_handle, 0); [compute_encoder dispatchThreads:MTLSizeMake(extent[0], 1, 1) /* Width, Height, Layer */ @@ -747,7 +742,7 @@ void gpu::MTLTexture::update_sub( MTLComputeState &cs = ctx->main_command_buffer.get_compute_state(); cs.bind_pso(pso); cs.bind_compute_bytes(¶ms, sizeof(params), 0); - cs.bind_compute_buffer(staging_buffer, staging_buffer_offset, 1); + cs.bind_compute_buffer(staging_buffer, 0, 1); cs.bind_compute_texture(texture_handle, 0); [compute_encoder dispatchThreads:MTLSizeMake(extent[0], extent[1], 1) /* Width, layers, nil */ @@ -779,7 +774,7 @@ void gpu::MTLTexture::update_sub( } [blit_encoder copyFromBuffer:staging_buffer - sourceOffset:staging_buffer_offset + texture_array_relative_offset + sourceOffset:texture_array_relative_offset sourceBytesPerRow:bytes_per_row sourceBytesPerImage:bytes_per_image sourceSize:MTLSizeMake(extent[0], extent[1], 1) @@ -807,7 +802,7 @@ void gpu::MTLTexture::update_sub( MTLComputeState &cs = ctx->main_command_buffer.get_compute_state(); cs.bind_pso(pso); cs.bind_compute_bytes(¶ms, sizeof(params), 0); - cs.bind_compute_buffer(staging_buffer, staging_buffer_offset, 1); + cs.bind_compute_buffer(staging_buffer, 0, 1); cs.bind_compute_texture(texture_handle, 0); [compute_encoder dispatchThreads:MTLSizeMake( @@ -828,7 +823,7 @@ void gpu::MTLTexture::update_sub( MTLComputeState &cs = ctx->main_command_buffer.get_compute_state(); cs.bind_pso(pso); cs.bind_compute_bytes(¶ms, sizeof(params), 0); - cs.bind_compute_buffer(staging_buffer, staging_buffer_offset, 1); + cs.bind_compute_buffer(staging_buffer, 0, 1); cs.bind_compute_texture(texture_handle, 0); [compute_encoder dispatchThreads:MTLSizeMake(extent[0], extent[1], @@ -848,7 +843,7 @@ void gpu::MTLTexture::update_sub( ctx->pipeline_state.unpack_row_length); int bytes_per_image = bytes_per_row * extent[1]; [blit_encoder copyFromBuffer:staging_buffer - sourceOffset:staging_buffer_offset + sourceOffset:0 sourceBytesPerRow:bytes_per_row sourceBytesPerImage:bytes_per_image sourceSize:MTLSizeMake(extent[0], extent[1], extent[2]) @@ -871,7 +866,7 @@ void gpu::MTLTexture::update_sub( MTLComputeState &cs = ctx->main_command_buffer.get_compute_state(); cs.bind_pso(pso); cs.bind_compute_bytes(¶ms, sizeof(params), 0); - cs.bind_compute_buffer(staging_buffer, staging_buffer_offset, 1); + cs.bind_compute_buffer(staging_buffer, 0, 1); cs.bind_compute_texture(texture_handle, 0); [compute_encoder dispatchThreads:MTLSizeMake( @@ -896,7 +891,7 @@ void gpu::MTLTexture::update_sub( int face_index = offset[2] + i; [blit_encoder copyFromBuffer:staging_buffer - sourceOffset:staging_buffer_offset + texture_array_relative_offset + sourceOffset:texture_array_relative_offset sourceBytesPerRow:bytes_per_row sourceBytesPerImage:bytes_per_image sourceSize:MTLSizeMake(extent[0], extent[1], 1) @@ -930,7 +925,7 @@ void gpu::MTLTexture::update_sub( for (int i = 0; i < extent[2]; i++) { int face_index = offset[2] + i; [blit_encoder copyFromBuffer:staging_buffer - sourceOffset:staging_buffer_offset + texture_array_relative_offset + sourceOffset:texture_array_relative_offset sourceBytesPerRow:bytes_per_row sourceBytesPerImage:bytes_per_image sourceSize:MTLSizeMake(extent[0], extent[1], 1) @@ -1058,6 +1053,11 @@ void gpu::MTLTexture::update_sub( /* Decrement texture reference counts. This ensures temporary texture views are released. */ [texture_handle release]; + + /* Release temporary staging buffer allocation. + * NOTE: Allocation will be tracked with command submission and released once no longer in use. + */ + temp_allocation->free(); } }