diff --git a/projects/rocr-runtime/runtime/hsa-runtime/core/inc/amd_blit_sdma.h b/projects/rocr-runtime/runtime/hsa-runtime/core/inc/amd_blit_sdma.h index a4feabc900..95c652afb9 100644 --- a/projects/rocr-runtime/runtime/hsa-runtime/core/inc/amd_blit_sdma.h +++ b/projects/rocr-runtime/runtime/hsa-runtime/core/inc/amd_blit_sdma.h @@ -309,6 +309,9 @@ class BlitSdma : public BlitSdmaBase { /// True if SDMA blit is ganged bool is_ganged_; + + /// Minimum submission size in bytes. + size_t min_submission_size_; }; // Ring indices are 32-bit. diff --git a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/amd_blit_sdma.cpp b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/amd_blit_sdma.cpp index 23ae0b3069..830cb98929 100644 --- a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/amd_blit_sdma.cpp +++ b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/amd_blit_sdma.cpp @@ -121,7 +121,8 @@ BlitSdma::BlitSdma() cached_reserve_index_(0), cached_commit_index_(0), platform_atomic_support_(true), - hdp_flush_support_(false) { + hdp_flush_support_(false), + min_submission_size_(0) { std::memset(&queue_resource_, 0, sizeof(queue_resource_)); } @@ -147,6 +148,13 @@ hsa_status_t BlitSdma: return HSA_STATUS_ERROR; } + // Some GFX9 devices require a minimum of 64 DWORDS per ring buffer submission. + if (agent_->isa()->GetVersion() >= core::Isa::Version(9, 0, 0) && + (agent_->isa()->GetVersion() <= core::Isa::Version(9, 0, 4) || + agent_->isa()->GetVersion() == core::Isa::Version(9, 0, 12))) { + min_submission_size_ = 256; + } + const core::Runtime::LinkInfo& link = core::Runtime::runtime_singleton_->GetLinkInfo( agent_->node_id(), core::Runtime::runtime_singleton_->cpu_agents()[0]->node_id()); if (agent_->isa()->GetVersion() == core::Isa::Version(7, 0, 1)) { @@ -322,13 +330,15 @@ hsa_status_t BlitSdma: const uint32_t total_command_size = total_poll_command_size + cmd_size + sync_command_size + total_timestamp_command_size + interrupt_command_size + flush_cmd_size + total_gang_command_size; + const uint32_t pad_size = total_command_size < min_submission_size_ ? + min_submission_size_ - total_command_size : 0; RingIndexTy curr_index; char* command_addr; uint64_t prior_bytes, post_bytes; { std::lock_guard lock(reservation_lock_); - command_addr = AcquireWriteAddress(total_command_size, curr_index); + command_addr = AcquireWriteAddress(total_command_size + pad_size, curr_index); if (command_addr == nullptr) { return HSA_STATUS_ERROR_OUT_OF_RESOURCES; } @@ -463,7 +473,16 @@ hsa_status_t BlitSdma: wrapped_index += trap_command_size_; } - ReleaseWriteAddress(curr_index, total_command_size); + // Pad size is DWORD aligned since all commands are dword aligned. + // Insert NOP header DWORD with value of the number of null DWORDs shifted + // by 16 bits to pad total submission. + if (pad_size) { + memset(command_addr, 0, pad_size); + uint32_t *dword_command_addr = reinterpret_cast(command_addr); + dword_command_addr[total_command_size/4] = (pad_size/4 - 1) << 16; + } + + ReleaseWriteAddress(curr_index, total_command_size + pad_size); return HSA_STATUS_SUCCESS; }