1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
// metal-helper-functions.h
#pragma once
#include "metal-base.h"
namespace gfx
{
using namespace Slang;
namespace metal
{
/// A "simple" binding offset that records an offset in buffer/texture/sampler slots
struct BindingOffset
{
uint32_t buffer = 0;
uint32_t texture = 0;
uint32_t sampler = 0;
/// Create a default (zero) offset
BindingOffset() = default;
/// Create an offset based on offset information in the given Slang `varLayout`
BindingOffset(slang::VariableLayoutReflection* varLayout)
{
if (varLayout)
{
buffer = (uint32_t)varLayout->getOffset(SLANG_PARAMETER_CATEGORY_METAL_BUFFER);
texture = (uint32_t)varLayout->getOffset(SLANG_PARAMETER_CATEGORY_METAL_TEXTURE);
sampler = (uint32_t)varLayout->getOffset(SLANG_PARAMETER_CATEGORY_METAL_SAMPLER);
}
}
/// Create an offset based on size/stride information in the given Slang `typeLayout`
BindingOffset(slang::TypeLayoutReflection* typeLayout)
{
if (typeLayout)
{
buffer = (uint32_t)typeLayout->getSize(SLANG_PARAMETER_CATEGORY_METAL_BUFFER);
texture = (uint32_t)typeLayout->getSize(SLANG_PARAMETER_CATEGORY_METAL_TEXTURE);
sampler = (uint32_t)typeLayout->getSize(SLANG_PARAMETER_CATEGORY_METAL_SAMPLER);
}
}
/// Add any values in the given `offset`
void operator+=(BindingOffset const& offset)
{
buffer += offset.buffer;
texture += offset.texture;
sampler += offset.sampler;
}
};
/// Contextual data and operations required when binding shader objects to the pipeline state
struct BindingContext
{
DeviceImpl* device = nullptr;
virtual void setBuffer(MTL::Buffer* buffer, NS::UInteger index) = 0;
virtual void setTexture(MTL::Texture* texture, NS::UInteger index) = 0;
virtual void setSampler(MTL::SamplerState* sampler, NS::UInteger index) = 0;
virtual void useResources(
MTL::Resource const** resources,
NS::UInteger count,
MTL::ResourceUsage usage) = 0;
};
struct ComputeBindingContext : public BindingContext
{
MTL::ComputeCommandEncoder* encoder;
Result init(DeviceImpl* device, MTL::ComputeCommandEncoder* encoder)
{
this->device = device;
this->encoder = encoder;
return SLANG_OK;
}
void setBuffer(MTL::Buffer* buffer, NS::UInteger index) override
{
encoder->setBuffer(buffer, 0, index);
}
void setTexture(MTL::Texture* texture, NS::UInteger index) override
{
encoder->setTexture(texture, index);
}
void setSampler(MTL::SamplerState* sampler, NS::UInteger index) override
{
encoder->setSamplerState(sampler, index);
}
void useResources(MTL::Resource const** resources, NS::UInteger count, MTL::ResourceUsage usage)
override
{
encoder->useResources(resources, count, usage);
}
};
struct RenderBindingContext : public BindingContext
{
MTL::RenderCommandEncoder* encoder;
Result init(DeviceImpl* device, MTL::RenderCommandEncoder* encoder)
{
this->device = device;
this->encoder = encoder;
return SLANG_OK;
}
void setBuffer(MTL::Buffer* buffer, NS::UInteger index) override
{
encoder->setVertexBuffer(buffer, 0, index);
encoder->setFragmentBuffer(buffer, 0, index);
}
void setTexture(MTL::Texture* texture, NS::UInteger index) override
{
encoder->setVertexTexture(texture, index);
encoder->setFragmentTexture(texture, index);
}
void setSampler(MTL::SamplerState* sampler, NS::UInteger index) override
{
encoder->setVertexSamplerState(sampler, index);
encoder->setFragmentSamplerState(sampler, index);
}
void useResources(MTL::Resource const** resources, NS::UInteger count, MTL::ResourceUsage usage)
override
{
encoder->useResources(resources, count, usage);
}
};
} // namespace metal
Result SLANG_MCALL getMetalAdapters(List<AdapterInfo>& outAdapters);
Result SLANG_MCALL createMetalDevice(const IDevice::Desc* desc, IDevice** outRenderer);
} // namespace gfx
|