Skip to content
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
4 changes: 4 additions & 0 deletions include/API/Buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ enum class BufferUsage {
struct BufferCreateDesc {
MemoryLocation Location;
BufferUsage Usage;

static BufferCreateDesc uploadBuffer() {
return BufferCreateDesc{MemoryLocation::CpuToGpu, BufferUsage::Storage};
}
};

class Buffer {
Expand Down
8 changes: 5 additions & 3 deletions include/API/Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,11 @@ createRenderTargetFromCPUBuffer(Device &Dev, const CPUBuffer &Buf);
llvm::Expected<std::unique_ptr<Texture>>
createDefaultDepthStencilTarget(Device &Dev, uint32_t Width, uint32_t Height);

// Creates a vertex buffer and uploads the given CPU-side vertex data into it.
llvm::Expected<std::unique_ptr<Buffer>>
createVertexBufferFromCPUBuffer(Device &Dev, const CPUBuffer &Buf);
llvm::Expected<std::unique_ptr<offloadtest::Buffer>>
createBufferWithData(Device &Dev, std::string Name,
const BufferCreateDesc &Desc, const void *Data,
size_t SizeInBytes, ComputeEncoder *Encoder,
std::unique_ptr<offloadtest::Buffer> *OutUploadBuffer);

} // namespace offloadtest

Expand Down
16 changes: 11 additions & 5 deletions lib/API/DX/Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1640,11 +1640,17 @@ class DXDevice : public offloadtest::Device {
}

if (P.isTraditionalRaster() && P.Bindings.VertexBufferPtr) {
auto VBOrErr = offloadtest::createVertexBufferFromCPUBuffer(
*this, *P.Bindings.VertexBufferPtr);
if (!VBOrErr)
return VBOrErr.takeError();
IS.VB = std::move(*VBOrErr);
const CPUBuffer *VBuffer = P.Bindings.VertexBufferPtr;

BufferCreateDesc BufDesc = {};
BufDesc.Location = MemoryLocation::CpuToGpu;
BufDesc.Usage = BufferUsage::VertexBuffer;
auto BufOrErr = createBufferWithData(*this, "VertexBuffer", BufDesc,
VBuffer->Data[0].get(),
VBuffer->size(), nullptr, nullptr);
if (!BufOrErr)
return BufOrErr.takeError();
IS.VB = std::move(*BufOrErr);
llvm::outs() << "Vertex buffer created.\n";
}

Expand Down
90 changes: 67 additions & 23 deletions lib/API/Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,29 +90,6 @@ offloadtest::createRenderTargetFromCPUBuffer(Device &Dev,
return Dev.createTexture("RenderTarget", Desc);
}

llvm::Expected<std::unique_ptr<Buffer>>
offloadtest::createVertexBufferFromCPUBuffer(Device &Dev,
const CPUBuffer &Buf) {
BufferCreateDesc BufDesc = {};
BufDesc.Location = MemoryLocation::CpuToGpu;
BufDesc.Usage = BufferUsage::VertexBuffer;
auto BufOrErr = Dev.createBuffer("VertexBuffer", BufDesc, Buf.size());
if (!BufOrErr)
return BufOrErr.takeError();
auto VB = std::move(*BufOrErr);

// TODO: Currently uses a single CpuToGpu mapped buffer.
// On discrete GPUs consider using a staging buffer + copy to a GpuOnly vertex
// buffer for optimal GPU read performance.
auto PtrOrErr = VB->map();
if (!PtrOrErr)
return PtrOrErr.takeError();
memcpy(*PtrOrErr, Buf.Data[0].get(), Buf.size());
VB->unmap();

return VB;
}

llvm::Expected<std::unique_ptr<Texture>>
offloadtest::createDefaultDepthStencilTarget(Device &Dev, uint32_t Width,
uint32_t Height) {
Expand All @@ -127,3 +104,70 @@ offloadtest::createDefaultDepthStencilTarget(Device &Dev, uint32_t Width,

return Dev.createTexture("DepthStencil", Desc);
}

// This is a separate function because recursion is not allowed in this code
// base.
static llvm::Expected<std::unique_ptr<offloadtest::Buffer>>
createUploadBufferWithData(Device &Dev, std::string Name, const void *Data,
size_t SizeInBytes) {

// Create Upload buffer
const BufferCreateDesc UploadDesc = BufferCreateDesc::uploadBuffer();
const std::string UploadBufferName = Name + " (Upload Buffer)";

auto UploadBufferOrErr =
Dev.createBuffer(UploadBufferName, UploadDesc, SizeInBytes);
if (!UploadBufferOrErr)
return UploadBufferOrErr.takeError();
auto UploadBuffer = std::move(*UploadBufferOrErr);

// Copy data over
auto MappedPtrOrErr = UploadBuffer->map();
if (!MappedPtrOrErr)
return MappedPtrOrErr.takeError();
void *MappedPtr = *MappedPtrOrErr;
memcpy(MappedPtr, Data, SizeInBytes);
UploadBuffer->unmap();

return std::move(UploadBuffer);
}

llvm::Expected<std::unique_ptr<offloadtest::Buffer>>
offloadtest::createBufferWithData(
Device &Dev, std::string Name, const BufferCreateDesc &Desc,
const void *Data, size_t SizeInBytes, ComputeEncoder *Encoder,
std::unique_ptr<offloadtest::Buffer> *OutUploadBuffer) {
auto BufferOrErr = Dev.createBuffer(Name, Desc, SizeInBytes);
if (!BufferOrErr)
return BufferOrErr.takeError();
auto Buffer = std::move(*BufferOrErr);

if (Desc.Location == MemoryLocation::GpuOnly) {
if (OutUploadBuffer == nullptr)
return llvm::createStringError(
"An upload buffer is required to create a GpuOnly buffer with data.");

// Create Upload buffer
auto UploadBufferOrErr =
createUploadBufferWithData(Dev, Name, Data, SizeInBytes);
if (!UploadBufferOrErr)
return UploadBufferOrErr.takeError();
*OutUploadBuffer = std::move(*UploadBufferOrErr);

// Copy Buffer to Buffer
if (auto Err = Encoder->copyBufferToBuffer(**OutUploadBuffer, 0, *Buffer, 0,
SizeInBytes))
return Err;

} else {
// Copy data over
auto MappedPtrOrErr = Buffer->map();
if (!MappedPtrOrErr)
return MappedPtrOrErr.takeError();
void *MappedPtr = *MappedPtrOrErr;
memcpy(MappedPtr, Data, SizeInBytes);
Buffer->unmap();
}

return Buffer;
}
16 changes: 11 additions & 5 deletions lib/API/MTL/MTLDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -956,11 +956,17 @@ class MTLDevice : public offloadtest::Device {
}

if (P.isTraditionalRaster() && P.Bindings.VertexBufferPtr) {
auto VBOrErr = offloadtest::createVertexBufferFromCPUBuffer(
*this, *P.Bindings.VertexBufferPtr);
if (!VBOrErr)
return VBOrErr.takeError();
IS.VB = std::move(*VBOrErr);
const CPUBuffer *VBuffer = P.Bindings.VertexBufferPtr;

BufferCreateDesc BufDesc = {};
BufDesc.Location = MemoryLocation::CpuToGpu;
BufDesc.Usage = BufferUsage::VertexBuffer;
auto BufOrErr = createBufferWithData(*this, "VertexBuffer", BufDesc,
VBuffer->Data[0].get(),
VBuffer->size(), nullptr, nullptr);
if (!BufOrErr)
return BufOrErr.takeError();
IS.VB = std::move(*BufOrErr);
llvm::outs() << "Vertex buffer created.\n";
}
return llvm::Error::success();
Expand Down
16 changes: 11 additions & 5 deletions lib/API/VK/Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1934,11 +1934,17 @@ class VulkanDevice : public offloadtest::Device {
}

if (P.isTraditionalRaster() && P.Bindings.VertexBufferPtr) {
auto VBOrErr = offloadtest::createVertexBufferFromCPUBuffer(
*this, *P.Bindings.VertexBufferPtr);
if (!VBOrErr)
return VBOrErr.takeError();
IS.VB = std::move(*VBOrErr);
const CPUBuffer *VBuffer = P.Bindings.VertexBufferPtr;

BufferCreateDesc BufDesc = {};
BufDesc.Location = MemoryLocation::CpuToGpu;
BufDesc.Usage = BufferUsage::VertexBuffer;
auto BufOrErr = createBufferWithData(*this, "VertexBuffer", BufDesc,
VBuffer->Data[0].get(),
VBuffer->size(), nullptr, nullptr);
if (!BufOrErr)
return BufOrErr.takeError();
IS.VB = std::move(*BufOrErr);
llvm::outs() << "Vertex buffer created.\n";
}

Expand Down
Loading