diff --git a/rocclr/runtime/device/device.hpp b/rocclr/runtime/device/device.hpp index ed23f9979c..db4fdd2229 100644 --- a/rocclr/runtime/device/device.hpp +++ b/rocclr/runtime/device/device.hpp @@ -1450,6 +1450,7 @@ public: /// Optional extensions virtual void submitSignal(amd::SignalCommand & cmd) = 0; virtual void submitMakeBuffersResident(amd::MakeBuffersResidentCommand & cmd) = 0; + virtual void submitWriteBufferFromFile(amd::WriteBufferFromFileCommand& cmd) { ShouldNotReachHere(); } //! Get the blit manager object device::BlitManager& blitMgr() const { return *blitMgr_; } diff --git a/rocclr/runtime/device/gpu/gpuresource.cpp b/rocclr/runtime/device/gpu/gpuresource.cpp index b9b47eef54..155ed575ba 100644 --- a/rocclr/runtime/device/gpu/gpuresource.cpp +++ b/rocclr/runtime/device/gpu/gpuresource.cpp @@ -445,6 +445,7 @@ Resource::create(MemoryType memType, CreateParams* params) desc.mipLevels = cal()->mipLevels_; desc.systemMemory = NULL; + uint allocAttempt = 0; do { // Find a type for allocation if (memoryType() == Persistent) { @@ -515,7 +516,8 @@ Resource::create(MemoryType memType, CreateParams* params) if (memoryType() == Local) { cal_.type_ = Persistent; } - else if (memoryType() == Persistent) { + // Don't switch to USWC if persistent memory was explicitly asked + else if ((allocAttempt > 0) && (memoryType() == Persistent)) { cal_.type_ = RemoteUSWC; } // Remote cacheable to uncacheable @@ -525,6 +527,7 @@ Resource::create(MemoryType memType, CreateParams* params) else { break; } + allocAttempt++; } } while (!calRes); diff --git a/rocclr/runtime/device/gpu/gpuvirtual.cpp b/rocclr/runtime/device/gpu/gpuvirtual.cpp index 68e5628454..680eee3404 100644 --- a/rocclr/runtime/device/gpu/gpuvirtual.cpp +++ b/rocclr/runtime/device/gpu/gpuvirtual.cpp @@ -3491,4 +3491,30 @@ VirtualGPU::assignDebugTrapHandler(const DebugToolInfo& dbgSetting, } +void +VirtualGPU::submitWriteBufferFromFile(amd::WriteBufferFromFileCommand& cmd) +{ + size_t copySize = cmd.size()[0]; + size_t fileOffset = cmd.fileOffset(); + size_t dstOffset = cmd.origin()[0]; + Memory* mem = dev().getGpuMemory(&cmd.memory()); + uint idx = 0; + while (copySize > 0) { + Memory* staging = dev().getGpuMemory(&cmd.staging(idx)); + size_t dstSize = amd::WriteBufferFromFileCommand::StagingBufferSize; + dstSize = std::min(dstSize, copySize); + void* dstBuffer = staging->cpuMap(*this); + if (!cmd.file()->readBlock(dstBuffer, fileOffset, 0, dstSize)) { + return; + } + staging->cpuUnmap(*this); + + bool result = blitMgr().copyBuffer(*staging, *mem, + fileOffset, dstOffset, dstSize, false); + flushDMA(getGpuEvent(staging->gslResource())->engineId_); + dstOffset += dstSize; + copySize -= dstSize; + } +} + } // namespace gpu diff --git a/rocclr/runtime/device/gpu/gpuvirtual.hpp b/rocclr/runtime/device/gpu/gpuvirtual.hpp index a2964d24c5..1aabaf5f04 100644 --- a/rocclr/runtime/device/gpu/gpuvirtual.hpp +++ b/rocclr/runtime/device/gpu/gpuvirtual.hpp @@ -243,6 +243,7 @@ public: virtual void submitSvmFillMemory(amd::SvmFillMemoryCommand& cmd); virtual void submitSvmMapMemory(amd::SvmMapMemoryCommand& cmd); virtual void submitSvmUnmapMemory(amd::SvmUnmapMemoryCommand& cmd); + virtual void submitWriteBufferFromFile(amd::WriteBufferFromFileCommand& cmd); void releaseMemory(gslMemObject gslResource, bool wait = true); void releaseKernel(CALimage calImage); diff --git a/rocclr/runtime/platform/command.cpp b/rocclr/runtime/platform/command.cpp index 217b46ea69..6a250dffc1 100644 --- a/rocclr/runtime/platform/command.cpp +++ b/rocclr/runtime/platform/command.cpp @@ -573,27 +573,61 @@ ThreadTraceMemObjectsCommand::validateMemory() return true; } +void +WriteBufferFromFileCommand::releaseResources() +{ + for (uint i = 0; i < NumStagingBuffers; ++i) { + if (NULL != staging_[i]) { + staging_[i]->release(); + } + } + + // Call the parent + OneMemoryArgCommand::releaseResources(); +} + void WriteBufferFromFileCommand::submit(device::VirtualDevice& device) { device::Memory* mem = memory_->getDeviceMemory(queue()->device()); - void* dstBuffer = mem->cpuMap(device); - // Make HD transfer to the host accessible memory - if (!file()->readBlock(dstBuffer, fileOffset(), origin()[0], size()[0])) { - return; + if (memory_->getMemFlags() & (CL_MEM_USE_HOST_PTR | + CL_MEM_ALLOC_HOST_PTR | CL_MEM_USE_PERSISTENT_MEM_AMD)) { + void* dstBuffer = mem->cpuMap(device); + // Make HD transfer to the host accessible memory + if (!file()->readBlock(dstBuffer, fileOffset(), origin()[0], size()[0])) { + return; + } + mem->cpuUnmap(device); + } + else { + device.submitWriteBufferFromFile(*this); } - mem->cpuUnmap(device); } bool WriteBufferFromFileCommand::validateMemory() { - if (!(memory_->getMemFlags() & (CL_MEM_USE_HOST_PTR | - CL_MEM_ALLOC_HOST_PTR | CL_MEM_USE_PERSISTENT_MEM_AMD))) { - return false; - } - if (queue()->device().info().type_ & CL_DEVICE_TYPE_GPU) { + // Check if the destination buffer has direct host access + if (!(memory_->getMemFlags() & (CL_MEM_USE_HOST_PTR | + CL_MEM_ALLOC_HOST_PTR | CL_MEM_USE_PERSISTENT_MEM_AMD))) { + // Allocate staging buffers + for (uint i = 0; i < NumStagingBuffers; ++i) { + staging_[i] = new (memory_->getContext()) + Buffer(memory_->getContext(), + StagingBufferMemType, StagingBufferSize); + if (NULL == staging_[i] || !staging_[i]->create(nullptr)) { + return false; + } + device::Memory* mem = staging_[i]->getDeviceMemory(queue()->device()); + if (NULL == mem) { + LogPrintfError("Can't allocate staging buffer - 0x%08X bytes!", + staging_[i]->getSize()); + return false; + } + } + } + device::Memory* mem = memory_->getDeviceMemory(queue()->device()); if (NULL == mem) { LogPrintfError("Can't allocate memory size - 0x%08X bytes!", diff --git a/rocclr/runtime/platform/command.hpp b/rocclr/runtime/platform/command.hpp index 4e9a6bd0ef..3ae4d4c379 100644 --- a/rocclr/runtime/platform/command.hpp +++ b/rocclr/runtime/platform/command.hpp @@ -1303,8 +1303,6 @@ public: pfnFreeFunc_(pfnFreeFunc), userData_(userData) { } - virtual void releaseResources() { Command::releaseResources(); } - virtual void submit(device::VirtualDevice& device) { device.submitSvmFreeMemory(*this); @@ -1338,8 +1336,6 @@ public: src_(src), srcSize_(srcSize) { } - virtual void releaseResources() { Command::releaseResources(); } - virtual void submit(device::VirtualDevice& device) { device.submitSvmCopyMemory(*this); @@ -1382,8 +1378,6 @@ public: memcpy(pattern_, pattern, patternSize); } - virtual void releaseResources() { Command::releaseResources(); } - virtual void submit(device::VirtualDevice& device) { device.submitSvmFillMemory(*this); @@ -1425,8 +1419,6 @@ public: { } - virtual void releaseResources() { Command::releaseResources(); } - virtual void submit(device::VirtualDevice& device) { device.submitSvmMapMemory(*this); @@ -1459,8 +1451,6 @@ public: svmMem_(svmMem) {} - virtual void releaseResources() { Command::releaseResources(); } - virtual void submit(device::VirtualDevice& device) { device.submitSvmUnmapMemory(*this); @@ -1477,11 +1467,17 @@ public: */ class WriteBufferFromFileCommand : public OneMemoryArgCommand { +public: + static const uint NumStagingBuffers = 2; + static const size_t StagingBufferSize = 4 * Mi; + static const uint StagingBufferMemType = CL_MEM_USE_PERSISTENT_MEM_AMD; + private: const Coord3D origin_; //!< Origin of the region to write to const Coord3D size_; //!< Size of the region to write to LiquidFlashFile* file_; //!< The file object for data read size_t fileOffset_; //!< Offset in the file for data read + amd::Memory* staging_[NumStagingBuffers]; //!< Staging buffers for transfer public: WriteBufferFromFileCommand( @@ -1498,8 +1494,13 @@ public: { // Sanity checks assert(size.c[0] > 0 && "invalid"); + for (uint i = 0; i < NumStagingBuffers; ++i) { + staging_[i] = NULL; + } } + virtual void releaseResources(); + virtual void submit(device::VirtualDevice& device); //! Return the memory object to write to @@ -1516,6 +1517,9 @@ public: //! Return the region size const Coord3D& size() const { return size_; } + //! Return the staging buffer for transfer + Memory& staging(uint i) const { return *staging_[i]; } + bool validateMemory(); };