Changeset View
Standalone View
source/blender/gpu/intern/gpu_shader_create_info.hh
| Show All 26 Lines | # define GPU_SHADER_INTERFACE_INFO(_interface, _inst_name) \ | ||||
| StageInterfaceInfo _interface(#_interface, _inst_name); \ | StageInterfaceInfo _interface(#_interface, _inst_name); \ | ||||
| _interface | _interface | ||||
| # define GPU_SHADER_CREATE_INFO(_info) \ | # define GPU_SHADER_CREATE_INFO(_info) \ | ||||
| ShaderCreateInfo _info(#_info); \ | ShaderCreateInfo _info(#_info); \ | ||||
| _info | _info | ||||
| #endif | #endif | ||||
| enum class Type { | enum class Type { | ||||
| /* Types supported natively across all GPU backends. */ | |||||
| FLOAT = 0, | FLOAT = 0, | ||||
| VEC2, | VEC2, | ||||
| VEC3, | VEC3, | ||||
| VEC4, | VEC4, | ||||
| MAT3, | MAT3, | ||||
| MAT4, | MAT4, | ||||
| UINT, | UINT, | ||||
| UVEC2, | UVEC2, | ||||
| UVEC3, | UVEC3, | ||||
| UVEC4, | UVEC4, | ||||
| INT, | INT, | ||||
| IVEC2, | IVEC2, | ||||
| IVEC3, | IVEC3, | ||||
| IVEC4, | IVEC4, | ||||
| BOOL, | BOOL, | ||||
| /* Additionally supported types to enable data optimisation and native | |||||
| * support in some GPUBackends. | |||||
| * NOTE: These types must be representable in all APIs. E.g. VEC3_101010I2 is aliased as vec3 in | |||||
| * the GL backend, as implicit type conversions from packed normal attribute data to vec3 is | |||||
| * supported. UCHAR/CHAR types are natively supported in Metal and can be used to avoid | |||||
| * additional data conversions for GPU_COMP_U8 vertex attributes. */ | |||||
| VEC3_101010I2, | |||||
| UCHAR, | |||||
| UCHAR2, | |||||
| UCHAR3, | |||||
| UCHAR4, | |||||
| CHAR, | |||||
| CHAR2, | |||||
| CHAR3, | |||||
| CHAR4 | |||||
| }; | }; | ||||
| /* All of these functions is a bit out of place */ | /* All of these functions is a bit out of place */ | ||||
| static inline Type to_type(const eGPUType type) | static inline Type to_type(const eGPUType type) | ||||
| { | { | ||||
| switch (type) { | switch (type) { | ||||
| case GPU_FLOAT: | case GPU_FLOAT: | ||||
| return Type::FLOAT; | return Type::FLOAT; | ||||
| Show All 23 Lines | switch (type) { | ||||
| case Type::VEC3: | case Type::VEC3: | ||||
| return stream << "vec3"; | return stream << "vec3"; | ||||
| case Type::VEC4: | case Type::VEC4: | ||||
| return stream << "vec4"; | return stream << "vec4"; | ||||
| case Type::MAT3: | case Type::MAT3: | ||||
| return stream << "mat3"; | return stream << "mat3"; | ||||
| case Type::MAT4: | case Type::MAT4: | ||||
| return stream << "mat4"; | return stream << "mat4"; | ||||
| case Type::VEC3_101010I2: | |||||
| return stream << "vec3_1010102_Inorm"; | |||||
| case Type::UCHAR: | |||||
| return stream << "uchar"; | |||||
| case Type::UCHAR2: | |||||
| return stream << "uchar2"; | |||||
| case Type::UCHAR3: | |||||
| return stream << "uchar3"; | |||||
| case Type::UCHAR4: | |||||
| return stream << "uchar4"; | |||||
| case Type::CHAR: | |||||
| return stream << "char"; | |||||
| case Type::CHAR2: | |||||
| return stream << "char2"; | |||||
| case Type::CHAR3: | |||||
| return stream << "char3"; | |||||
| case Type::CHAR4: | |||||
| return stream << "char4"; | |||||
| case Type::INT: | |||||
| return stream << "int"; | |||||
| case Type::IVEC2: | |||||
| return stream << "ivec2"; | |||||
| case Type::IVEC3: | |||||
| return stream << "ivec3"; | |||||
| case Type::IVEC4: | |||||
| return stream << "ivec4"; | |||||
| case Type::UINT: | |||||
| return stream << "uint"; | |||||
| case Type::UVEC2: | |||||
| return stream << "uvec2"; | |||||
| case Type::UVEC3: | |||||
| return stream << "uvec3"; | |||||
| case Type::UVEC4: | |||||
| return stream << "uvec4"; | |||||
fclem: I am not sure what are theses for. Completion? `char` is not a GLSL type and neither… | |||||
Not Done Inline ActionsThese additional types were added to provide direct type mapping between actual input vertex types and their corresponding type inside a Metal shader. Given Metal does not support as many implicit type conversions as Metal, it is more convenient and optimal to allow data to be directly passed. Two use-cases for this are in the edit_mesh_vert shader. Where input vertex data can be in several forms, but is used as follows in the Geometry shader alternative path (not included in this PR): .vertex_in(0, Type::VEC3, "pos") .vertex_in(1, Type::UCHAR4, "data") .vertex_in(2, Type::VEC3_101010I2, "vnor") or .vertex_in(0, Type::VEC3, "pos") .vertex_in(1, Type::UCHAR4, "data") .vertex_in(2, Type::VEC3, "vnor") vs original: .vertex_in(0, Type::VEC3, "pos") .vertex_in(1, Type::IVEC4, "data") .vertex_in(2, Type::VEC3, "vnor") For the "data" vertex attributes, these are often encoded as a UChar4 in the vertex format: GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT); Conversion from a UChar4 vertex attribute input data to a UInt4 vertex attribute in the shader is invalid in Metal via implicit conversion. Therefore, under the Metal path, changing the input type in the Shader create info to UCHAR4 allows us to directly read that data as-is. The GLSL path then has a macro to map char types to integer types, such that implicit shader conversion still works in the same way as the original version. e.g. #define uchar4 uvec4 This could likely be handled in a different way, and a number of these types were added for thoroughness, though given these are not supported by GLSL directly, perhaps a different approach is best. It's also worth noting that vec3_1010102_Inorm is also not a valid literal type in Metal, but this was a type alias, again converted back by macro, to explicitly allow direct data mapping, specifically in this case for SSBO vertex fetch, which needs to interpret a compressed vector manually. In GLSL, this macro converted the type directly to vec3, to allow implicit vertex assembly to populate the values: For Metal, this instead uses an int as a backing store in the shader, and a special vertex attribute read routine to unpack into a vec3 during ssbo vertex fetch, as vertex assembly isn't used in this mode: MichaelPW: These additional types were added to provide direct type mapping between actual input vertex… | |||||
Not Done Inline ActionsOkay, I don't have issue with them being added. But it might be confusing for user of the API as these are reserved for internal Metal backend usage. Make sure to make that clear inside enum class Type by separating the new types with a comment. We might use them directly in the future if they prove to reduce code complexity. fclem: Okay, I don't have issue with them being added. But it might be confusing for user of the API… | |||||
| default: | default: | ||||
| BLI_assert(0); | BLI_assert(0); | ||||
| return stream; | return stream; | ||||
| } | } | ||||
| } | } | ||||
| static inline std::ostream &operator<<(std::ostream &stream, const eGPUType type) | static inline std::ostream &operator<<(std::ostream &stream, const eGPUType type) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | enum class PrimitiveIn { | ||||
| TRIANGLES_ADJACENCY, | TRIANGLES_ADJACENCY, | ||||
| }; | }; | ||||
| /** Output layout for geometry shader. */ | /** Output layout for geometry shader. */ | ||||
| enum class PrimitiveOut { | enum class PrimitiveOut { | ||||
| POINTS = 0, | POINTS = 0, | ||||
| LINE_STRIP, | LINE_STRIP, | ||||
| TRIANGLE_STRIP, | TRIANGLE_STRIP, | ||||
| LINES, | |||||
| TRIANGLES, | |||||
| }; | }; | ||||
| struct StageInterfaceInfo { | struct StageInterfaceInfo { | ||||
| struct InOut { | struct InOut { | ||||
| Interpolation interp; | Interpolation interp; | ||||
| Type type; | Type type; | ||||
| StringRefNull name; | StringRefNull name; | ||||
| }; | }; | ||||
| ▲ Show 20 Lines • Show All 341 Lines • ▼ Show 20 Lines | public: | ||||
| Self &uniform_buf(int slot, | Self &uniform_buf(int slot, | ||||
| StringRefNull type_name, | StringRefNull type_name, | ||||
| StringRefNull name, | StringRefNull name, | ||||
| Frequency freq = Frequency::PASS) | Frequency freq = Frequency::PASS) | ||||
| { | { | ||||
| Resource res(Resource::BindType::UNIFORM_BUFFER, slot); | Resource res(Resource::BindType::UNIFORM_BUFFER, slot); | ||||
| res.uniformbuf.name = name; | res.uniformbuf.name = name; | ||||
| res.uniformbuf.type_name = type_name; | res.uniformbuf.type_name = type_name; | ||||
Not Done Inline ActionsI am unsure if this is a good name nor if this is the right place for this workaround. I would have guess that the shader should just be different for Metal. Maybe it still needs to be (as it is not included in this PR, I can't say). But to me the option should just be a boolean or a function to transform any vertex_in into a SSBO bind. fclem: I am unsure if this is a good name nor if this is the right place for this workaround. I would… | |||||
Not Done Inline ActionsFollowing separate discussions on BlenderChat and to make a more permanent note here, the overall geometry shader alternative path could certainly be done in another way. In this case, the Create-info change is to register the data which would be specified in the current: Though it was a slight oversight of me not completely remove the other path for detecting the pragma string. These data points aim to match the same input as the geometry shader. The aim is that for each input primitive, we specify the type of output primitive and number of desired output vertices. i.e. for 3D poly line, to take an example where your input primitive type is LineList. To generate a wide line using a quad, we would use TriangleList as the output primitive type, and specify 6 vertices to create two triangles per input line. Under the hood, when this draw call is executed, rather than executing a line draw, the backend will execute a draw using TriangleList and multiply the output vertices by the number of input primitives to invoke that many instances of the vertex shader. There are other cases such as Workbench shadows where the output vertex count can be up to 12 vertices at most. However, yes, at the moment, use of this line implies use of SSBO vertex fetch mode being enabled, in much the same way as if .geometry_layout( or .geometry_source( are specified. Happy to either add an explicit create-info line to enable this, or also add a boolean param to specify whether it is enabled if this is preferred? MichaelPW: Following separate discussions on BlenderChat and to make a more permanent note here, the… | |||||
Not Done Inline ActionsSince the shaders are different implementation alltogether, I would like to have different create infos. The workaround one should replace the standard one just like that draw_modelmat = draw_modelmat_legacy; in gpu_shader_create_info.cc. So the create_info API should not have any change to support this. fclem: Since the shaders are different implementation alltogether, I would like to have different… | |||||
Not Done Inline ActionsRight, so currently they do have different create info's (again not included in this PR), though like with geometry shaders, those new create-info's require some configuration to declare how the SSBO vertex fetch mode invokes a draw. I can remove these configurations in gpu_shader_create_info.cc if this is not desired, though this would mean needing to use something like the existing pragma inside the non-geometry-shader variant of the source: For a little bit of context, this is an example of create info for gpu_shader_3D_polyline using a non-geometry-shader variant which relies on SSBO vertex fetch: GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline)
.define("SMOOTH_WIDTH", "1.0")
.push_constant(Type::MAT4, "ModelViewProjectionMatrix")
.push_constant(Type::VEC2, "viewportSize")
.push_constant(Type::FLOAT, "lineWidth")
.push_constant(Type::BOOL, "lineSmooth")
.vertex_in(0, Type::VEC3, "pos")
.vertex_out(gpu_shader_3D_polyline_iface)
.geometry_layout(PrimitiveIn::LINES, PrimitiveOut::TRIANGLE_STRIP, 4)
.geometry_out(gpu_shader_3D_polyline_iface)
.fragment_out(0, Type::VEC4, "fragColor")
.vertex_source("gpu_shader_3D_polyline_vert.glsl")
.geometry_source("gpu_shader_3D_polyline_geom.glsl")
.fragment_source("gpu_shader_3D_polyline_frag.glsl")
.additional_info("gpu_srgb_to_framebuffer_space");
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_no_geom)
.define("SMOOTH_WIDTH", "1.0")
.push_constant(Type::MAT4, "ModelViewProjectionMatrix")
.push_constant(Type::VEC2, "viewportSize")
.push_constant(Type::FLOAT, "lineWidth")
.push_constant(Type::BOOL, "lineSmooth")
.vertex_in(0, Type::VEC3, "pos")
.vertex_out(gpu_shader_3D_polyline_iface)
.ssbo_vertex_fetch_out(PrimitiveOut::TRIANGLES, 6)
.fragment_out(0, Type::VEC4, "fragColor")
.vertex_source("gpu_shader_3D_polyline_vert_no_geom.glsl")
.fragment_source("gpu_shader_3D_polyline_frag.glsl")
.additional_info("gpu_srgb_to_framebuffer_space");Perhaps best to remove this from this PR anyhow, and instead use a future PR which has a little more context for this solution? MichaelPW: Right, so currently they do have different create info's (again not included in this PR)… | |||||
| ((freq == Frequency::PASS) ? pass_resources_ : batch_resources_).append(res); | ((freq == Frequency::PASS) ? pass_resources_ : batch_resources_).append(res); | ||||
| interface_names_size_ += name.size() + 1; | interface_names_size_ += name.size() + 1; | ||||
| return *(Self *)this; | return *(Self *)this; | ||||
| } | } | ||||
| Self &storage_buf(int slot, | Self &storage_buf(int slot, | ||||
| Qualifier qualifiers, | Qualifier qualifiers, | ||||
| StringRefNull type_name, | StringRefNull type_name, | ||||
| ▲ Show 20 Lines • Show All 299 Lines • Show Last 20 Lines | |||||
I am not sure what are theses for. Completion? char is not a GLSL type and neither vec3_1010102_Inorm. Is it for pyGPU support?