diff --git a/projects/clr/rocclr/device/rocm/rocblit.cpp b/projects/clr/rocclr/device/rocm/rocblit.cpp index b1842c4f5b..314f4732d1 100644 --- a/projects/clr/rocclr/device/rocm/rocblit.cpp +++ b/projects/clr/rocclr/device/rocm/rocblit.cpp @@ -1035,7 +1035,6 @@ bool KernelBlitManager::copyBufferToImageKernel(device::Memory& srcMemory, bool rejected = false; Memory* dstView = &gpuMem(dstMemory); - bool releaseView = false; bool result = false; amd::Image* dstImage = static_cast(dstMemory.owner()); amd::Image* srcImage = static_cast(srcMemory.owner()); @@ -1068,7 +1067,6 @@ bool KernelBlitManager::copyBufferToImageKernel(device::Memory& srcMemory, dstView = createView(gpuMem(dstMemory), newFormat, CL_MEM_WRITE_ONLY); if (dstView != nullptr) { rejected = false; - releaseView = true; } } @@ -1164,11 +1162,6 @@ bool KernelBlitManager::copyBufferToImageKernel(device::Memory& srcMemory, address parameters = captureArguments(kernels_[blitType]); result = gpu().submitKernelInternal(ndrange, *kernels_[blitType], parameters, nullptr); releaseArguments(parameters); - if (releaseView) { - // todo SRD programming could be changed to avoid a stall - gpu().releaseGpuMemoryFence(); - dstView->owner()->release(); - } return result; } @@ -1235,7 +1228,6 @@ bool KernelBlitManager::copyImageToBufferKernel(device::Memory& srcMemory, bool rejected = false; Memory* srcView = &gpuMem(srcMemory); - bool releaseView = false; bool result = false; amd::Image* srcImage = static_cast(srcMemory.owner()); amd::Image::Format newFormat(srcImage->getImageFormat()); @@ -1267,7 +1259,6 @@ bool KernelBlitManager::copyImageToBufferKernel(device::Memory& srcMemory, srcView = createView(gpuMem(srcMemory), newFormat, CL_MEM_READ_ONLY); if (srcView != nullptr) { rejected = false; - releaseView = true; } } @@ -1369,11 +1360,6 @@ bool KernelBlitManager::copyImageToBufferKernel(device::Memory& srcMemory, address parameters = captureArguments(kernels_[blitType]); result = gpu().submitKernelInternal(ndrange, *kernels_[blitType], parameters, nullptr); releaseArguments(parameters); - if (releaseView) { - // todo SRD programming could be changed to avoid a stall - gpu().releaseGpuMemoryFence(); - srcView->owner()->release(); - } return result; } @@ -1395,7 +1381,6 @@ bool KernelBlitManager::copyImage(device::Memory& srcMemory, device::Memory& dst amd::Image::Format srcFormat(srcImage->getImageFormat()); amd::Image::Format dstFormat(dstImage->getImageFormat()); bool srcRejected = false, dstRejected = false; - bool srcReleaseView = false, dstReleaseView = false; // Find unsupported source formats for (uint i = 0; i < RejectedFormatDataTotal; ++i) { if (RejectedData[i].clOldType_ == srcFormat.image_channel_data_type) { @@ -1449,7 +1434,6 @@ bool KernelBlitManager::copyImage(device::Memory& srcMemory, device::Memory& dst srcView = createView(gpuMem(srcMemory), srcFormat, CL_MEM_READ_ONLY); if (srcView != nullptr) { srcRejected = false; - srcReleaseView = true; } } @@ -1457,7 +1441,6 @@ bool KernelBlitManager::copyImage(device::Memory& srcMemory, device::Memory& dst dstView = createView(gpuMem(dstMemory), dstFormat, CL_MEM_WRITE_ONLY); if (dstView != nullptr) { dstRejected = false; - dstReleaseView = true; } } @@ -1465,14 +1448,6 @@ bool KernelBlitManager::copyImage(device::Memory& srcMemory, device::Memory& dst if (srcRejected || dstRejected) { result = DmaBlitManager::copyImage(srcMemory, dstMemory, srcOrigin, dstOrigin, size, entire, copyMetadata); - if (srcReleaseView) { - gpu().releaseGpuMemoryFence(); - srcView->owner()->release(); - } - if (dstReleaseView) { - gpu().releaseGpuMemoryFence(); - dstView->owner()->release(); - } synchronize(); } @@ -1543,16 +1518,6 @@ bool KernelBlitManager::copyImage(device::Memory& srcMemory, device::Memory& dst result = gpu().submitKernelInternal(ndrange, *kernels_[blitType], parameters, nullptr); releaseArguments(parameters); - if (srcReleaseView) { - // todo SRD programming could be changed to avoid a stall - gpu().releaseGpuMemoryFence(); - srcView->owner()->release(); - } - if (dstReleaseView) { - // todo SRD programming could be changed to avoid a stall - gpu().releaseGpuMemoryFence(); - dstView->owner()->release(); - } synchronize(); return result; @@ -2409,7 +2374,6 @@ bool KernelBlitManager::fillImage(device::Memory& memory, const void* pattern, uint32_t iFillColor[4]; bool rejected = false; - bool releaseView = false; // For depth, we need to create a view if (newFormat.image_channel_order == CL_sRGBA) { @@ -2445,7 +2409,6 @@ bool KernelBlitManager::fillImage(device::Memory& memory, const void* pattern, memView = createView(gpuMem(memory), newFormat, CL_MEM_WRITE_ONLY); if (memView != nullptr) { rejected = false; - releaseView = true; } } @@ -2536,11 +2499,6 @@ bool KernelBlitManager::fillImage(device::Memory& memory, const void* pattern, address parameters = captureArguments(kernels_[fillType]); result = gpu().submitKernelInternal(ndrange, *kernels_[fillType], parameters, nullptr); releaseArguments(parameters); - if (releaseView) { - // todo SRD programming could be changed to avoid a stall - gpu().releaseGpuMemoryFence(); - memView->owner()->release(); - } synchronize(); @@ -2706,31 +2664,22 @@ Memory* KernelBlitManager::createView(const Memory& parent, cl_image_format form cl_mem_flags flags) const { assert((parent.owner()->asBuffer() == nullptr) && "View supports images only"); amd::Image* parentImage = static_cast(parent.owner()); - amd::Image* image = - parentImage->createView(parent.owner()->getContext(), format, &gpu(), 0, flags); - + auto parent_dev_image = static_cast(parentImage->getDeviceMemory(dev())); + amd::Image* image = parent_dev_image->FindView(format); if (image == nullptr) { - LogError("[OCL] Fail to allocate view of image object"); - return nullptr; + image = parentImage->createView(parent.owner()->getContext(), format, &gpu(), 0, flags); + if (image == nullptr) { + LogError("[OCL] Fail to allocate view of image object"); + return nullptr; + } + if (!parent_dev_image->AddView(image)) { + // Another thread already added a view + image->release(); + image = parent_dev_image->FindView(format); + } } - - Image* devImage = new roc::Image(dev(), *image); - if (devImage == nullptr) { - LogError("[OCL] Fail to allocate device mem object for the view"); - image->release(); - return nullptr; - } - - if (!devImage->createView(parent)) { - LogError("[OCL] Fail to create device mem object for the view"); - delete devImage; - image->release(); - return nullptr; - } - - image->replaceDeviceMemory(&dev_, devImage); - - return devImage; + auto dev_image = static_cast(image->getDeviceMemory(dev())); + return dev_image; } address KernelBlitManager::captureArguments(const amd::Kernel* kernel) const { diff --git a/projects/clr/rocclr/device/rocm/rocmemory.cpp b/projects/clr/rocclr/device/rocm/rocmemory.cpp index 3dea4c45bd..3b05a28a31 100644 --- a/projects/clr/rocclr/device/rocm/rocmemory.cpp +++ b/projects/clr/rocclr/device/rocm/rocmemory.cpp @@ -1430,7 +1430,12 @@ void* Image::allocMapTarget(const amd::Coord3D& origin, const amd::Coord3D& regi Image::~Image() { destroy(); } +// ================================================================================================ void Image::destroy() { + for (auto it : view_cache_) { + it->release(); + } + delete copyImageBuffer_; if (hsaImageObject_.handle != 0) { @@ -1462,6 +1467,7 @@ void Image::destroy() { } } +// ================================================================================================ bool Image::ValidateMemory() { amd::Image* img = owner()->asImage(); // Create a native image without pitch for validation @@ -1477,5 +1483,34 @@ bool Image::ValidateMemory() { } } +// ================================================================================================ +bool Image::AddView(amd::Image* image) { + amd::ScopedLock l(owner()->lockMemoryOps()); + for (auto it : view_cache_) { + if ((it->getImageFormat().image_channel_data_type == + image->getImageFormat().image_channel_data_type) && + (it->getImageFormat().image_channel_order == + image->getImageFormat().image_channel_order)) { + return false; + } + } + view_cache_.push_back(image); + // Remove parent dependency on the child, since cache will be destroyed within the parent + owner()->release(); + return true; +} + +// ================================================================================================ +amd::Image* Image::FindView(cl_image_format format) const { + amd::ScopedLock l(owner()->lockMemoryOps()); + for (auto it : view_cache_) { + if ((it->getImageFormat().image_channel_data_type == format.image_channel_data_type) && + (it->getImageFormat().image_channel_order == format.image_channel_order)) { + return it; + } + } + return nullptr; +} + } #endif // WITHOUT_HSA_BACKEND diff --git a/projects/clr/rocclr/device/rocm/rocmemory.hpp b/projects/clr/rocclr/device/rocm/rocmemory.hpp index 069499f641..92ec7529d6 100644 --- a/projects/clr/rocclr/device/rocm/rocmemory.hpp +++ b/projects/clr/rocclr/device/rocm/rocmemory.hpp @@ -224,6 +224,13 @@ class Image : public roc::Memory { amd::Image* CopyImageBuffer() const { return copyImageBuffer_; } virtual uint64_t originalDeviceAddress() const { return reinterpret_cast(originalDeviceMemory_); } + + //! Adds an image view to the view cache for the fast blit manager operations + bool AddView(amd::Image* image); + + //! Finds an image view of this original image from the cache + amd::Image* FindView(cl_image_format format) const; + private: //! Disable copy constructor Image(const Buffer&); @@ -246,6 +253,7 @@ class Image : public roc::Memory { void* originalDeviceMemory_; amd::Image* copyImageBuffer_ = nullptr; + std::vector view_cache_; //!< Cache of views for fast access }; } #endif