Skip to content

Commit 91c7201

Browse files
author
swfly
committed
import_external_image
1 parent 83dd2aa commit 91c7201

File tree

13 files changed

+95
-20
lines changed

13 files changed

+95
-20
lines changed

include/luisa/runtime/device.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,11 @@ class LC_RUNTIME_API Device {
189189
return _create<Image<T>>(pixel, size, mip_levels, simultaneous_access, allow_raster_target);
190190
}
191191

192+
template<typename T>
193+
[[nodiscard]] auto import_external_image(PixelStorage pixel, uint2 size, byte* buffer, uint mip_levels = 1u, bool simultaneous_access = false, bool allow_raster_target = false) noexcept {
194+
return _create<Image<T>>(pixel, size, buffer, mip_levels, simultaneous_access, allow_raster_target);
195+
}
196+
192197
template<typename T>
193198
[[nodiscard]] auto create_sparse_image(PixelStorage pixel, uint width, uint height, uint mip_levels = 1u, bool simultaneous_access = true) noexcept {
194199
return _create<SparseImage<T>>(pixel, make_uint2(width, height), mip_levels, simultaneous_access);

include/luisa/runtime/image.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,23 @@ class Image final : public Resource {
7373
size.x, size.y, 1u,
7474
detail::max_mip_levels(make_uint3(size, 1u), mip_levels),
7575
simultaneous_access, allow_raster_target);
76-
}(),
77-
storage, size, mip_levels} {}
76+
}(),
77+
storage, size, mip_levels} {}
78+
79+
Image(DeviceInterface *device, PixelStorage storage, uint2 size, byte* data,
80+
uint mip_levels = 1u, bool simultaneous_access = false, bool allow_raster_target = false) noexcept
81+
: Image{device,
82+
[&] {
83+
if (size.x == 0 || size.y == 0) [[unlikely]] {
84+
detail::image_size_zero_error();
85+
}
86+
return device->create_texture(
87+
pixel_storage_to_format<T>(storage), 2u,
88+
size.x, size.y, 1u,
89+
detail::max_mip_levels(make_uint3(size, 1u), mip_levels),
90+
simultaneous_access, allow_raster_target, data);
91+
}(),
92+
storage, size, mip_levels} {}
7893

7994
public:
8095
Image() noexcept = default;

include/luisa/runtime/remote/client_interface.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class LC_RUNTIME_API ClientInterface : public DeviceInterface {
4646
[[nodiscard]] ResourceCreationInfo create_texture(
4747
PixelFormat format, uint dimension,
4848
uint width, uint height, uint depth,
49-
uint mipmap_levels, bool simultaneous_access, bool allow_raster_target) noexcept override;
49+
uint mipmap_levels, bool simultaneous_access, bool allow_raster_target, byte* external_buffer) noexcept override;
5050
void destroy_texture(uint64_t handle) noexcept override;
5151

5252
// bindless array

include/luisa/runtime/rhi/device_interface.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ class LC_RUNTIME_API DeviceInterface : public luisa::enable_shared_from_this<Dev
125125
[[nodiscard]] virtual ResourceCreationInfo create_texture(
126126
PixelFormat format, uint dimension,
127127
uint width, uint height, uint depth,
128-
uint mipmap_levels, bool simultaneous_access, bool allow_raster_target) noexcept = 0;
128+
uint mipmap_levels, bool simultaneous_access, bool allow_raster_target,
129+
byte* external_buffer = nullptr) noexcept = 0;
129130
virtual void destroy_texture(uint64_t handle) noexcept = 0;
130131

131132
// bindless array

src/backends/fallback/fallback_device.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,14 +162,26 @@ BufferCreationInfo FallbackDevice::create_buffer(const ir::CArc<ir::Type> *eleme
162162
#endif
163163
}
164164

165-
ResourceCreationInfo FallbackDevice::create_texture(PixelFormat format, uint dimension, uint width, uint height, uint depth, uint mipmap_levels, bool simultaneous_access, bool allow_raster_target) noexcept {
166-
auto texture = luisa::new_with_allocator<FallbackTexture>(
167-
pixel_format_to_storage(format), dimension,
168-
make_uint3(width, height, depth), mipmap_levels);
169-
return {
170-
.handle = reinterpret_cast<uint64_t>(texture),
171-
.native_handle = texture->native_handle(),
172-
};
165+
ResourceCreationInfo FallbackDevice::create_texture(PixelFormat format, uint dimension, uint width, uint height, uint depth, uint mipmap_levels, bool simultaneous_access, bool allow_raster_target, byte* external_buffer) noexcept {
166+
167+
if (external_buffer == nullptr) {
168+
auto texture = luisa::new_with_allocator<FallbackTexture>(
169+
pixel_format_to_storage(format), dimension,
170+
make_uint3(width, height, depth), mipmap_levels);
171+
return {
172+
.handle = reinterpret_cast<uint64_t>(texture),
173+
.native_handle = texture->native_handle(),
174+
};
175+
}
176+
else {
177+
auto texture = luisa::new_with_allocator<FallbackTexture>(
178+
pixel_format_to_storage(format), dimension,
179+
make_uint3(width, height, depth), mipmap_levels, reinterpret_cast<std::byte*>(external_buffer));
180+
return {
181+
.handle = reinterpret_cast<uint64_t>(texture),
182+
.native_handle = texture->native_handle(),
183+
};
184+
}
173185
}
174186

175187
ResourceCreationInfo FallbackDevice::create_stream(StreamTag stream_tag) noexcept {

src/backends/fallback/fallback_device.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class FallbackDevice : public DeviceInterface {
4949
uint compute_warp_size() const noexcept override;
5050
BufferCreationInfo create_buffer(const Type *element, size_t elem_count, void *external_memory) noexcept override;
5151
BufferCreationInfo create_buffer(const ir::CArc<ir::Type> *element, size_t elem_count, void *external_memory) noexcept override;
52-
ResourceCreationInfo create_texture(PixelFormat format, uint dimension, uint width, uint height, uint depth, uint mipmap_levels, bool simultaneous_access, bool allow_raster_target) noexcept override;
52+
ResourceCreationInfo create_texture(PixelFormat format, uint dimension, uint width, uint height, uint depth, uint mipmap_levels, bool simultaneous_access, bool allow_raster_target, byte* external_buffer) noexcept override;
5353
ResourceCreationInfo create_stream(StreamTag stream_tag) noexcept override;
5454
void dispatch(uint64_t stream_handle, CommandList &&list) noexcept override;
5555
void set_stream_log_callback(uint64_t stream_handle, const StreamLogCallback &callback) noexcept override;

src/backends/fallback/fallback_texture.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,49 @@ FallbackTexture::FallbackTexture(PixelStorage storage, uint dim, uint3 size, uin
124124
_data = luisa::allocate_with_allocator<std::byte>(static_cast<size_t>(size_pixels) << _pixel_stride_shift);
125125
}
126126
}
127+
FallbackTexture::FallbackTexture(PixelStorage storage, uint dim, uint3 size, uint levels, std::byte *external_buffer) noexcept
128+
: _storage{storage}, _mip_levels{levels}, _dimension{dim} {
129+
this->external = true;
130+
if (_dimension == 2u) {
131+
_pixel_stride_shift = std::bit_width(static_cast<uint>(pixel_storage_size(storage, make_uint3(1u)))) - 1u;
132+
if (storage == PixelStorage::BC6 || storage == PixelStorage::BC7) {
133+
_pixel_stride_shift = 0u;
134+
}
135+
_size[0] = size.x;
136+
_size[1] = size.y;
137+
_size[2] = 1u;
138+
_mip_offsets[0] = 0u;
139+
auto sz = make_uint2(size);
140+
for (auto i = 1u; i < levels; i++) {
141+
auto s = (sz + block_size - 1u) / block_size * block_size;
142+
_mip_offsets[i] = _mip_offsets[i - 1u] + s.x * s.y;
143+
sz = luisa::max(sz >> 1u, 1u);
144+
}
145+
auto s = (sz + block_size - 1u) / block_size * block_size;
146+
auto size_pixels = _mip_offsets[levels - 1u] + s.x * s.y;
147+
_data = external_buffer;
148+
} else {
149+
_pixel_stride_shift = std::bit_width(static_cast<uint>(pixel_storage_size(storage, make_uint3(1u)))) - 1u;
150+
_size[0] = size.x;
151+
_size[1] = size.y;
152+
_size[2] = size.z;
153+
_mip_offsets[0] = 0u;
154+
for (auto i = 1u; i < levels; i++) {
155+
auto s = (size + block_size - 1u) / block_size * block_size;
156+
_mip_offsets[i] = _mip_offsets[i - 1u] + s.x * s.y * s.z;
157+
size = luisa::max(size >> 1u, 1u);
158+
}
159+
auto s = (size + block_size - 1u) / block_size * block_size;
160+
auto size_pixels = _mip_offsets[levels - 1u] + s.x * s.y * s.z;
161+
_data = external_buffer;
162+
}
163+
}
127164

128-
FallbackTexture::~FallbackTexture() noexcept { luisa::deallocate_with_allocator(_data); }
165+
FallbackTexture::~FallbackTexture() noexcept {
166+
if (!external) {
167+
luisa::deallocate_with_allocator(_data);
168+
}
169+
}
129170

130171
FallbackTextureView FallbackTexture::view(uint level) const noexcept {
131172
auto size = luisa::max(make_uint3(_size[0], _size[1], _size[2]) >> level, 1u);

src/backends/fallback/fallback_texture.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,10 @@ class alignas(16u) FallbackTexture {
301301
uint _mip_levels : 8u; // 19B
302302
uint _dimension : 8u; // 20B
303303
std::array<uint, 15u> _mip_offsets{};// 80B
304-
304+
bool external{false};
305305
public:
306306
FallbackTexture(PixelStorage storage, uint dim, uint3 size, uint levels) noexcept;
307+
FallbackTexture(PixelStorage storage, uint dim, uint3 size, uint levels, std::byte* external_buffer) noexcept;
307308
~FallbackTexture() noexcept;
308309
FallbackTexture(FallbackTexture &&) noexcept = delete;
309310
FallbackTexture(const FallbackTexture &) noexcept = delete;

src/backends/metal/metal_device.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ void MetalDevice::destroy_buffer(uint64_t handle) noexcept {
311311

312312
ResourceCreationInfo MetalDevice::create_texture(PixelFormat format, uint dimension,
313313
uint width, uint height, uint depth, uint mipmap_levels,
314-
bool allow_simultaneous_access, bool allow_raster_target) noexcept {
314+
bool allow_simultaneous_access, bool allow_raster_target, byte* external_buffer) noexcept {
315315
return with_autorelease_pool([=, this] {
316316
auto texture = new_with_allocator<MetalTexture>(
317317
_handle, format, dimension, width, height, depth,

src/backends/metal/metal_device.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class MetalDevice : public DeviceInterface {
6060
BufferCreationInfo create_buffer(const Type *element, size_t elem_count, void *external_memory) noexcept override;
6161
BufferCreationInfo create_buffer(const ir::CArc<ir::Type> *element, size_t elem_count, void *external_memory) noexcept override;
6262
void destroy_buffer(uint64_t handle) noexcept override;
63-
ResourceCreationInfo create_texture(PixelFormat format, uint dimension, uint width, uint height, uint depth, uint mipmap_levels, bool simultaneous_access, bool allow_raster_target) noexcept override;
63+
ResourceCreationInfo create_texture(PixelFormat format, uint dimension, uint width, uint height, uint depth, uint mipmap_levels, bool simultaneous_access, bool allow_raster_target, byte* external_buffer) noexcept override;
6464
void destroy_texture(uint64_t handle) noexcept override;
6565
ResourceCreationInfo create_bindless_array(size_t size) noexcept override;
6666
void destroy_bindless_array(uint64_t handle) noexcept override;

0 commit comments

Comments
 (0)