Skip to content

Commit bd53455

Browse files
committed
Add texture creation to all backends
1 parent 6b1921b commit bd53455

8 files changed

Lines changed: 448 additions & 52 deletions

File tree

include/API/Device.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "API/API.h"
1818
#include "API/Buffer.h"
1919
#include "API/Capabilities.h"
20+
#include "API/Texture.h"
2021
#include "llvm/ADT/StringRef.h"
2122
#include "llvm/ADT/iterator_range.h"
2223

@@ -60,6 +61,10 @@ class Device {
6061
virtual llvm::Expected<std::shared_ptr<Buffer>>
6162
createBuffer(std::string Name, BufferCreateDesc &Desc,
6263
size_t SizeInBytes) = 0;
64+
65+
virtual llvm::Expected<std::shared_ptr<Texture>>
66+
createTexture(llvm::StringRef Name, TextureCreateDesc &Desc) = 0;
67+
6368
virtual void printExtra(llvm::raw_ostream &OS) {}
6469

6570
virtual ~Device() = 0;

include/API/Texture.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ namespace offloadtest {
2424

2525
// TODO: Add Unorm types (e.g. R8Unorm, RGBA8Unorm) which can be sampled as
2626
// floats.
27-
//
2827
// TODO: Add SRGB types (e.g. RGBA8Srgb) once needed.
28+
//
29+
// Note: No 3-channel formats due to lack of Metal support.
2930
enum class TextureFormat {
3031
R16Sint,
3132
R16Uint,
@@ -39,9 +40,6 @@ enum class TextureFormat {
3940
RG32Sint,
4041
RG32Uint,
4142
RG32Float,
42-
RGB32Sint,
43-
RGB32Uint,
44-
RGB32Float,
4543
RGBA32Sint,
4644
RGBA32Uint,
4745
RGBA32Float,
@@ -82,12 +80,6 @@ inline llvm::StringRef getTextureFormatName(TextureFormat Format) {
8280
return "RG32Uint";
8381
case TextureFormat::RG32Float:
8482
return "RG32Float";
85-
case TextureFormat::RGB32Sint:
86-
return "RGB32Sint";
87-
case TextureFormat::RGB32Uint:
88-
return "RGB32Uint";
89-
case TextureFormat::RGB32Float:
90-
return "RGB32Float";
9183
case TextureFormat::RGBA32Sint:
9284
return "RGBA32Sint";
9385
case TextureFormat::RGBA32Uint:

lib/API/DX/DXResources.h

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//===- DXResources.h - DirectX Resource Helpers ---------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
#ifndef OFFLOADTEST_API_DXRESOURCES_H
13+
#define OFFLOADTEST_API_DXRESOURCES_H
14+
15+
#include "API/Device.h"
16+
17+
#include <d3d12.h>
18+
#include <dxgiformat.h>
19+
20+
namespace offloadtest {
21+
22+
inline D3D12_HEAP_TYPE getDXHeapType(MemoryLocation Location) {
23+
switch (Location) {
24+
case MemoryLocation::GpuOnly:
25+
return D3D12_HEAP_TYPE_DEFAULT;
26+
case MemoryLocation::CpuToGpu:
27+
return D3D12_HEAP_TYPE_UPLOAD;
28+
case MemoryLocation::GpuToCpu:
29+
return D3D12_HEAP_TYPE_READBACK;
30+
}
31+
llvm_unreachable("All MemoryLocation cases handled");
32+
}
33+
34+
inline DXGI_FORMAT getDXGIFormat(TextureFormat Format) {
35+
switch (Format) {
36+
case TextureFormat::R16Sint:
37+
return DXGI_FORMAT_R16_SINT;
38+
case TextureFormat::R16Uint:
39+
return DXGI_FORMAT_R16_UINT;
40+
case TextureFormat::RG16Sint:
41+
return DXGI_FORMAT_R16G16_SINT;
42+
case TextureFormat::RG16Uint:
43+
return DXGI_FORMAT_R16G16_UINT;
44+
case TextureFormat::RGBA16Sint:
45+
return DXGI_FORMAT_R16G16B16A16_SINT;
46+
case TextureFormat::RGBA16Uint:
47+
return DXGI_FORMAT_R16G16B16A16_UINT;
48+
case TextureFormat::R32Sint:
49+
return DXGI_FORMAT_R32_SINT;
50+
case TextureFormat::R32Uint:
51+
return DXGI_FORMAT_R32_UINT;
52+
case TextureFormat::R32Float:
53+
return DXGI_FORMAT_R32_FLOAT;
54+
case TextureFormat::RG32Sint:
55+
return DXGI_FORMAT_R32G32_SINT;
56+
case TextureFormat::RG32Uint:
57+
return DXGI_FORMAT_R32G32_UINT;
58+
case TextureFormat::RG32Float:
59+
return DXGI_FORMAT_R32G32_FLOAT;
60+
case TextureFormat::RGBA32Sint:
61+
return DXGI_FORMAT_R32G32B32A32_SINT;
62+
case TextureFormat::RGBA32Uint:
63+
return DXGI_FORMAT_R32G32B32A32_UINT;
64+
case TextureFormat::RGBA32Float:
65+
return DXGI_FORMAT_R32G32B32A32_FLOAT;
66+
case TextureFormat::D32Float:
67+
return DXGI_FORMAT_D32_FLOAT;
68+
}
69+
llvm_unreachable("All TextureFormat cases handled");
70+
}
71+
72+
inline D3D12_RESOURCE_FLAGS getDXResourceFlags(TextureUsage Usage) {
73+
D3D12_RESOURCE_FLAGS Flags = D3D12_RESOURCE_FLAG_NONE;
74+
if ((Usage & TextureUsage::Storage) != 0)
75+
Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
76+
if ((Usage & TextureUsage::RenderTarget) != 0)
77+
Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
78+
if ((Usage & TextureUsage::DepthStencil) != 0)
79+
Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
80+
return Flags;
81+
}
82+
83+
} // namespace offloadtest
84+
85+
#endif // OFFLOADTEST_API_DXRESOURCES_H

lib/API/DX/Device.cpp

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
#include "Support/Pipeline.h"
3838
#include "Support/WinError.h"
3939

40+
#include "DXResources.h"
41+
4042
#include "llvm/ADT/SmallVector.h"
4143
#include "llvm/Object/DXContainer.h"
4244
#include "llvm/Support/Error.h"
@@ -282,6 +284,17 @@ class DXBuffer : public offloadtest::Buffer {
282284
: Buffer(Buffer), Name(Name), Desc(Desc), SizeInBytes(SizeInBytes) {}
283285
};
284286

287+
class DXTexture : public offloadtest::Texture {
288+
public:
289+
ComPtr<ID3D12Resource> Resource;
290+
std::string Name;
291+
TextureCreateDesc Desc;
292+
293+
DXTexture(ComPtr<ID3D12Resource> Resource, llvm::StringRef Name,
294+
TextureCreateDesc Desc)
295+
: Resource(Resource), Name(Name), Desc(Desc) {}
296+
};
297+
285298
class DXQueue : public offloadtest::Queue {
286299
public:
287300
ComPtr<ID3D12CommandQueue> Queue;
@@ -370,19 +383,7 @@ class DXDevice : public offloadtest::Device {
370383
llvm::Expected<std::shared_ptr<offloadtest::Buffer>>
371384
createBuffer(std::string Name, BufferCreateDesc &Desc,
372385
size_t SizeInBytes) override {
373-
374-
D3D12_HEAP_TYPE HeapType = D3D12_HEAP_TYPE_DEFAULT;
375-
switch (Desc.Location) {
376-
case MemoryLocation::GpuOnly:
377-
HeapType = D3D12_HEAP_TYPE_DEFAULT;
378-
break;
379-
case MemoryLocation::CpuToGpu:
380-
HeapType = D3D12_HEAP_TYPE_UPLOAD;
381-
break;
382-
case MemoryLocation::GpuToCpu:
383-
HeapType = D3D12_HEAP_TYPE_READBACK;
384-
break;
385-
}
386+
const D3D12_HEAP_TYPE HeapType = getDXHeapType(Desc.Location);
386387

387388
const D3D12_RESOURCE_FLAGS Flags =
388389
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
@@ -402,6 +403,40 @@ class DXDevice : public offloadtest::Device {
402403
return std::make_shared<DXBuffer>(DeviceBuffer, Name, Desc, SizeInBytes);
403404
}
404405

406+
llvm::Expected<std::shared_ptr<offloadtest::Texture>>
407+
createTexture(llvm::StringRef Name, TextureCreateDesc &Desc) override {
408+
if (!isValidTextureUsageAndFormat(Desc.Usage, Desc.Format))
409+
return llvm::createStringError(
410+
std::errc::invalid_argument,
411+
"Invalid texture usage/format combination: usage '%s' is not "
412+
"compatible with format '%s'.",
413+
getTextureUsageName(Desc.Usage).c_str(),
414+
getTextureFormatName(Desc.Format).data());
415+
416+
const D3D12_HEAP_PROPERTIES HeapProps =
417+
CD3DX12_HEAP_PROPERTIES(getDXHeapType(Desc.Location));
418+
419+
D3D12_RESOURCE_DESC TexDesc = {};
420+
TexDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
421+
TexDesc.Width = Desc.Width, TexDesc.Height = Desc.Height,
422+
TexDesc.DepthOrArraySize = 1;
423+
TexDesc.MipLevels = static_cast<UINT16>(Desc.MipLevels);
424+
TexDesc.Format = getDXGIFormat(Desc.Format);
425+
TexDesc.SampleDesc.Count = 1;
426+
TexDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
427+
TexDesc.Flags = getDXResourceFlags(Desc.Usage);
428+
429+
ComPtr<ID3D12Resource> DeviceTexture;
430+
if (auto Err = HR::toError(Device->CreateCommittedResource(
431+
&HeapProps, D3D12_HEAP_FLAG_NONE, &TexDesc,
432+
D3D12_RESOURCE_STATE_COMMON, nullptr,
433+
IID_PPV_ARGS(&DeviceTexture)),
434+
"Failed to create texture."))
435+
return Err;
436+
437+
return std::make_shared<DXTexture>(DeviceTexture, Name, Desc);
438+
}
439+
405440
static llvm::Expected<DXDevice> create(ComPtr<IDXCoreAdapter> Adapter,
406441
const DeviceConfig &Config) {
407442
ComPtr<ID3D12Device> Device;

lib/API/MTL/MTLDevice.cpp

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "metal_irconverter_runtime.h"
1111

1212
#include "API/Device.h"
13+
#include "MTLResources.h"
1314
#include "Support/Pipeline.h"
1415

1516
#include "llvm/ADT/SmallString.h"
@@ -100,6 +101,21 @@ class MTLBuffer : public offloadtest::Buffer {
100101
}
101102
};
102103

104+
class MTLTexture : public offloadtest::Texture {
105+
public:
106+
MTL::Texture *Tex;
107+
std::string Name;
108+
TextureCreateDesc Desc;
109+
110+
MTLTexture(MTL::Texture *Tex, llvm::StringRef Name, TextureCreateDesc Desc)
111+
: Tex(Tex), Name(Name), Desc(Desc) {}
112+
113+
~MTLTexture() override {
114+
if (Tex)
115+
Tex->release();
116+
}
117+
};
118+
103119
class MTLDevice : public offloadtest::Device {
104120
Capabilities Caps;
105121
MTL::Device *Device;
@@ -567,24 +583,39 @@ class MTLDevice : public offloadtest::Device {
567583
llvm::Expected<std::shared_ptr<offloadtest::Buffer>>
568584
createBuffer(std::string Name, BufferCreateDesc &Desc,
569585
size_t SizeInBytes) override {
570-
MTL::ResourceOptions StorageMode;
571-
switch (Desc.Location) {
572-
case MemoryLocation::GpuOnly:
573-
StorageMode = MTL::ResourceStorageModePrivate;
574-
break;
575-
case MemoryLocation::CpuToGpu:
576-
case MemoryLocation::GpuToCpu:
577-
StorageMode = MTL::ResourceStorageModeManaged;
578-
break;
579-
}
580-
581-
MTL::Buffer *Buf = Device->newBuffer(SizeInBytes, StorageMode);
586+
MTL::Buffer *Buf =
587+
Device->newBuffer(SizeInBytes, getMetalResourceOptions(Desc.Location));
582588
if (!Buf)
583589
return llvm::createStringError(std::errc::not_enough_memory,
584590
"Failed to create Metal buffer.");
585591
return std::make_shared<MTLBuffer>(Buf, Name, Desc, SizeInBytes);
586592
}
587593

594+
llvm::Expected<std::shared_ptr<offloadtest::Texture>>
595+
createTexture(llvm::StringRef Name, TextureCreateDesc &Desc) override {
596+
if (!isValidTextureUsageAndFormat(Desc.Usage, Desc.Format))
597+
return llvm::createStringError(
598+
std::errc::invalid_argument,
599+
"Invalid texture usage/format combination: usage '%s' is not "
600+
"compatible with format '%s'.",
601+
getTextureUsageName(Desc.Usage).c_str(),
602+
getTextureFormatName(Desc.Format).data());
603+
604+
MTL::TextureDescriptor *TDesc =
605+
MTL::TextureDescriptor::texture2DDescriptor(
606+
getMetalFormat(Desc.Format), Desc.Width, Desc.Height,
607+
Desc.MipLevels > 1);
608+
TDesc->setMipmapLevelCount(Desc.MipLevels);
609+
TDesc->setStorageMode(getMetalStorageMode(Desc.Location));
610+
TDesc->setUsage(getMetalTextureUsage(Desc.Usage));
611+
612+
MTL::Texture *Tex = Device->newTexture(TDesc);
613+
if (!Tex)
614+
return llvm::createStringError(std::errc::not_enough_memory,
615+
"Failed to create Metal texture.");
616+
return std::make_shared<MTLTexture>(Tex, Name, Desc);
617+
}
618+
588619
llvm::Error executeProgram(Pipeline &P) override {
589620
InvocationState IS;
590621

0 commit comments

Comments
 (0)