Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2af734d
Move `MemoryLocation` to `Resources.h` - move `BufferUsage`, `BufferC…
EmilioLaiso Mar 26, 2026
ea286e0
Add `Texture.h`
EmilioLaiso Mar 26, 2026
b6eca77
Add texture creation to all backends
EmilioLaiso Mar 26, 2026
5c82fee
Add optional `ClearValue` variant to `TextureCreateDesc`. Expand text…
EmilioLaiso Mar 26, 2026
69d7d25
add `toTextureFormat` function needed as a bridge while refactoring code
EmilioLaiso Mar 26, 2026
bf95c4a
use `createTexture` in `createRenderTarget`
EmilioLaiso Mar 26, 2026
b8488dd
Metal render target readback now achieved through blit to readback bu…
EmilioLaiso Mar 30, 2026
4e88977
Unify render target creation across DX, VK, and Metal backends throug…
EmilioLaiso Mar 30, 2026
e856176
use texture desc clear color on metal and vk backends instead of hard…
EmilioLaiso Mar 30, 2026
062efe9
add `validateTextureDescMatchesCPUBuffer`, `getTextureFormatSize`, `i…
EmilioLaiso Mar 30, 2026
e1091aa
Add `D32FloatS8Uint` format
EmilioLaiso Mar 30, 2026
6ac908a
add `createDepthStencil`function
EmilioLaiso Mar 30, 2026
6da4502
rewrite depth stencil using `createTexture` and align usages of depth…
EmilioLaiso Mar 30, 2026
2be7872
Move RTV/DSV to texture creation rather than `createGraphicsCommands`
EmilioLaiso Mar 31, 2026
925fe5f
generalized `Format` enum instead of `TextureFormat`
EmilioLaiso Mar 31, 2026
250afe4
const
EmilioLaiso Apr 2, 2026
2d6924c
pr feedback: rename functions and remove comments
EmilioLaiso Apr 2, 2026
c918630
fix resources initial state
EmilioLaiso Apr 2, 2026
c0ab760
fmt
EmilioLaiso Apr 7, 2026
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
36 changes: 36 additions & 0 deletions include/API/Buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===- Buffer.h - Offload API Buffer --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//

#ifndef OFFLOADTEST_API_BUFFER_H
#define OFFLOADTEST_API_BUFFER_H

#include "API/Resources.h"

namespace offloadtest {

struct BufferCreateDesc {
MemoryLocation Location;
};

class Buffer {
public:
virtual ~Buffer() = default;

Buffer(const Buffer &) = delete;
Buffer &operator=(const Buffer &) = delete;

protected:
Buffer() = default;
};

} // namespace offloadtest

#endif // OFFLOADTEST_API_BUFFER_H
38 changes: 17 additions & 21 deletions include/API/Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
#include "Config.h"

#include "API/API.h"
#include "API/Buffer.h"
#include "API/Capabilities.h"
#include "API/Texture.h"
#include "Support/Pipeline.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"

Expand All @@ -35,27 +38,6 @@ struct DeviceConfig {
bool EnableValidationLayer = false;
};

enum class MemoryLocation {
GpuOnly,
CpuToGpu,
GpuToCpu,
};

struct BufferCreateDesc {
MemoryLocation Location;
};

class Buffer {
public:
virtual ~Buffer() = default;

Buffer(const Buffer &) = delete;
Buffer &operator=(const Buffer &) = delete;

protected:
Buffer() = default;
};

class Queue {
public:
virtual ~Queue() = 0;
Expand All @@ -80,6 +62,10 @@ class Device {
virtual llvm::Expected<std::shared_ptr<Buffer>>
createBuffer(std::string Name, BufferCreateDesc &Desc,
size_t SizeInBytes) = 0;

virtual llvm::Expected<std::shared_ptr<Texture>>
createTexture(std::string Name, TextureCreateDesc &Desc) = 0;

virtual void printExtra(llvm::raw_ostream &OS) {}

virtual ~Device() = 0;
Expand All @@ -100,6 +86,16 @@ initializeMetalDevices(const DeviceConfig Config,
llvm::Expected<llvm::SmallVector<std::unique_ptr<Device>>>
initializeDevices(const DeviceConfig Config);

// Creates a render target texture using the format and dimensions from a
// CPUBuffer. Does not upload the buffer's data — only uses its description to
// configure the texture.
llvm::Expected<std::shared_ptr<Texture>>
createRenderTargetFromCPUBuffer(Device &Dev, const CPUBuffer &Buf);

// Creates a depth/stencil texture matching the dimensions of a render target.
llvm::Expected<std::shared_ptr<Texture>>
createDefaultDepthStencilTarget(Device &Dev, uint32_t Width, uint32_t Height);

} // namespace offloadtest

#endif // OFFLOADTEST_API_DEVICE_H
159 changes: 159 additions & 0 deletions include/API/FormatConversion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
//===- FormatConversion.h - Bridge between DataFormat and Format -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Transitional helpers for converting between the legacy DataFormat + Channels
// description system and the unified Format enum. This file should be deleted
// once the pipeline is fully migrated to use Format directly.
//
//===----------------------------------------------------------------------===//

#ifndef OFFLOADTEST_API_FORMATCONVERSION_H
#define OFFLOADTEST_API_FORMATCONVERSION_H

#include "API/Resources.h"
#include "API/Texture.h"
#include "Support/Pipeline.h"

#include "llvm/Support/Error.h"

namespace offloadtest {

// Bridge for code that still describes textures as DataFormat + Channels (e.g.
// render targets bound via CPUBuffer). Once the pipeline is refactored to use
// Format directly, this function can be removed.
inline llvm::Expected<Format> toFormat(DataFormat Format, int Channels) {
switch (Format) {
case DataFormat::Int16:
switch (Channels) {
case 1:
return Format::R16Sint;
case 2:
return Format::RG16Sint;
case 4:
return Format::RGBA16Sint;
}
break;
case DataFormat::UInt16:
switch (Channels) {
case 1:
return Format::R16Uint;
case 2:
return Format::RG16Uint;
case 4:
return Format::RGBA16Uint;
}
break;
case DataFormat::Int32:
switch (Channels) {
case 1:
return Format::R32Sint;
case 2:
return Format::RG32Sint;
case 4:
return Format::RGBA32Sint;
}
break;
case DataFormat::UInt32:
switch (Channels) {
case 1:
return Format::R32Uint;
case 2:
return Format::RG32Uint;
case 4:
return Format::RGBA32Uint;
}
break;
case DataFormat::Float32:
switch (Channels) {
case 1:
return Format::R32Float;
case 2:
return Format::RG32Float;
case 4:
return Format::RGBA32Float;
}
break;
case DataFormat::Depth32:
// D32FloatS8Uint is not expressible as DataFormat + Channels because the
// stencil component is uint8, not a second Depth32 channel. Once the
// pipeline uses Format directly, this limitation goes away.
if (Channels == 1)
return Format::D32Float;
break;
// No Format mapping for these DataFormats.
case DataFormat::Hex8:
case DataFormat::Hex16:
case DataFormat::Hex32:
case DataFormat::Hex64:
case DataFormat::UInt64:
case DataFormat::Int64:
case DataFormat::Float16:
case DataFormat::Float64:
case DataFormat::Bool:
return llvm::createStringError(std::errc::invalid_argument,
"DataFormat %d has no Format equivalent.",
static_cast<int>(Format));
}
return llvm::createStringError(std::errc::invalid_argument,
"No Format for DataFormat %d with %d "
"channel(s).",
static_cast<int>(Format), Channels);
}

// Validates that a TextureCreateDesc is consistent with the CPUBuffer it was
// derived from. Call this after building a TextureCreateDesc from a CPUBuffer
// to catch mismatches between the two description systems.
inline llvm::Error
validateTextureDescMatchesCPUBuffer(const TextureCreateDesc &Desc,
const CPUBuffer &Buf) {
auto ExpectedFmt = toFormat(Buf.Format, Buf.Channels);
if (!ExpectedFmt)
return ExpectedFmt.takeError();
if (Desc.Format != *ExpectedFmt)
return llvm::createStringError(
std::errc::invalid_argument,
"TextureCreateDesc format '%s' does not match CPUBuffer format "
"(DataFormat %d, %d channels -> '%s').",
getFormatName(Desc.Format).data(), static_cast<int>(Buf.Format),
Buf.Channels, getFormatName(*ExpectedFmt).data());
if (Desc.Width != static_cast<uint32_t>(Buf.OutputProps.Width))
return llvm::createStringError(
std::errc::invalid_argument,
"TextureCreateDesc width %u does not match CPUBuffer width %d.",
Desc.Width, Buf.OutputProps.Width);
if (Desc.Height != static_cast<uint32_t>(Buf.OutputProps.Height))
return llvm::createStringError(
std::errc::invalid_argument,
"TextureCreateDesc height %u does not match CPUBuffer height %d.",
Desc.Height, Buf.OutputProps.Height);
if (Desc.MipLevels != static_cast<uint32_t>(Buf.OutputProps.MipLevels))
return llvm::createStringError(
std::errc::invalid_argument,
"TextureCreateDesc mip levels %u does not match CPUBuffer mip "
"levels %d.",
Desc.MipLevels, Buf.OutputProps.MipLevels);
const uint32_t TexelSize = getFormatSize(Desc.Format);
if (Buf.Stride > 0 && static_cast<uint32_t>(Buf.Stride) != TexelSize)
return llvm::createStringError(
std::errc::invalid_argument,
"CPUBuffer stride %d does not match texture format element size %u.",
Buf.Stride, TexelSize);
const uint64_t ExpectedSize =
static_cast<uint64_t>(Desc.Width) * Desc.Height * TexelSize;
if (static_cast<uint64_t>(Buf.size()) != ExpectedSize)
return llvm::createStringError(
std::errc::invalid_argument,
"CPUBuffer size %u does not match expected size %llu "
"(width %u * height %u * element size %u).",
Buf.size(), ExpectedSize, Desc.Width, Desc.Height, TexelSize);
return llvm::Error::success();
}

} // namespace offloadtest

#endif // OFFLOADTEST_API_FORMATCONVERSION_H
Loading