Blender V5.0
mtl_pso_descriptor_state.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
8#pragma once
9
10#include "BLI_math_bits.h"
11#include "GPU_batch.hh"
12#include "GPU_vertex_format.hh"
13
14#include <Metal/Metal.h>
15
16#include "BLI_vector.hh"
17
19#include "gpu_shader_private.hh"
20
21namespace blender::gpu {
22
28 MTLVertexFormat format;
29 int offset;
32
34 {
35 return (format == other.format) && (offset == other.offset) &&
36 (buffer_index == other.buffer_index) &&
38 }
39
40 uint64_t hash() const
41 {
42 return uint64_t((uint64_t(this->format) ^ (this->offset << 4) ^ (this->buffer_index << 8) ^
43 (this->format_conversion_mode << 12)));
44 }
45
46 void reset()
47 {
48 format = MTLVertexFormatInvalid;
49 offset = 0;
50 buffer_index = 0;
52 }
53};
54
56 MTLVertexStepFunction step_function;
58 int stride;
59
61 {
62 return (step_function == other.step_function) && (step_rate == other.step_rate) &&
63 (stride == other.stride);
64 }
65
66 uint64_t hash() const
67 {
68 return uint64_t(uint64_t(this->step_function) ^ (this->step_rate << 4) ^ (this->stride << 8));
69 }
70
71 void reset()
72 {
73 step_function = MTLVertexStepFunctionPerVertex;
74 step_rate = 1;
75 stride = 0;
76 }
77};
78
80
81 /* Core Vertex Attributes. */
87 MTLPrimitiveTopologyClass prim_topology_class;
88
89 bool operator==(const MTLVertexDescriptor &other) const
90 {
91 if ((this->max_attribute_value != other.max_attribute_value) ||
92 (this->total_attributes != other.total_attributes) ||
93 (this->num_vert_buffers != other.num_vert_buffers))
94 {
95 return false;
96 }
97 if (this->prim_topology_class != other.prim_topology_class) {
98 return false;
99 };
100
101 for (const int a : IndexRange(this->max_attribute_value + 1)) {
102 if (!(this->attributes[a] == other.attributes[a])) {
103 return false;
104 }
105 }
106
107 for (const int b : IndexRange(this->num_vert_buffers)) {
108 if (!(this->buffer_layouts[b] == other.buffer_layouts[b])) {
109 return false;
110 }
111 }
112
113 /* NOTE: No need to compare SSBO attributes, as these will match attribute bindings for the
114 * given shader. These are simply extra pre-resolved properties we want to include in the
115 * cache. */
116 return true;
117 }
118
120 {
121 uint64_t hash = (uint64_t)(this->max_attribute_value ^ this->num_vert_buffers);
122 for (const int a : IndexRange(this->max_attribute_value + 1)) {
123 hash ^= this->attributes[a].hash() << a;
124 }
125
126 for (const int b : IndexRange(this->num_vert_buffers)) {
127 hash ^= this->buffer_layouts[b].hash() << (b + 10);
128 }
129 return hash;
130 }
131};
132
135
141
143 {
144 return values == other.values;
145 }
146
148 {
149 uint64_t hash = values.size();
150 uint seed = 0xFF;
151 for (const shader::SpecializationConstant::Value &value : values) {
152 seed = seed << 1;
153 hash ^= seed ^ value.u;
154 }
155 return hash;
156 }
157};
158
159/* Metal Render Pipeline State Descriptor -- All unique information which feeds PSO creation. */
161 /* This state descriptor will contain ALL parameters which generate a unique PSO.
162 * We will then use this state-object to efficiently look-up or create a
163 * new PSO for the current shader.
164 *
165 * Unlike the 'MTLContextGlobalShaderPipelineState', this struct contains a subset of
166 * parameters used to distinguish between unique PSOs. This struct is hash-able and only
167 * contains those parameters which are required by PSO generation. Non-unique state such as
168 * bound resources is not tracked here, as it does not require a unique PSO permutation if
169 * changed. */
170
171 /* Input Vertex Descriptor. */
173
174 /* Render Target attachment state.
175 * Assign to #MTLPixelFormatInvalid if not used. */
180
181 /* Render Pipeline State affecting PSO creation. */
183 MTLBlendOperation alpha_blend_op;
184 MTLBlendOperation rgb_blend_op;
186 MTLBlendFactor dest_rgb_blend_factor;
188 MTLBlendFactor src_rgb_blend_factor;
189
190 /* Global color write mask as this cannot be specified per attachment. */
191 MTLColorWriteMask color_write_mask;
192
193 /* Clip distance enablement. */
195
196 /* Point size required by point primitives. */
197 float point_size = 0.0f;
198
199 /* Specialization constants map. */
201
202 /* Comparison Operator for caching. */
204 {
205 if (!(vertex_descriptor == other.vertex_descriptor)) {
206 return false;
207 }
208
210 return false;
211 }
212
218 (rgb_blend_op != other.rgb_blend_op) ||
223 (vertex_descriptor.prim_topology_class != other.vertex_descriptor.prim_topology_class) ||
224 (point_size != other.point_size))
225 {
226 return false;
227 }
228
229 /* Attachments can be skipped, so num_color_attachments will not define the range. */
230 for (const int c : IndexRange(GPU_FB_MAX_COLOR_ATTACHMENT)) {
232 return false;
233 }
234 }
235
237 return false;
238 }
239
240 return true;
241 }
242
244 {
245 /* NOTE(Metal): Current setup aims to minimize overlap of parameters
246 * which are more likely to be different, to ensure earlier hash
247 * differences without having to fallback to comparisons.
248 * Though this could likely be further improved to remove
249 * has collisions. */
250
251 uint64_t hash = this->vertex_descriptor.hash();
252 hash ^= uint64_t(this->num_color_attachments) << 16; /* up to 6 (3 bits). */
253 hash ^= uint64_t(this->depth_attachment_format) << 18; /* up to 555 (9 bits). */
254 hash ^= uint64_t(this->stencil_attachment_format) << 20; /* up to 555 (9 bits). */
255 hash ^= uint64_t(
256 *((uint64_t *)&this->vertex_descriptor.prim_topology_class)); /* Up to 3 (2 bits). */
257
258 /* Only include elements in Hash if they are needed - avoids variable null assignments
259 * influencing hash. */
260 if (this->num_color_attachments > 0) {
261 hash ^= uint64_t(this->color_write_mask) << 22; /* 4 bit bit-mask. */
262 hash ^= uint64_t(this->alpha_blend_op) << 26; /* Up to 4 (3 bits). */
263 hash ^= uint64_t(this->rgb_blend_op) << 29; /* Up to 4 (3 bits). */
264 hash ^= uint64_t(this->dest_alpha_blend_factor) << 32; /* Up to 18 (5 bits). */
265 hash ^= uint64_t(this->dest_rgb_blend_factor) << 37; /* Up to 18 (5 bits). */
266 hash ^= uint64_t(this->src_alpha_blend_factor) << 42; /* Up to 18 (5 bits). */
267 hash ^= uint64_t(this->src_rgb_blend_factor) << 47; /* Up to 18 (5 bits). */
268
270 hash ^= uint64_t(this->color_attachment_format[c]) << (c + 52); /* Up to 555 (9 bits). */
271 }
272 }
273
274 hash |= uint64_t((this->blending_enabled && (this->num_color_attachments > 0)) ? 1 : 0) << 62;
275 hash ^= uint64_t(float_as_uint(this->point_size));
276
277 /* Clipping plane enablement. */
279
280 /* Specialization constants. We can treat the raw bytes as uint. */
281 hash ^= specialization_state.hash();
282
283 return hash;
284 }
285
286 /* Reset the Vertex Descriptor to default. */
288 {
289 vertex_descriptor.total_attributes = 0;
290 vertex_descriptor.max_attribute_value = 0;
291 vertex_descriptor.num_vert_buffers = 0;
292 vertex_descriptor.prim_topology_class = MTLPrimitiveTopologyClassUnspecified;
293 for (int i = 0; i < GPU_VERT_ATTR_MAX_LEN; i++) {
294 vertex_descriptor.attributes[i].reset();
295 }
296 }
297};
298
299/* Metal Compute Pipeline State Descriptor containing all unique information which feeds PSO
300 * creation. */
302
303 /* Specialization constants map. */
305
311
312 /* Comparison Operator for caching. */
314 {
316 }
317
319 {
320 return specialization_state.hash();
321 }
322};
323
324} // namespace blender::gpu
MINLINE unsigned int float_as_uint(float f)
unsigned char uchar
unsigned int uint
static constexpr int GPU_BATCH_VBO_MAX_LEN
Definition GPU_batch.hh:33
static constexpr int GPU_VERT_ATTR_MAX_LEN
GPUVertFetchMode
@ GPU_FETCH_FLOAT
unsigned long long int uint64_t
static unsigned long seed
Definition btSoftBody.h:39
#define GPU_FB_MAX_COLOR_ATTACHMENT
bool operator==(const MTLComputePipelineStateDescriptor &other) const
MTLComputePipelineStateDescriptor(Vector< shader::SpecializationConstant::Value > values)
MTLPixelFormat color_attachment_format[GPU_FB_MAX_COLOR_ATTACHMENT]
bool operator==(const MTLRenderPipelineStateDescriptor &other) const
bool operator==(const MTLVertexAttributeDescriptorPSO &other) const
bool operator==(const MTLVertexBufferLayoutDescriptorPSO &other) const
MTLVertexAttributeDescriptorPSO attributes[GPU_VERT_ATTR_MAX_LEN]
MTLVertexBufferLayoutDescriptorPSO buffer_layouts[GPU_BATCH_VBO_MAX_LEN]
bool operator==(const MTLVertexDescriptor &other) const
MTLPrimitiveTopologyClass prim_topology_class
SpecializationStateDescriptor(Vector< shader::SpecializationConstant::Value > source)
bool operator==(const SpecializationStateDescriptor &other) const
Vector< shader::SpecializationConstant::Value > values
i
Definition text_draw.cc:230