Skip to content

Commit

Permalink
[SYCL][Bindless] Add mipmap interop + slight redesign + bug fix
Browse files Browse the repository at this point in the history
Mipmap interop:
 - Remove "interop" image type as it is redundant for image creation
 - Add a vulkan mipmap interop test

Slight redesign:
 - Simplify external resources

Modify the bindless spec to reflect these changes

Fix Vulkan interop tests to prevent memory leak issue by freeing mapped memory
  • Loading branch information
Seanst98 committed Feb 26, 2024
1 parent c90de3c commit 761d8c1
Show file tree
Hide file tree
Showing 11 changed files with 726 additions and 197 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ enum class image_channel_type : /* unspecified */ {
enum class image_type : /* unspecified */ {
standard,
mipmap,
interop,
};

struct image_descriptor {
Expand Down Expand Up @@ -229,7 +228,7 @@ struct image_descriptor {

The image descriptor represents the image dimensions, channel type, and channel
order. An `image_type` member is also present to allow for implementation of
mipmapped and interop images.
mipmapped images.

The `image_descriptor` shall be default constructible and follow by-value
semantics.
Expand Down Expand Up @@ -1236,53 +1235,71 @@ memory or semaphore objects. CUDA for example only supports importation of
external memory and semaphores, but provides no support for their exportation.
====

=== Importing external memory objects
=== External Resource types

In order to import a memory object, an external API must provide an appropriate
handle to that memory. The exact structure and type of this handle can depend on
the external API, and the operating system the application is running on.

In order to facilitate a number of different external memory handle types, we
propose the following structures.
In order to facilitate the importing of a number of different external memory
and external semaphore handle types, we propose the following resource
structures.

[NOTE]
====
We only show two examples of external memory handle types here, but the
`external_mem_descriptor` struct could be templated by any number of handle
We only show three examples of external resource handle types here, but the
`external_mem_descriptor` and `external_semaphore_descriptor` structs, as
defined in <<importing_external_memory_objects>> and
<<importing_external_semaphores>>, could be templated by any number of handle
types, provided that the SYCL implementation provides support for them.
====

```cpp
namespace sycl::ext::oneapi::experimental {

// POSIX file descriptor memory handle type
struct external_mem_fd {
// POSIX file descriptor handle type
struct resource_fd {
int file_descriptor;
};

// Windows NT memory handle type
struct external_mem_win32 {
// Windows NT handle type
struct resource_win32_handle {
void *handle;
};

// Windows NT name type
struct resource_win32_name {
const void *name;
};

// Descriptor templated on specific external memory handle type
template <typename external_mem_handle_type>
struct external_mem_handle_type {
external_mem_handle_type external_handle;
}
```

=== Importing external memory objects [[importing_external_memory_objects]]

In order to import a memory object, an external API must provide an appropriate
handle to that memory. The exact structure and type of this handle can depend on
the external API, and the operating system the application is running on.

External memory import is facilitated through the following proposed descriptor
struct.

```cpp
namespace sycl::ext::oneapi::experimental {

// Descriptor templated on specific resource type
template <typename ResourceType>
struct external_mem_descriptor {
ResourceType external_resource;
size_t size_in_bytes;
};

}
```

The user should create an `external_mem_descriptor` templated on the appropriate
handle type for their purposes, e.g. `external_mem_fd` to describe a POSIX file
descriptor resource on Linux systems, or an `external_mem_win32` for Windows NT
resource handles.
handle type, `ResourceType`, for their purposes, e.g. `resource_fd` to describe
a POSIX file descriptor resource on Linux systems, or a `resource_win32_handle`
for Windows NT resource handles.

Once the user populates the `external_mem_descriptor` with the appropriate
`external_mem_handle_type` values, and the size of the external memory in bytes,
`ResourceType` values, and the size of the external memory in bytes,
they can then import that memory into SYCL through `import_external_memory`.

```cpp
Expand All @@ -1293,15 +1310,15 @@ struct interop_mem_handle {
raw_handle_type raw_handle;
};

template <typename external_mem_handle_type>
template <typename ResourceType>
interop_mem_handle import_external_memory(
external_mem_descriptor<external_mem_handle_type> externalMemDescriptor,
external_mem_descriptor<ResourceType> externalMemDescriptor,
const sycl::device &syclDevice,
const sycl::context &syclContext);

template <typename external_mem_handle_type>
template <typename ResourceType>
interop_mem_handle import_external_memory(
external_mem_descriptor<external_mem_handle_type> externalMemDescriptor,
external_mem_descriptor<ResourceType> externalMemDescriptor,
const sycl::queue &syclQueue);

image_mem_handle map_external_image_memory(
Expand All @@ -1325,8 +1342,12 @@ When calling `create_image` with an `image_mem_handle` mapped from an external
memory object, the user must ensure that the image descriptor they pass to
`create_image` has members that match or map to those of the external API.
A mismatch between any of the `width`, `height`, `depth`, `image_channel_type`,
or `image_channel_order` members will result in undefined behavior. The
`image_type` member must be set to `image_type::interop`.
or `image_channel_order` members will result in undefined behavior.

Additionally, the `image_type` describing the image must match to the image of
the external API. The current supported importable image types are `standard`
and `mipmap`. Attempting to import other image types will result in undefined
behaviour.

Once a user has finished operating on imported memory, they must ensure that
they destroy the imported memory handle through `release_external_memory`.
Expand All @@ -1348,7 +1369,7 @@ void release_external_memory(interop_mem_handle interopMem,
Destroying or freeing any imported memory through `image_mem_free` or
`sycl::free` will result in undefined behavior.

=== Importing external semaphores
=== Importing external semaphores [[importing_external_semaphores]]

In addition to proposing importation of external memory resources, we also
propose importation of synchronization primitives. Just like the sharing of
Expand All @@ -1358,47 +1379,29 @@ memory resources handles can take different forms of structure and type
depending on the API and operating system, so do external semaphore resource
handles.

In order to facilitate a number of different external semaphore handle types, we
propose the following structures.

[NOTE]
====
We only show two examples of external semaphore resource handle types here, but
the `external_semaphore_descriptor` struct could be templated by any number of
handle types, provided that the SYCL implementation provides support for them.
====
External semaphore import is facilitated through the following proposed
descriptor struct.

```cpp
namespace sycl::ext::oneapi::experimental {

// POSIX file descriptor semaphore handle
struct external_semaphore_fd {
int file_descriptor;
};

// Windows NT semaphore handle
struct external_semaphore_win32 {
void *handle;
const void *name;
};

// Descriptor templated on specific external semaphore handle type
template <typename external_semaphore_handle_type>
// Descriptor templated on specific resource type
template <typename ResourceType>
struct external_semaphore_descriptor {
external_semaphore_handle_type external_handle;
ResourceType external_resource;
};

}
```

The user should create an `external_semaphore_descriptor` templated on the
appropriate handle type for their purposes, e.g. `external_semaphore_fd` to
describe a POSIX file descriptor resource on Linux systems, or an
`external_mem_win32` for Windows NT resource handles.
appropriate handle type, `ResourceType`, for their purposes, e.g. `resource_fd`
to describe a POSIX file descriptor resource on Linux systems, or a
`resource_win32_handle` for Windows NT resource handles.

Once the user populates the `external_semaphore_descriptor` with the appropriate
`external_semaphore_handle_type` values, they can then import that semaphore
into SYCL through `import_external_semaphore`.
`ResourceType` values, they can then import that semaphore into SYCL through
`import_external_semaphore`.

```cpp
namespace sycl::ext::oneapi::experimental {
Expand All @@ -1408,17 +1411,17 @@ struct interop_semaphore_handle {
raw_handle_type raw_handle;
};

template <typename external_semaphore_handle_type>
template <typename ResourceType>
interop_semaphore_handle import_external_semaphore(
external_semaphore_descriptor<external_semaphore_handle_type>
external_semaphore_descriptor<ResourceType>
externalSemaphoreDescriptor,
const sycl::device &syclDevice,
const sycl::context &syclContext);
}

template <typename external_semaphore_handle_type>
template <typename ResourceType>
interop_semaphore_handle import_external_semaphore(
external_semaphore_descriptor<external_semaphore_handle_type>
external_semaphore_descriptor<ResourceType>
externalSemaphoreDescriptor,
const sycl::queue &syclQueue);
}
Expand Down Expand Up @@ -1786,10 +1789,8 @@ sycl::ext::oneapi::experimental::image_channel_type channel_type =
/* we assume sycl::image_channel_type::unsigned_int32 */;

// Image descriptor - mapped to external API image layout
// with `image_type::interop`
sycl::ext::oneapi::experimental::image_descriptor desc(
{width, height}, channel_order, channel_type,
sycl::ext::oneapi::experimental::image_type::interop);
{width, height}, channel_order, channel_type);

size_t img_size_in_bytes = width * height * sizeof(uint32_t);

Expand All @@ -1798,12 +1799,12 @@ int external_output_image_file_descriptor = /* passed from external API */

// Extension: populate external memory descriptors
sycl::ext::oneapi::experimental::external_mem_descriptor<
sycl::ext::oneapi::experimental::external_mem_fd>
sycl::ext::oneapi::experimental::resource_fd>
input_ext_mem_desc{external_input_image_file_descriptor,
img_size_in_bytes};

sycl::ext::oneapi::experimental::external_mem_descriptor<
sycl::ext::oneapi::experimental::external_mem_fd>
sycl::ext::oneapi::experimental::resource_fd>
output_ext_mem_desc{external_output_image_file_descriptor,
img_size_in_bytes};

Expand All @@ -1818,11 +1819,11 @@ int done_semaphore_file_descriptor = /* passed from external API */;
// Extension: populate external semaphore descriptor.
// We assume POSIX file descriptor resource types
sycl::ext::oneapi::experimental::external_semaphore_descriptor<
sycl::ext::oneapi::experimental::external_semaphore_fd>
sycl::ext::oneapi::experimental::resource_fd>
wait_external_semaphore_desc{wait_semaphore_file_descriptor};

sycl::ext::oneapi::experimental::external_semaphore_descriptor<
sycl::ext::oneapi::experimental::external_semaphore_fd>
sycl::ext::oneapi::experimental::resource_fd>
done_external_semaphore_desc{done_semaphore_file_descriptor};

try {
Expand Down Expand Up @@ -2084,4 +2085,6 @@ These features still need to be handled:
|5.3|2024-02-16| - Replace `read_image` and `read_mipmap` APIs in favor of more
descriptive naming, with `fetch_image`, `sample_image`, and
`sample_mipmap`.
|5.4|2024-02-26| - Update interop with mipmap interop and slight redesign
- `interop` removed from `image_type`
|======================
7 changes: 3 additions & 4 deletions sycl/include/sycl/ext/oneapi/bindless_images_descriptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ namespace ext::oneapi::experimental {
/// image type enum
enum class image_type : unsigned int {
standard = 0,
interop = 1,
mipmap = 2,
cubemap = 3, /* Not implemented */
layered = 4, /* Not implemented */
mipmap = 1,
cubemap = 2, /* Not implemented */
layered = 3, /* Not implemented */
};

/// A struct to describe the properties of an image.
Expand Down
47 changes: 32 additions & 15 deletions sycl/include/sycl/ext/oneapi/bindless_images_interop.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,54 @@ struct interop_mem_handle {
raw_handle_type raw_handle;
};

/// External memory file descriptor type
struct external_mem_fd {
/// Opaque interop semaphore handle type
struct interop_semaphore_handle {
using raw_handle_type = pi_uint64;
raw_handle_type raw_handle;
};

// External resource file descriptor type
struct resource_fd {
int file_descriptor;
};

/// Windows external memory type
struct external_mem_win32 {
// Windows external handle type
struct resource_win32_handle {
void *handle;
};

// Windows external name type
struct resource_win32_name {
const void *name;
};

/// Opaque external memory descriptor type
template <typename HandleType> struct external_mem_descriptor {
HandleType external_handle;
template <typename ResourceType> struct external_mem_descriptor {
ResourceType external_resource;
size_t size_in_bytes;
};

/// Opaque interop semaphore handle type
struct interop_semaphore_handle {
using raw_handle_type = pi_uint64;
raw_handle_type raw_handle;
// Opaque external semaphore descriptor type
template <typename ResourceType> struct external_semaphore_descriptor {
ResourceType external_resource;
};

/// External semaphore file descriptor type
struct external_semaphore_fd {
/// EVERYTHING BELOW IS DEPRECATED

/// External memory file descriptor type
struct external_mem_fd {
int file_descriptor;
};

/// Opaque external semaphore descriptor type
template <typename HandleType> struct external_semaphore_descriptor {
HandleType external_handle;
/// Windows external memory type
struct external_mem_win32 {
void *handle;
const void *name;
};

/// External semaphore file descriptor type
struct external_semaphore_fd {
int file_descriptor;
};

} // namespace ext::oneapi::experimental
Expand Down
16 changes: 8 additions & 8 deletions sycl/plugins/unified_runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ endif()
if(SYCL_PI_UR_USE_FETCH_CONTENT)
include(FetchContent)

set(UNIFIED_RUNTIME_REPO "https://github.com/oneapi-src/unified-runtime.git")
# commit 588615e90bfd2b889834120dfff172236c6b8aa8
# Merge: 4e69cc60 47084751
# Author: Kenneth Benzie (Benie) <k.benzie@codeplay.com>
# Date: Thu Feb 22 16:10:13 2024 +0000
# Merge pull request #1371 from pbalcer/l0-query-status-sync-deadlock
# [L0] fix a deadlock in queue sync and event status query
set(UNIFIED_RUNTIME_TAG 588615e90bfd2b889834120dfff172236c6b8aa8)
set(UNIFIED_RUNTIME_REPO "https://github.com/Seanst98/unified-runtime.git")
# commit 79c28d0f0713f58358d5080653d95803fd131749
# Merge: 25e0b603 45d76b78
# Author: aarongreig <aaron.greig@codeplay.com>
# Date: Fri Jan 12 16:14:44 2024 +0000
# Merge pull request #1186 from hdelan/device-global-hip
# [HIP] Add support for global variable read write
set(UNIFIED_RUNTIME_TAG 4fc4b4f56ac25b871f52f864b4b1da2560ec0afe)

if(SYCL_PI_UR_OVERRIDE_FETCH_CONTENT_REPO)
set(UNIFIED_RUNTIME_REPO "${SYCL_PI_UR_OVERRIDE_FETCH_CONTENT_REPO}")
Expand Down
Loading

0 comments on commit 761d8c1

Please sign in to comment.