Blender V4.3
mtl_shader_interface.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#pragma once
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_vector.hh"
14
16#include "mtl_capabilities.hh"
18
19#include "GPU_common.hh"
20#include "GPU_common_types.hh"
21#include "GPU_texture.hh"
23#include <Metal/Metal.h>
24#include <functional>
25
26namespace blender::gpu {
27
28/* #MTLShaderInterface describes the layout and properties of a given shader,
29 * including input and output bindings, and any special properties or modes
30 * that the shader may require.
31 *
32 * -- Shader input/output bindings --
33 *
34 * We require custom data-structures for the binding information in Metal.
35 * This is because certain bindings contain and require more information to
36 * be stored than can be tracked solely within the `ShaderInput` struct.
37 * e.g. data sizes and offsets.
38 *
39 * Upon interface completion, `prepare_common_shader_inputs` is used to
40 * populate the global `ShaderInput*` array to enable correct functionality
41 * of shader binding location lookups. These returned locations act as indices
42 * into the arrays stored here in the #MTLShaderInterface, such that extraction
43 * of required information can be performed within the back-end.
44 *
45 * e.g. `int loc = GPU_shader_get_uniform(...)`
46 * `loc` will match the index into the `MTLShaderUniform uniforms_[]` array
47 * to fetch the required Metal specific information.
48 *
49 *
50 *
51 * -- Argument Buffers and Argument Encoders --
52 *
53 * We can use #ArgumentBuffers (AB's) in Metal to extend the resource bind limitations
54 * by providing bind-less support.
55 *
56 * Argument Buffers are used for sampler bindings when the builtin
57 * sampler limit of 16 is exceeded, as in all cases for Blender,
58 * each individual texture is associated with a given sampler, and this
59 * lower limit would otherwise reduce the total availability of textures
60 * used in shaders.
61 *
62 * In future, argument buffers may be extended to support other resource
63 * types, if overall bind limits are ever increased within Blender.
64 *
65 * The #ArgumentEncoder cache used to store the generated #ArgumentEncoders for a given
66 * shader permutation. The #ArgumentEncoder is the resource used to write resource binding
67 * information to a specified buffer, and is unique to the shader's resource interface.
68 */
69
70enum class ShaderStage : uint8_t {
71 VERTEX = 1 << 0,
72 FRAGMENT = 1 << 1,
73 COMPUTE = 2 << 1,
75};
77
79{
80 switch (stage) {
82 return 0;
84 return 1;
86 return 2;
87 default:
89 return 0;
90 }
91 return 0;
92}
93
94/* Shader input/output binding information. */
97 MTLVertexFormat format;
103 /* For attributes of Matrix/array types, we need to insert "fake" attributes for
104 * each element, as matrix types are not natively supported.
105 *
106 * > 1 if matrix/arrays are used, specifying number of elements.
107 * = 1 for non-matrix types
108 * = 0 if used as a dummy slot for "fake" matrix attributes. */
110};
111
114 uint32_t size = 0;
115 /* Buffer resource bind index in shader `[[buffer(index)]]`. */
117 /* Explicit bind location for texture. */
119 /* Tracking for manual uniform addition. */
122};
123
126 /* Index of `MTLShaderBufferBlock` this uniform belongs to. */
131};
132
136
138 bool used;
140 /* Texture resource bind slot in shader `[[texture(n)]]`. */
142 /* Explicit bind location for texture. */
147 /* Whether texture resource is expected to be image or sampler. */
149 /* SSBO index for texture buffer binding. */
151 /* Uniform location for texture buffer metadata. */
153};
154
157 /* Sampler resource bind slot in shader `[[sampler(n)]]`. */
159};
160
161/* Utility Functions. */
162MTLVertexFormat mtl_datatype_to_vertex_type(eMTLDataType type);
163
168
169 private:
170 /* Argument encoders caching.
171 * Static size is based on common input permutation variations. */
172 static const int ARGUMENT_ENCODERS_CACHE_SIZE = 3;
173 struct ArgumentEncoderCacheEntry {
174 id<MTLArgumentEncoder> encoder;
175 int buffer_index;
176 };
177 ArgumentEncoderCacheEntry arg_encoders_[ARGUMENT_ENCODERS_CACHE_SIZE] = {};
178
179 /* Vertex input Attributes. */
180 uint32_t total_attributes_;
181 uint32_t total_vert_stride_;
183
184 /* Uniforms. */
185 uint32_t total_uniforms_;
187
188 /* Uniform Blocks. */
189 uint32_t total_uniform_blocks_;
190 uint32_t max_uniformbuf_index_;
192 MTLShaderBufferBlock push_constant_block_;
193
194 /* Storage blocks. */
195 uint32_t total_storage_blocks_;
196 uint32_t max_storagebuf_index_;
198
199 /* Textures. */
200 /* Textures support explicit binding indices, so some texture slots
201 * remain unused. */
202 uint32_t total_textures_;
203 int max_texture_index_;
205
206 /* Specialization constants. */
207 uint32_t total_constants_;
208 Vector<MTLShaderConstant> constants_;
209
210 /* Whether argument buffers are used for sampler bindings. */
211 bool sampler_use_argument_buffer_;
212 int sampler_argument_buffer_bind_index_[3];
213
214 /* Attribute Mask. */
215 uint32_t enabled_attribute_mask_;
216
217 /* Debug. */
218 char name[256];
219
220 public:
221 MTLShaderInterface(const char *name);
223
224 void init();
225 void add_input_attribute(uint32_t name_offset,
226 uint32_t attribute_location,
227 MTLVertexFormat format,
228 uint32_t buffer_index,
229 uint32_t size,
230 uint32_t offset,
231 int matrix_element_count = 1);
233 uint32_t buffer_index,
234 uint32_t location,
235 uint32_t size,
236 ShaderStage stage_mask = ShaderStage::ANY);
238 uint32_t buffer_index,
239 uint32_t location,
240 uint32_t size,
241 ShaderStage stage_mask = ShaderStage::ANY);
242 void add_uniform(uint32_t name_offset, eMTLDataType type, int array_len = 1);
243 void add_texture(uint32_t name_offset,
244 uint32_t texture_slot,
245 uint32_t location,
246 eGPUTextureType tex_binding_type,
247 eGPUSamplerFormat sampler_format,
248 bool is_texture_sampler,
250 int tex_buffer_ssbo_location = -1);
251 void add_push_constant_block(uint32_t name_offset);
252 void add_constant(uint32_t name_offset);
253
254 /* Resolve and cache locations of builtin uniforms and uniform blocks. */
255 void map_builtins();
256 void set_sampler_properties(bool use_argument_buffer,
257 uint32_t argument_buffer_bind_index_vert,
258 uint32_t argument_buffer_bind_index_frag,
259 uint32_t argument_buffer_bind_index_compute);
260
261 /* Prepare #ShaderInput interface for binding resolution. */
262 void prepare_common_shader_inputs(const shader::ShaderCreateInfo *info = nullptr);
263
264 /* Fetch Uniforms. */
265 const MTLShaderUniform &get_uniform(uint index) const;
267
268 /* Fetch Constants. */
270
271 /* Fetch Uniform Blocks. */
272 const MTLShaderBufferBlock &get_uniform_block(uint index) const;
274 bool has_uniform_block(uint32_t block_index) const;
275 uint32_t get_uniform_block_size(uint32_t block_index) const;
276
277 /* Fetch Storage Blocks. */
278 const MTLShaderBufferBlock &get_storage_block(uint index) const;
280 bool has_storage_block(uint32_t block_index) const;
281 uint32_t get_storage_block_size(uint32_t block_index) const;
282
283 /* Push constant uniform data block should always be available. */
286
287 /* Fetch textures. */
288 const MTLShaderTexture &get_texture(uint index) const;
293
294 /* Fetch Attributes. */
295 const MTLShaderInputAttribute &get_attribute(uint index) const;
299
300 /* Name buffer fetching. */
301 const char *get_name_at_offset(uint32_t offset) const;
302
303 /* Interface name. */
304 const char *get_name() const
305 {
306 return this->name;
307 }
308
309 /* Argument buffer encoder management. */
310 id<MTLArgumentEncoder> find_argument_encoder(int buffer_index) const;
311
312 void insert_argument_encoder(int buffer_index, id encoder);
313
314 MEM_CXX_CLASS_ALLOC_FUNCS("MTLShaderInterface");
315};
316
317} // namespace blender::gpu
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
unsigned int uint
#define ENUM_OPERATORS(_type, _max)
Read Guarded memory(de)allocation.
bool has_storage_block(uint32_t block_index) const
uint32_t add_storage_block(uint32_t name_offset, uint32_t buffer_index, uint32_t location, uint32_t size, ShaderStage stage_mask=ShaderStage::ANY)
uint32_t add_uniform_block(uint32_t name_offset, uint32_t buffer_index, uint32_t location, uint32_t size, ShaderStage stage_mask=ShaderStage::ANY)
void add_uniform(uint32_t name_offset, eMTLDataType type, int array_len=1)
const MTLShaderBufferBlock & get_push_constant_block() const
const MTLShaderTexture & get_texture(uint index) const
void insert_argument_encoder(int buffer_index, id encoder)
const MTLShaderBufferBlock & get_uniform_block(uint index) const
uint32_t get_storage_block_size(uint32_t block_index) const
const char * get_name_at_offset(uint32_t offset) const
bool has_uniform_block(uint32_t block_index) const
int get_argument_buffer_bind_index(ShaderStage stage) const
const MTLShaderInputAttribute & get_attribute(uint index) const
const MTLShaderBufferBlock & get_storage_block(uint index) const
const MTLShaderUniform & get_uniform(uint index) const
void add_input_attribute(uint32_t name_offset, uint32_t attribute_location, MTLVertexFormat format, uint32_t buffer_index, uint32_t size, uint32_t offset, int matrix_element_count=1)
id< MTLArgumentEncoder > find_argument_encoder(int buffer_index) const
uint32_t get_uniform_block_size(uint32_t block_index) const
void add_texture(uint32_t name_offset, uint32_t texture_slot, uint32_t location, eGPUTextureType tex_binding_type, eGPUSamplerFormat sampler_format, bool is_texture_sampler, ShaderStage stage_mask=ShaderStage::FRAGMENT, int tex_buffer_ssbo_location=-1)
void add_constant(uint32_t name_offset)
void add_push_constant_block(uint32_t name_offset)
void set_sampler_properties(bool use_argument_buffer, uint32_t argument_buffer_bind_index_vert, uint32_t argument_buffer_bind_index_frag, uint32_t argument_buffer_bind_index_compute)
MEM_CXX_CLASS_ALLOC_FUNCS("MTLShaderInterface")
void prepare_common_shader_inputs(const shader::ShaderCreateInfo *info=nullptr)
EvaluationStage stage
Definition deg_eval.cc:83
format
#define MTL_MAX_BUFFER_BINDINGS
#define MTL_MAX_TEXTURE_SLOTS
#define MTL_MAX_VERTEX_INPUT_ATTRIBUTES
#define MTL_MAX_UNIFORMS_PER_BLOCK
uint get_shader_stage_index(ShaderStage stage)
MTLVertexFormat mtl_datatype_to_vertex_type(eMTLDataType type)
unsigned int uint32_t
Definition stdint.h:80
unsigned char uint8_t
Definition stdint.h:78
Describe inputs & outputs, stage interfaces, resources and sources of a shader. If all data is correc...