Skip to content

[SYCL][ESIMD][EMU] Merging buffer/image info to surface info #5930

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 41 additions & 90 deletions sycl/plugins/esimd_emulator/pi_esimd_emulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1000,17 +1000,17 @@ pi_result piMemBufferCreate(pi_context Context, pi_mem_flags Flags, size_t Size,
}

char *MapBasePtr = nullptr;
cm_buffer_ptr_slot CmBuf;
cm_surface_ptr_t CmBuf;
cm_support::SurfaceIndex *CmIndex;
int Status = cm_support::CM_FAILURE;

if (Flags & PI_MEM_FLAGS_HOST_PTR_USE) {
CmBuf.tag = cm_buffer_ptr_slot::type_user_provided;
CmBuf.tag = cm_surface_ptr_t::TypeUserProvidedBuffer;
Status = Context->Device->CmDevicePtr->CreateBufferUP(
static_cast<unsigned int>(Size), HostPtr, CmBuf.UPBufPtr);
CmBuf.UPBufPtr->GetIndex(CmIndex);
} else {
CmBuf.tag = cm_buffer_ptr_slot::type_regular;
CmBuf.tag = cm_surface_ptr_t::TypeRegularBuffer;
Status = Context->Device->CmDevicePtr->CreateBuffer(
static_cast<unsigned int>(Size), CmBuf.RegularBufPtr);
CmBuf.RegularBufPtr->GetIndex(CmIndex);
Expand Down Expand Up @@ -1066,58 +1066,40 @@ pi_result piMemRelease(pi_mem Mem) {
}

if (--(Mem->RefCount) == 0) {
int Status = cm_support::CM_FAILURE;

if (Mem->getMemType() == PI_MEM_TYPE_BUFFER) {
_pi_buffer *PiBuf = static_cast<_pi_buffer *>(Mem);
if (PiBuf->BufferPtr.tag == cm_buffer_ptr_slot::type_user_provided) {
Status = Mem->Context->Device->CmDevicePtr->DestroyBufferUP(
PiBuf->BufferPtr.UPBufPtr);
} else {
Status = Mem->Context->Device->CmDevicePtr->DestroySurface(
PiBuf->BufferPtr.RegularBufPtr);
}
} else if (Mem->getMemType() == PI_MEM_TYPE_IMAGE2D) {
_pi_image *PiImg = static_cast<_pi_image *>(Mem);
if (PiImg->ImagePtr.tag == cm_image_ptr_slot::type_user_provided) {
Status = Mem->Context->Device->CmDevicePtr->DestroySurface2DUP(
PiImg->ImagePtr.UPImgPtr);
} else {
Status = Mem->Context->Device->CmDevicePtr->DestroySurface(
PiImg->ImagePtr.RegularImgPtr);
}
}

if (Status != cm_support::CM_SUCCESS) {
return PI_INVALID_MEM_OBJECT;
}

// Removing Surface-map entry
std::lock_guard<std::mutex> Lock{*PiESimdSurfaceMapLock};
auto MapEntryIt = PiESimdSurfaceMap->find(Mem->SurfaceIndex);
if (MapEntryIt != PiESimdSurfaceMap->end()) {
PiESimdSurfaceMap->erase(MapEntryIt);
} else {
if (PrintPiTrace) {
std::cerr << "Failure from CM-managed buffer/image deletion"
<< std::endl;
}
return PI_INVALID_MEM_OBJECT;
}

// TODO : Erasing should be done during 'piMemRelease'? Or Host has
// to call 'piEnqueueMemUnmap' for all mapped addresses before
// calling 'piMemRelease'?
std::lock_guard<std::mutex> MapLock{Mem->MappingsMutex};
for (auto mapit = Mem->Mappings.begin(); mapit != Mem->Mappings.end();) {
mapit = Mem->Mappings.erase(mapit);
}

assert(MapEntryIt != PiESimdSurfaceMap->end() &&
"Failure from Buffer/Image deletion");
PiESimdSurfaceMap->erase(MapEntryIt);
delete Mem;
}
return PI_SUCCESS;
}

_pi_mem::~_pi_mem() {
int Status = cm_support::CM_FAILURE;

cm_support::CmDevice *CmDevice = Context->Device->CmDevicePtr;

if (SurfacePtr.tag == cm_surface_ptr_t::TypeUserProvidedBuffer) {
Status = CmDevice->DestroyBufferUP(SurfacePtr.UPBufPtr);
} else if (SurfacePtr.tag == cm_surface_ptr_t::TypeRegularBuffer) {
Status = CmDevice->DestroySurface(SurfacePtr.RegularBufPtr);
} else if (SurfacePtr.tag == cm_surface_ptr_t::TypeUserProvidedImage) {
Status = CmDevice->DestroySurface2DUP(SurfacePtr.UPImgPtr);
} else if (SurfacePtr.tag == cm_surface_ptr_t::TypeRegularImage) {
Status = CmDevice->DestroySurface(SurfacePtr.RegularImgPtr);
}

assert(Status == cm_support::CM_SUCCESS &&
"Surface Deletion Failure from CM_EMU");

for (auto mapit = Mappings.begin(); mapit != Mappings.end();) {
mapit = Mappings.erase(mapit);
}
}

cm_support::CM_SURFACE_FORMAT
ConvertPiImageFormatToCmFormat(const pi_image_format *PiFormat) {
using ULongPair = std::pair<unsigned long, unsigned long>;
Expand Down Expand Up @@ -1208,18 +1190,19 @@ pi_result piMemImageCreate(pi_context Context, pi_mem_flags Flags,
}

char *MapBasePtr = nullptr;
cm_image_ptr_slot CmImg;
cm_surface_ptr_t CmImg;
cm_support::SurfaceIndex *CmIndex;
int Status = cm_support::CM_SUCCESS;

if (Flags & PI_MEM_FLAGS_HOST_PTR_USE) {
CmImg.tag = cm_image_ptr_slot::type_user_provided;
CmImg.tag = cm_surface_ptr_t::TypeUserProvidedImage;
Status = Context->Device->CmDevicePtr->CreateSurface2DUP(
static_cast<unsigned int>(ImageDesc->image_width),
static_cast<unsigned int>(ImageDesc->image_height), CmSurfFormat,
HostPtr, CmImg.UPImgPtr);
CmImg.UPImgPtr->GetIndex(CmIndex);
} else {
CmImg.tag = cm_surface_ptr_t::TypeRegularImage;
Status = Context->Device->CmDevicePtr->CreateSurface2D(
static_cast<unsigned int>(ImageDesc->image_width),
static_cast<unsigned int>(ImageDesc->image_height), CmSurfFormat,
Expand Down Expand Up @@ -1495,12 +1478,13 @@ pi_result piEnqueueMemBufferRead(pi_queue Queue, pi_mem Src,
RetEv->IsDummyEvent = true;
}

if (buf->BufferPtr.tag == cm_buffer_ptr_slot::type_user_provided) {
if (buf->SurfacePtr.tag == cm_surface_ptr_t::TypeUserProvidedBuffer) {
// CM does not provide 'ReadSurface' call for 'User-Provided'
// Surface. memcpy is used for BufferRead PI_API call.
memcpy(Dst, buf->MapHostPtr, Size);
} else {
int Status = buf->BufferPtr.RegularBufPtr->ReadSurface(
assert(buf->SurfacePtr.tag == cm_surface_ptr_t::TypeRegularBuffer);
int Status = buf->SurfacePtr.RegularBufPtr->ReadSurface(
reinterpret_cast<unsigned char *>(Dst),
nullptr, // event
static_cast<uint64_t>(Size));
Expand Down Expand Up @@ -1668,12 +1652,13 @@ pi_result piEnqueueMemImageRead(pi_queue CommandQueue, pi_mem Image,
}

size_t Size = RowPitch * (Region->height);
if (PiImg->ImagePtr.tag == cm_image_ptr_slot::type_user_provided) {
if (PiImg->SurfacePtr.tag == cm_surface_ptr_t::TypeUserProvidedImage) {
// CM does not provide 'ReadSurface' call for 'User-Provided'
// Surface. memcpy is used for ImageRead PI_API call.
memcpy(Ptr, PiImg->MapHostPtr, Size);
} else {
int Status = PiImg->ImagePtr.RegularImgPtr->ReadSurface(
assert(PiImg->SurfacePtr.tag == cm_surface_ptr_t::TypeRegularImage);
int Status = PiImg->SurfacePtr.RegularImgPtr->ReadSurface(
reinterpret_cast<unsigned char *>(Ptr),
nullptr, // event
static_cast<uint64_t>(Size));
Expand Down Expand Up @@ -1930,43 +1915,9 @@ pi_result piTearDown(void *) {

for (auto it = PiESimdSurfaceMap->begin(); it != PiESimdSurfaceMap->end();) {
auto Mem = it->second;
if (Mem == nullptr) {
/// Skipping map entry for SLM_BTI
it = PiESimdSurfaceMap->erase(it);
continue;
}
int Status = cm_support::CM_FAILURE;

if (Mem->getMemType() == PI_MEM_TYPE_BUFFER) {
_pi_buffer *PiBuf = static_cast<_pi_buffer *>(Mem);
if (PiBuf->BufferPtr.tag == cm_buffer_ptr_slot::type_user_provided) {
Status = Mem->Context->Device->CmDevicePtr->DestroyBufferUP(
PiBuf->BufferPtr.UPBufPtr);
} else {
Status = Mem->Context->Device->CmDevicePtr->DestroySurface(
PiBuf->BufferPtr.RegularBufPtr);
}
} else if (Mem->getMemType() == PI_MEM_TYPE_IMAGE2D) {
_pi_image *PiImg = static_cast<_pi_image *>(Mem);
if (PiImg->ImagePtr.tag == cm_image_ptr_slot::type_user_provided) {
Status = Mem->Context->Device->CmDevicePtr->DestroySurface2DUP(
PiImg->ImagePtr.UPImgPtr);
} else {
Status = Mem->Context->Device->CmDevicePtr->DestroySurface(
PiImg->ImagePtr.RegularImgPtr);
}
}

if (Status != cm_support::CM_SUCCESS) {
return PI_INVALID_MEM_OBJECT;
}

// No "MappingsMutex" as piTearDown is guaranteed to be called
// from single thread for plug-in
for (auto mapit = Mem->Mappings.begin(); mapit != Mem->Mappings.end();) {
mapit = Mem->Mappings.erase(mapit);
}

if (Mem != nullptr) {
delete Mem;
} // else { /* Null-entry for SLM_BTI */ }
it = PiESimdSurfaceMap->erase(it);
}
return PI_SUCCESS;
Expand Down
81 changes: 35 additions & 46 deletions sycl/plugins/esimd_emulator/pi_esimd_emulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ struct _pi_object {
_pi_object() : RefCount{1} {}

std::atomic<pi_uint32> RefCount;

virtual ~_pi_object() = default;
};
struct _pi_platform {
_pi_platform() = default;
Expand Down Expand Up @@ -105,9 +107,28 @@ struct _pi_queue : _pi_object {
cm_support::CmQueue *CmQueuePtr = nullptr;
};

struct _pi_mem : _pi_object {
_pi_mem() = default;
struct cm_surface_ptr_t {
Copy link
Contributor

@kbobrovs kbobrovs Apr 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add later comments what is this structure for.

// 'UP' means 'User-Provided' in CM Lib - corresponding to
// Buffer/Image created with PI_MEM_FLAGS_HOST_PTR_USE option in
// SYCL
enum SurfaceType {
TypeNone,
TypeRegularBuffer,
TypeUserProvidedBuffer,
TypeRegularImage,
TypeUserProvidedImage
};
SurfaceType tag = TypeNone;

union {
cm_support::CmBuffer *RegularBufPtr = nullptr;
cm_support::CmBufferUP *UPBufPtr;
cm_support::CmSurface2D *RegularImgPtr;
cm_support::CmSurface2DUP *UPImgPtr;
};
};

struct _pi_mem : _pi_object {
pi_context Context;

// To be used for piEnqueueMemBufferMap
Expand Down Expand Up @@ -135,67 +156,35 @@ struct _pi_mem : _pi_object {
// Supporing multi-threaded mapping/unmapping calls
std::mutex MappingsMutex;

_pi_mem_type getMemType() const { return MemType; };
cm_surface_ptr_t SurfacePtr;

// Destructor for invoking buffer/image destory calls in CM Runtime
~_pi_mem();

protected:
_pi_mem(pi_context ctxt, char *HostPtr, _pi_mem_type MemTypeArg,
_pi_mem(pi_context ctxt, char *HostPtr, cm_surface_ptr_t SurfacePtrArg,
unsigned int SurfaceIdxArg)
: Context{ctxt}, MapHostPtr{HostPtr},
SurfaceIndex{SurfaceIdxArg}, MemType{MemTypeArg} {}

private:
_pi_mem_type MemType;
};

// TODO: Merge cm_buffer_ptr_slot and cm_image_ptr_slot into one
// struct
struct cm_buffer_ptr_slot {
// 'UP' means 'User-Provided' in CM Lib - corresponding to
// Host-created buffer in SYCL

enum type { type_none, type_regular, type_user_provided };
type tag = type_none;

union {
cm_support::CmBuffer *RegularBufPtr = nullptr;
cm_support::CmBufferUP *UPBufPtr;
};
};

struct cm_image_ptr_slot {
// 'UP' means 'User-Provided' in CM Lib - corresponding to
// Host-created image in SYCL

enum type { type_none, type_regular, type_user_provided };
type tag = type_none;

union {
cm_support::CmSurface2D *RegularImgPtr = nullptr;
cm_support::CmSurface2DUP *UPImgPtr;
};
: Context{ctxt}, MapHostPtr{HostPtr}, SurfaceIndex{SurfaceIdxArg},
SurfacePtr{SurfacePtrArg} {}
};

struct _pi_buffer final : _pi_mem {
// Buffer/Sub-buffer constructor
_pi_buffer(pi_context ctxt, char *HostPtr, cm_buffer_ptr_slot BufferPtrArg,
_pi_buffer(pi_context ctxt, char *HostPtr, cm_surface_ptr_t SurfacePtrArg,
unsigned int SurfaceIdxArg, size_t SizeArg)
: _pi_mem(ctxt, HostPtr, PI_MEM_TYPE_BUFFER, SurfaceIdxArg),
BufferPtr{BufferPtrArg}, Size{SizeArg} {}
: _pi_mem(ctxt, HostPtr, SurfacePtrArg, SurfaceIdxArg), Size{SizeArg} {}

cm_buffer_ptr_slot BufferPtr;
size_t Size;
};

struct _pi_image final : _pi_mem {
// Image constructor
_pi_image(pi_context ctxt, char *HostPtr, cm_image_ptr_slot ImagePtrArg,
_pi_image(pi_context ctxt, char *HostPtr, cm_surface_ptr_t SurfacePtrArg,
unsigned int SurfaceIdxArg, size_t WidthArg, size_t HeightArg,
size_t BPPArg)
: _pi_mem(ctxt, HostPtr, PI_MEM_TYPE_IMAGE2D, SurfaceIdxArg),
ImagePtr(ImagePtrArg), Width{WidthArg}, Height{HeightArg},
BytesPerPixel{BPPArg} {}
: _pi_mem(ctxt, HostPtr, SurfacePtrArg, SurfaceIdxArg), Width{WidthArg},
Height{HeightArg}, BytesPerPixel{BPPArg} {}

cm_image_ptr_slot ImagePtr;
size_t Width;
size_t Height;
size_t BytesPerPixel;
Expand Down