P4 to Git Change 1531829 by gandryey@gera-w8 on 2018/03/23 18:34:36

SWDEV-79445 - OCL generic changes and code clean-up
	- Implement ConstantBuffer management through a single managed buffer. It reduces the amount of allocated buffers on GPU

Affected files ...

... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palconstbuf.cpp#6 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palconstbuf.hpp#5 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palkernel.cpp#48 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palvirtual.cpp#79 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palvirtual.hpp#44 edit
This commit is contained in:
foreman
2018-03-23 18:41:23 -04:00
parent 1d513806a5
commit 73b44b613b
5 changed files with 129 additions and 69 deletions
+45 -26
View File
@@ -16,7 +16,6 @@ ManagedBuffer::ManagedBuffer(VirtualGPU& gpu, uint32_t size)
, activeBuffer_(0)
, size_(size)
, wrtOffset_(0)
, lastWrtSize_(0)
, wrtAddress_(nullptr) {}
// ================================================================================================
@@ -27,23 +26,10 @@ ManagedBuffer::~ManagedBuffer() {
}
delete it;
}
amd::AlignedMemory::deallocate(sysMemCopy_);
}
// ================================================================================================
bool ManagedBuffer::create(Resource::MemoryType type, bool constbuf) {
if (constbuf) {
// Create sysmem copy for the constant buffer.
// Allocate extra memory to account the internal arguments
sysMemCopy_ = reinterpret_cast<address>(amd::AlignedMemory::allocate(
2 * gpu_.dev().info().maxParameterSize_, 256));
if (sysMemCopy_ == nullptr) {
LogPrintfError("We couldn't allocate sysmem copy for constant buffer, size(%d)!", size_);
return false;
}
memset(sysMemCopy_, 0, gpu_.dev().info().maxParameterSize_);
}
bool ManagedBuffer::create(Resource::MemoryType type) {
for (uint i = 0; i < buffers_.size(); ++i) {
buffers_[i] = new Memory(const_cast<pal::Device&>(gpu_.dev()), size_);
if (nullptr == buffers_[i] || !buffers_[i]->create(type)) {
@@ -66,14 +52,13 @@ bool ManagedBuffer::create(Resource::MemoryType type, bool constbuf) {
}
// ================================================================================================
bool ManagedBuffer::uploadDataToHw(uint32_t size) {
static constexpr uint32_t HwCbAlignment = 256;
address ManagedBuffer::reserve(uint32_t size, uint64_t* gpu_address) {
static constexpr uint32_t MemAlignment = 256;
// Align copy size on the vector's boundary
uint32_t count = amd::alignUp(size, 16);
wrtOffset_ += lastWrtSize_;
// Align reserve size on the vector's boundary
uint32_t count = amd::alignUp(size, MemAlignment);
// Check if CB has enough space for copy
// Check if buffer has enough space for reservation
if ((wrtOffset_ + count) > size_) {
// Get the next buffer in the list
++activeBuffer_;
@@ -82,15 +67,49 @@ bool ManagedBuffer::uploadDataToHw(uint32_t size) {
buffers_[activeBuffer_]->wait(gpu_);
wrtAddress_ = buffers_[activeBuffer_]->data();
wrtOffset_ = 0;
lastWrtSize_ = 0;
}
// Update memory with new CB data
memcpy((reinterpret_cast<char*>(wrtAddress_) + wrtOffset_), sysMemCopy_, count);
*gpu_address = buffers_[activeBuffer_]->vmAddress() + wrtOffset_;
address cpu_address = wrtAddress_ + wrtOffset_;
// Adjust the offset by the reserved size
wrtOffset_ += count;
// Adjust the size by the HW CB buffer alignment
lastWrtSize_ = amd::alignUp(size, HwCbAlignment);
return cpu_address;
}
// ================================================================================================
ConstantBuffer::ConstantBuffer(ManagedBuffer& mbuf, uint32_t size)
: mbuf_(mbuf)
, sys_mem_copy_(nullptr)
, size_(size)
{}
// ================================================================================================
ConstantBuffer::~ConstantBuffer() {
amd::AlignedMemory::deallocate(sys_mem_copy_);
}
// ================================================================================================
bool ConstantBuffer::Create() {
// Create sysmem copy for the constant buffer.
sys_mem_copy_ = reinterpret_cast<address>(amd::AlignedMemory::allocate(size_, 256));
if (sys_mem_copy_ == nullptr) {
LogPrintfError("We couldn't allocate sysmem copy for constant buffer, size(%d)!", size_);
return false;
}
memset(sys_mem_copy_, 0, size_);
return true;
}
// ================================================================================================
uint64_t ConstantBuffer::UploadDataToHw(uint32_t size) const
{
uint64_t vm_address;
address cpu_address = mbuf_.reserve(size, &vm_address);
// Update memory with new CB data
memcpy(cpu_address, sys_mem_copy_, size);
return vm_address;
}
} // namespace pal
+45 -13
View File
@@ -20,27 +20,22 @@ class ManagedBuffer : public amd::HeapObject {
~ManagedBuffer();
//! Creates the real HW constant buffer
bool create(Resource::MemoryType type, bool constBuf = false);
bool create(Resource::MemoryType type);
/*! \brief Uploads current constant buffer data from sysMemCopy_ to HW
*
* \return True if the data upload was succesful
*/
bool uploadDataToHw(uint32_t size //!< real data size for upload
);
//! Returns a pointer to the system memory copy for CB
address sysMemCopy() const { return sysMemCopy_; }
address reserve(uint32_t size, //!< real data size for upload
uint64_t* gpu_address);
//! Returns CB size
uint32_t size() const { return size_; }
//! Returns current write offset for the constant buffer
//! Returns current write offset for the managed buffer
uint32_t wrtOffset() const { return wrtOffset_; }
//! Returns last write size for the constant buffer
uint32_t lastWrtSize() const { return lastWrtSize_; }
//! Returns active GPU buffer
Memory* activeMemory() const { return buffers_[activeBuffer_]; }
uint64_t vmAddress() const { return buffers_[activeBuffer_]->vmAddress(); }
@@ -58,11 +53,48 @@ class ManagedBuffer : public amd::HeapObject {
VirtualGPU& gpu_; //!< Virtual GPU object
std::vector<Memory*> buffers_; //!< Buffers for management
uint32_t activeBuffer_; //!< Current active buffer
address sysMemCopy_; //!< System memory copy
uint32_t size_; //!< Constant buffer size
uint32_t wrtOffset_; //!< Current write offset
uint32_t lastWrtSize_; //!< Last write size
void* wrtAddress_; //!< Write address in CB
address wrtAddress_; //!< Write address in CB
};
//! Constant buffer
class ConstantBuffer : public amd::HeapObject {
public:
//! Constructor for the ConstBuffer class
ConstantBuffer(ManagedBuffer& mbuf, //!< Managed buffer
uint32_t size
);
//! Destructor for the ConstBuffer class
~ConstantBuffer();
//! Creates the real HW constant buffer
bool Create();
/*! \brief Uploads current constant buffer data from sysMemCopy_ to HW
*
* \return GPU address for the uploaded data
*/
uint64_t UploadDataToHw(uint32_t size //!< real data size for upload
) const;
//! Returns a pointer to the system memory copy for CB
address SysMemCopy(uint32_t size = 0) const { return sys_mem_copy_; }
//! Returns active GPU buffer
Memory* ActiveMemory() const { return mbuf_.activeMemory(); }
private:
//! Disable copy constructor
ConstantBuffer(const ConstantBuffer&) = delete;
//! Disable operator=
ConstantBuffer& operator=(const ConstantBuffer&) = delete;
ManagedBuffer& mbuf_; //!< Managed buffer on GPU
address sys_mem_copy_; //!< System memory copy
uint32_t size_; //!< Constant buffer size
};
/*@}*/} // namespace pal
+18 -21
View File
@@ -920,8 +920,8 @@ hsa_kernel_dispatch_packet_t* HSAILKernel::loadArguments(
const_address parameters, bool nativeMem, uint64_t vmDefQueue, uint64_t* vmParentWrap) const {
static const bool WaitOnBusyEngine = true;
uint64_t ldsAddress = ldsSize();
address aqlArgBuf = gpu.cb(0)->sysMemCopy();
address aqlStruct = gpu.cb(1)->sysMemCopy();
address aqlArgBuf = gpu.cb(0)->SysMemCopy();
address aqlStruct = gpu.cb(1)->SysMemCopy();
bool srdResource = false;
if (dynamicParallelism()) {
@@ -929,10 +929,9 @@ hsa_kernel_dispatch_packet_t* HSAILKernel::loadArguments(
AmdAqlWrap* wrap = reinterpret_cast<AmdAqlWrap*>(aqlStruct);
memset(wrap, 0, sizeof(AmdAqlWrap));
wrap->state = AQL_WRAP_BUSY;
ManagedBuffer* cb = gpu.constBufs_[1];
cb->uploadDataToHw(sizeof(AmdAqlWrap));
*vmParentWrap = cb->vmAddress() + cb->wrtOffset();
gpu.addVmMemory(cb->activeMemory());
const ConstantBuffer* cb = gpu.cb(1);
*vmParentWrap = cb->UploadDataToHw(sizeof(AmdAqlWrap));
gpu.addVmMemory(cb->ActiveMemory());
}
const amd::KernelSignature& signature = kernel.signature();
@@ -1066,12 +1065,11 @@ hsa_kernel_dispatch_packet_t* HSAILKernel::loadArguments(
case HSAIL_ARGTYPE_REFERENCE: {
// Copy the current structure into CB1
memcpy(aqlStruct, paramaddr, arg->size_);
ManagedBuffer* cb = gpu.constBufs_[1];
cb->uploadDataToHw(arg->size_);
const ConstantBuffer* cb = gpu.cb(1);
// Then use a pointer in aqlArgBuffer to CB1
size_t gpuPtr = static_cast<size_t>(cb->vmAddress() + cb->wrtOffset());
size_t gpuPtr = static_cast<size_t>(cb->UploadDataToHw(arg->size_));
WriteAqlArg(&aqlArgBuf, &gpuPtr, sizeof(size_t), sizeof(size_t));
gpu.addVmMemory(cb->activeMemory());
gpu.addVmMemory(cb->ActiveMemory());
break;
}
case HSAIL_ARGTYPE_VALUE:
@@ -1109,12 +1107,11 @@ hsa_kernel_dispatch_packet_t* HSAILKernel::loadArguments(
if (image->memoryType() == Resource::ImageView) {
// Copy the current structre into CB1
memcpy(aqlStruct, image->hwState(), HsaImageObjectSize);
ManagedBuffer* cb = gpu.constBufs_[1];
cb->uploadDataToHw(HsaImageObjectSize);
const ConstantBuffer* cb = gpu.cb(1);
// Then use a pointer in aqlArgBuffer to CB1
uint64_t srd = cb->vmAddress() + cb->wrtOffset();
uint64_t srd = cb->UploadDataToHw(HsaImageObjectSize);
WriteAqlArg(&aqlArgBuf, &srd, sizeof(srd), sizeof(srd));
gpu.addVmMemory(cb->activeMemory());
gpu.addVmMemory(cb->ActiveMemory());
} else {
uint64_t srd = image->hwSrd();
WriteAqlArg(&aqlArgBuf, &srd, sizeof(srd), sizeof(srd));
@@ -1171,15 +1168,15 @@ hsa_kernel_dispatch_packet_t* HSAILKernel::loadArguments(
#if defined(WITH_LIGHTNING_COMPILER)
// Check there is no arguments' buffer overflow. We may not use all the
// hidden argument slots.
assert(aqlArgBuf <= (gpu.cb(0)->sysMemCopy() + argsBufferSize()));
assert(aqlArgBuf <= (gpu.cb(0)->SysMemCopy() + argsBufferSize()));
#else // !defined(WITH_LIGHTNING_COMPILER)
// HSAIL kernarg segment size is rounded up to multiple of 16.
aqlArgBuf = amd::alignUp(aqlArgBuf, 16);
assert((aqlArgBuf == (gpu.cb(0)->sysMemCopy() + argsBufferSize())) &&
assert((aqlArgBuf == (gpu.cb(0)->SysMemCopy() + argsBufferSize())) &&
"Size and the number of arguments don't match!");
#endif // !defined(WITH_LIGHTNING_COMPILER)
hsa_kernel_dispatch_packet_t* hsaDisp =
reinterpret_cast<hsa_kernel_dispatch_packet_t*>(gpu.cb(0)->sysMemCopy() + argsBufferSize());
reinterpret_cast<hsa_kernel_dispatch_packet_t*>(gpu.cb(0)->SysMemCopy() + argsBufferSize());
amd::NDRange local(sizes.local());
const amd::NDRange& global = sizes.global();
@@ -1204,15 +1201,15 @@ hsa_kernel_dispatch_packet_t* HSAILKernel::loadArguments(
hsaDisp->group_segment_size = ldsAddress - ldsSize();
hsaDisp->kernel_object = gpuAqlCode();
ManagedBuffer* cb = gpu.constBufs_[0];
cb->uploadDataToHw(argsBufferSize() + sizeof(hsa_kernel_dispatch_packet_t));
uint64_t argList = cb->vmAddress() + cb->wrtOffset();
const ConstantBuffer* cb = gpu.cb(0);
uint64_t argList = cb->UploadDataToHw(
argsBufferSize() + sizeof(hsa_kernel_dispatch_packet_t));
hsaDisp->kernarg_address = reinterpret_cast<void*>(argList);
hsaDisp->reserved2 = 0;
hsaDisp->completion_signal.handle = 0;
gpu.addVmMemory(cb->activeMemory());
gpu.addVmMemory(cb->ActiveMemory());
gpu.addVmMemory(&prog().codeSegGpu());
for (pal::Memory* mem : prog().globalStores()) {
gpu.addVmMemory(mem);
+15 -4
View File
@@ -702,6 +702,7 @@ VirtualGPU::VirtualGPU(Device& device)
printfDbgHSA_(nullptr),
tsCache_(nullptr),
dmaFlushMgmt_(device),
writeBuffer_(nullptr),
hwRing_(0),
readjustTimeGPU_(0),
lastTS_(nullptr),
@@ -812,6 +813,13 @@ bool VirtualGPU::create(bool profiling, uint deviceQueueSize, uint rtCUs,
Unimplemented();
}
writeBuffer_ = new ManagedBuffer(*this, dev().settings().stagedXferSize_);
if ((writeBuffer_ == nullptr) || !writeBuffer_->create(Resource::RemoteUSWC)) {
// We failed to create a constant buffer
delete writeBuffer_;
return false;
}
// Diable double copy optimization,
// since UAV read from nonlocal is fast enough
blitSetup.disableCopyBufferToImageOpt_ = true;
@@ -934,6 +942,8 @@ VirtualGPU::~VirtualGPU() {
delete constBufs_[i];
}
delete writeBuffer_;
//! @todo Temporarily keep the buffer mapped for debug purpose
if (nullptr != schedParams_) {
schedParams_->unmap(this);
@@ -2803,15 +2813,16 @@ void VirtualGPU::waitEventLock(CommandBatch* cb) {
}
bool VirtualGPU::allocConstantBuffers() {
// Allocate constant buffers, GCN doesn't really have a limit
static constexpr uint32_t MinCbSize = 256 * Ki;
// Allocate constant buffers.
// Use double size, reported to the app to account for internal arguments
const uint32_t MinCbSize = 2 * dev().info().maxParameterSize_;
uint i;
// Create/reallocate constant buffer resources
for (i = 0; i < MaxConstBuffersArguments; ++i) {
ManagedBuffer* constBuf = new ManagedBuffer(*this, MinCbSize);
ConstantBuffer* constBuf = new ConstantBuffer(*writeBuffer_, MinCbSize);
if ((constBuf != nullptr) && constBuf->create(Resource::RemoteUSWC, true)) {
if ((constBuf != nullptr) && constBuf->Create()) {
addConstBuffer(constBuf);
} else {
// We failed to create a constant buffer
+6 -5
View File
@@ -207,7 +207,7 @@ class VirtualGPU : public device::VirtualDevice {
State() : value_(0) {}
};
typedef std::vector<ManagedBuffer*> constbufs_t;
typedef std::vector<ConstantBuffer*> constbufs_t;
class MemoryDependency : public amd::EmbeddedObject {
public:
@@ -341,12 +341,10 @@ class VirtualGPU : public device::VirtualDevice {
);
//! Returns a resource associated with the constant buffer
const ManagedBuffer* cb(uint idx) const { return constBufs_[idx]; }
const ConstantBuffer* cb(uint idx) const { return constBufs_[idx]; }
//! Adds CAL objects into the constant buffer vector
void addConstBuffer(ManagedBuffer* cb) { constBufs_.push_back(cb); }
constbufs_t constBufs_; //!< constant buffers
void addConstBuffer(ConstantBuffer* cb) { constBufs_.push_back(cb); }
//! Start the command profiling
void profilingBegin(amd::Command& command, //!< Command queue object
@@ -597,6 +595,9 @@ class VirtualGPU : public device::VirtualDevice {
std::vector<Memory*> xferWriteBuffers_; //!< Stage write buffers
std::vector<amd::Memory*> pinnedMems_; //!< Pinned memory list
ManagedBuffer* writeBuffer_; //!< Managed write buffer
constbufs_t constBufs_; //!< constant buffers
typedef std::queue<CommandBatch*> CommandBatchQueue;
CommandBatchQueue cbQueue_; //!< Queue of command batches
CommandBatchQueue freeCbQueue_; //!< Queue of free command batches