Blender V4.3
mtl_shader_generator.hh File Reference

Go to the source code of this file.

Classes

struct  blender::gpu::MSLUniform
 
struct  blender::gpu::MSLConstant
 
struct  blender::gpu::MSLBufferBlock
 
struct  blender::gpu::MSLTextureResource
 
struct  blender::gpu::MSLVertexInputAttribute
 
struct  blender::gpu::MSLVertexOutputAttribute
 
struct  blender::gpu::MSLFragmentOutputAttribute
 
struct  blender::gpu::MSLSharedMemoryBlock
 
class  blender::gpu::MSLGeneratorInterface
 

Namespaces

namespace  blender
 
namespace  blender::gpu
 

Macros

#define UNIFORM_SSBO_USES_INDEXED_RENDERING_STR   "uniform_ssbo_uses_indexed_rendering"
 
#define UNIFORM_SSBO_INDEX_MODE_U16_STR   "uniform_ssbo_index_mode_u16"
 
#define UNIFORM_SSBO_INPUT_PRIM_TYPE_STR   "uniform_ssbo_input_prim_type"
 
#define UNIFORM_SSBO_INPUT_VERT_COUNT_STR   "uniform_ssbo_input_vert_count"
 
#define UNIFORM_SSBO_INDEX_BASE_STR   "uniform_ssbo_index_base_"
 
#define UNIFORM_SSBO_OFFSET_STR   "uniform_ssbo_offset_"
 
#define UNIFORM_SSBO_STRIDE_STR   "uniform_ssbo_stride_"
 
#define UNIFORM_SSBO_FETCHMODE_STR   "uniform_ssbo_fetchmode_"
 
#define UNIFORM_SSBO_VBO_ID_STR   "uniform_ssbo_vbo_id_"
 
#define UNIFORM_SSBO_TYPE_STR   "uniform_ssbo_type_"
 

Typedefs

using blender::gpu::MSLFragmentTileInputAttribute = MSLFragmentOutputAttribute
 

Enumerations

enum  blender::gpu::MSLTextureSamplerAccess {
  blender::gpu::TEXTURE_ACCESS_NONE = 0 , blender::gpu::TEXTURE_ACCESS_SAMPLE , blender::gpu::TEXTURE_ACCESS_READ , blender::gpu::TEXTURE_ACCESS_WRITE ,
  blender::gpu::TEXTURE_ACCESS_READWRITE
}
 

Functions

const char * blender::gpu::get_stage_class_name (ShaderStage stage)
 
const char * blender::gpu::get_shader_stage_instance_name (ShaderStage stage)
 
bool blender::gpu::is_builtin_type (std::string type)
 
bool blender::gpu::is_matrix_type (const std::string &type)
 
bool blender::gpu::is_matrix_type (const shader::Type &type)
 
int blender::gpu::get_matrix_location_count (const std::string &type)
 
int blender::gpu::get_matrix_location_count (const shader::Type &type)
 
std::string blender::gpu::get_matrix_subtype (const std::string &type)
 
shader::Type blender::gpu::get_matrix_subtype (const shader::Type &type)
 
std::string blender::gpu::get_attribute_conversion_function (bool *uses_conversion, const shader::Type &type)
 
const char * blender::gpu::to_string_msl (const shader::Interpolation &interp)
 
char * blender::gpu::next_symbol_in_range (char *begin, char *end, char symbol)
 
char * blender::gpu::next_word_in_range (char *begin, char *end)
 
Create Info
const char * blender::gpu::to_string (const shader::PrimitiveOut &layout)
 
const char * blender::gpu::to_string (const shader::PrimitiveIn &layout)
 
const char * blender::gpu::to_string (const shader::Interpolation &interp)
 
const char * blender::gpu::to_string (const shader::Type &type)
 

Macro Definition Documentation

◆ UNIFORM_SSBO_FETCHMODE_STR

#define UNIFORM_SSBO_FETCHMODE_STR   "uniform_ssbo_fetchmode_"

◆ UNIFORM_SSBO_INDEX_BASE_STR

#define UNIFORM_SSBO_INDEX_BASE_STR   "uniform_ssbo_index_base_"

◆ UNIFORM_SSBO_INDEX_MODE_U16_STR

#define UNIFORM_SSBO_INDEX_MODE_U16_STR   "uniform_ssbo_index_mode_u16"

◆ UNIFORM_SSBO_INPUT_PRIM_TYPE_STR

#define UNIFORM_SSBO_INPUT_PRIM_TYPE_STR   "uniform_ssbo_input_prim_type"

◆ UNIFORM_SSBO_INPUT_VERT_COUNT_STR

#define UNIFORM_SSBO_INPUT_VERT_COUNT_STR   "uniform_ssbo_input_vert_count"

◆ UNIFORM_SSBO_OFFSET_STR

◆ UNIFORM_SSBO_STRIDE_STR

◆ UNIFORM_SSBO_TYPE_STR

◆ UNIFORM_SSBO_USES_INDEXED_RENDERING_STR

#define UNIFORM_SSBO_USES_INDEXED_RENDERING_STR   "uniform_ssbo_uses_indexed_rendering"

– Metal Shader Generator for GLSL -> MSL conversion –

The Metal shader generator class is used as a conversion utility for generating a compatible MSL shader from a source GLSL shader. There are several steps involved in creating a shader, and structural changes which enable the source to function in the same way.

1) Extraction and conversion of shaders input's and output's to their Metal-compatible version. This is a subtle data transformation from GPUShaderCreateInfo, allowing for Metal-specific parameters.

2) Determine usage of shader features such as GL global variable usage, depth write output, clip distances, multilayered rendering, barycentric coordinates etc;

3) Generate MSL shader.

4) Populate #MTLShaderInterface, describing input/output structure, bind-points, buffer size and alignment, shader feature usage etc; Everything required by the Metal back-end to successfully enable use of shaders and GPU back-end features.

For each shading stage, we generate an MSL shader following these steps:

1) Output custom shader defines describing modes e.g. whether we are using sampler bindings or argument buffers; at the top of the shader.

2) Inject common Metal headers.

  • mtl_shader_defines.msl is used to map GLSL functions to MSL.
  • mtl_shader_common.msl is added to ALL MSL shaders to provide common functionality required by the back-end. This primarily contains function-constant hooks, used in PSO generation.

3) Create a class Scope which wraps the GLSL shader. This is used to create a global per-thread scope around the shader source, to allow access to common shader members (GLSL globals, shader inputs/outputs etc)

4) Generate shader interface structs and populate local members where required for:

  • VertexInputs
  • VertexOutputs
  • Uniforms
  • Uniform Blocks
  • textures ; etc;

5) Inject GLSL source.

6) Generate MSL shader entry point function. Every Metal shader must have a vertex/fragment/kernel entry-point, which contains the function binding table. This is where bindings are specified and passed into the shader.

For converted shaders, the MSL entry-point will also instantiate a shader class per thread, and pass over bound resource references into the class.

Finally, the shaders "main()" method will be called, and outputs are copied.

NOTE: For position outputs, the default output position will be converted to the Metal coordinate space, which involves flipping the Y coordinate and re-mapping the depth range between 0 and 1, as with Vulkan.

The final shader structure looks as follows:

-- Shader defines --
#define USE_ARGUMENT_BUFFER_FOR_SAMPLERS 0
... etc ...;
class MetalShaderVertexImp {
-- Common shader interface structs --
struct VertexIn {
}
struct VertexOut {...}
struct PushConstantBlock {...}
struct drw_Globals {...}
...
-- GLSL source code --
...
};
vertex MetalShaderVertexImp::VertexOut vertex_function_entry(
MetalShaderVertexImp::VertexIn v_in [[stage_in]],
constant PushConstantBlock& globals [[buffer(MTL_uniform_buffer_base_index)]]) {
MetalShaderVertexImp impl;
-- Copy input members into impl instance --
-- Execute GLSL main function --
impl.main();
-- Copy outputs and return --
MetalShaderVertexImp::VertexOut out;
out.pos = impl.pos;
-- transform position to Metal coordinate system --
return v_out;
}
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
velocity_obj_prev_buf[] vec4
static char ** members
Definition makesdna.cc:69
int main()
static IOCIOImpl * impl
Definition ocio_capi.cc:9

– Metal buffer bindings structure –

Metal shader contains several different binding types. All buffers are bound using the buffer(N) binding attribute tag. However, different ranges serve different purposes. The structure of the bindings always happen as follows:

Vertex Buffers (N) <– 0 Index buffer Default Push constant block for uniforms <– MTL_uniform_buffer_base_index Uniform buffers <– MTL_uniform_buffer_base_index+1 Storage buffers <– MTL_storage_buffer_base_index Samplers/argument buffer table <– last buffer + 1 Transform feedback buffer <– MTL_transform_feedback_buffer_index ~last_buffer+2

Up to a maximum of 31 bindings.

– SSBO-vertex-fetchmode –

SSBO-vertex-fetchmode is a special option wherein vertex buffers are bound directly as buffers in the shader, rather than using the VertexDescriptor and [[stage_in]] vertex assembly.

The purpose of this mode is to enable random-access reading of all vertex data. This is particularly useful for efficiently converting geometry shaders to Metal shading language, as these techniques are not supported natively in Metal.

Geometry shaders can be re-created by firing off a vertex shader with the desired number of total output vertices. Each vertex can then read whichever input attributes it needs to achieve the output result. This manual reading is also used to provide support for GPU_provoking_vertex, wherein the output vertex for flat shading needs to change. In these cases, the manual vertex assembly can flip which vertices are read within the primitive.

From an efficiency perspective, this is more GPU-friendly than geometry shading, due to improved parallelism throughout the whole pipe, and for Apple hardware specifically, there is no significant performance loss from manual vertex assembly vs under-the-hood assembly.

This mode works by passing the required vertex descriptor information into the shader as uniform data, describing the type, stride, offset, step-mode and buffer index of each attribute, such that the shader SSBO-vertex-fetch utility functions know how to extract data.

This also works with indexed rendering, by similarly binding the index buffer as a manual buffer.

When this mode is used, the code generation and shader interface generation varies to accommodate the required features.

This mode can be enabled in a shader with:

#pragma USE_SSBO_VERTEX_FETCH(TriangleList/LineList, output_vertex_count_per_input_primitive)

This mirrors the geometry shader interface layout(triangle_strip, max_vertices = 3) out;

Definition at line 173 of file mtl_shader_generator.hh.

Referenced by blender::gpu::MTLShader::prepare_ssbo_vertex_fetch_metadata(), and blender::gpu::MSLGeneratorInterface::prepare_ssbo_vertex_fetch_uniforms().

◆ UNIFORM_SSBO_VBO_ID_STR