diff --git a/source/blender/gpu/metal/mtl_texture.mm b/source/blender/gpu/metal/mtl_texture.mm index ca73c206e38..f9d46627ada 100644 --- a/source/blender/gpu/metal/mtl_texture.mm +++ b/source/blender/gpu/metal/mtl_texture.mm @@ -527,6 +527,8 @@ void gpu::MTLTexture::update_sub( } } + const bool is_compressed = (format_flag_ & GPU_FORMAT_COMPRESSED); + @autoreleasepool { /* Determine totalsize of INPUT Data. */ int num_channels = to_component_len(format_); @@ -593,10 +595,12 @@ void gpu::MTLTexture::update_sub( false /* Not a clear. */ }; - /* Determine whether we can do direct BLIT or not. */ + /* Determine whether we can do direct BLIT or not. For compressed textures, + * always assume a direct blit (input data pretends to be float, but it is + * not). */ bool can_use_direct_blit = true; - if (expected_dst_bytes_per_pixel != input_bytes_per_pixel || - num_channels != destination_num_channels) + if (!is_compressed && (expected_dst_bytes_per_pixel != input_bytes_per_pixel || + num_channels != destination_num_channels)) { can_use_direct_blit = false; } @@ -620,7 +624,7 @@ void gpu::MTLTexture::update_sub( /* Safety Checks. */ if (type == GPU_DATA_UINT_24_8 || type == GPU_DATA_10_11_11_REV || - type == GPU_DATA_2_10_10_10_REV) + type == GPU_DATA_2_10_10_10_REV || is_compressed) { BLI_assert(can_use_direct_blit && "Special input data type must be a 1-1 mapping with destination texture as it " @@ -755,6 +759,12 @@ void gpu::MTLTexture::update_sub( extent[0] : ctx->pipeline_state.unpack_row_length); size_t bytes_per_image = bytes_per_row; + if (is_compressed) { + size_t block_size = to_block_size(format_); + size_t blocks_x = divide_ceil_u(extent[0], 4); + bytes_per_row = blocks_x * block_size; + bytes_per_image = bytes_per_row; + } int max_array_index = ((type_ == GPU_TEXTURE_1D_ARRAY) ? extent[1] : 1); for (int array_index = 0; array_index < max_array_index; array_index++) { @@ -827,6 +837,13 @@ void gpu::MTLTexture::update_sub( extent[0] : ctx->pipeline_state.unpack_row_length); size_t bytes_per_image = bytes_per_row * extent[1]; + if (is_compressed) { + size_t block_size = to_block_size(format_); + size_t blocks_x = divide_ceil_u(extent[0], 4); + size_t blocks_y = divide_ceil_u(extent[1], 4); + bytes_per_row = blocks_x * block_size; + bytes_per_image = bytes_per_row * blocks_y; + } size_t texture_array_relative_offset = 0; int base_slice = (type_ == GPU_TEXTURE_2D_ARRAY) ? offset[2] : 0; @@ -1218,6 +1235,12 @@ void gpu::MTLTexture::ensure_mipmaps(int miplvl) void gpu::MTLTexture::generate_mipmap() { + /* Compressed textures allow users to provide their own custom mipmaps. And + * we can't generate them at runtime anyway. */ + if (format_flag_ & GPU_FORMAT_COMPRESSED) { + return; + } + /* Fetch Active Context. */ MTLContext *ctx = static_cast(unwrap(GPU_context_active_get())); BLI_assert(ctx); diff --git a/source/blender/gpu/metal/mtl_texture_util.mm b/source/blender/gpu/metal/mtl_texture_util.mm index 86773f048b7..8b29a582833 100644 --- a/source/blender/gpu/metal/mtl_texture_util.mm +++ b/source/blender/gpu/metal/mtl_texture_util.mm @@ -160,13 +160,17 @@ MTLPixelFormat gpu_texture_format_to_metal(eGPUTextureFormat tex_format) return MTLPixelFormatR8Snorm; /* Special formats, texture only. */ case GPU_SRGB8_A8_DXT1: + return MTLPixelFormatBC1_RGBA_sRGB; case GPU_SRGB8_A8_DXT3: + return MTLPixelFormatBC2_RGBA_sRGB; case GPU_SRGB8_A8_DXT5: + return MTLPixelFormatBC3_RGBA_sRGB; case GPU_RGBA8_DXT1: + return MTLPixelFormatBC1_RGBA; case GPU_RGBA8_DXT3: + return MTLPixelFormatBC2_RGBA; case GPU_RGBA8_DXT5: - BLI_assert_msg(false, "Compressed texture not implemented yet!\n"); - return MTLPixelFormatRGBA8Unorm; + return MTLPixelFormatBC3_RGBA; case GPU_SRGB8: /* 24-Bit pixel format are not supported. Emulate using a padded type with alpha. */ return MTLPixelFormatRGBA8Unorm_sRGB; @@ -247,6 +251,14 @@ size_t get_mtl_format_bytesize(MTLPixelFormat tex_format) return 4; case MTLPixelFormatDepth16Unorm: return 2; + case MTLPixelFormatBC1_RGBA: + case MTLPixelFormatBC1_RGBA_sRGB: + return 1; /* Note: not quite correct (BC1 is 0.5 bpp). */ + case MTLPixelFormatBC2_RGBA: + case MTLPixelFormatBC2_RGBA_sRGB: + case MTLPixelFormatBC3_RGBA: + case MTLPixelFormatBC3_RGBA_sRGB: + return 1; default: BLI_assert_msg(false, "Unrecognised GPU pixel format!\n"); @@ -272,6 +284,12 @@ int get_mtl_format_num_components(MTLPixelFormat tex_format) case MTLPixelFormatRGBA8Unorm_sRGB: case MTLPixelFormatRGB10A2Uint: case MTLPixelFormatRGB10A2Unorm: + case MTLPixelFormatBC1_RGBA_sRGB: + case MTLPixelFormatBC2_RGBA_sRGB: + case MTLPixelFormatBC3_RGBA_sRGB: + case MTLPixelFormatBC1_RGBA: + case MTLPixelFormatBC2_RGBA: + case MTLPixelFormatBC3_RGBA: return 4; case MTLPixelFormatRG11B10Float: