Cleanup: Metal: Simplify mtl_convert_vertex_format

_No response_

Pull Request: https://projects.blender.org/blender/blender/pulls/130036
This commit is contained in:
Clément Foucault
2024-11-08 16:07:58 +01:00
committed by Clément Foucault
parent ceaa4fa8a1
commit 72b24fa336
3 changed files with 137 additions and 431 deletions

View File

@@ -327,12 +327,8 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts,
*
* NOTE: Even if full conversion is not supported, we may still partially perform an
* implicit conversion where possible, such as vector truncation or expansion. */
MTLVertexFormat converted_format;
bool can_convert = mtl_vertex_format_resize(
mtl_attr.format, a->comp_len, &converted_format);
desc.vertex_descriptor.attributes[mtl_attr.location].format = can_convert ?
converted_format :
mtl_attr.format;
MTLVertexFormat converted_format = format_resize_comp(mtl_attr.format, a->comp_len);
desc.vertex_descriptor.attributes[mtl_attr.location].format = converted_format;
desc.vertex_descriptor.attributes[mtl_attr.location].format_conversion_mode =
(GPUVertFetchMode)a->fetch_mode;
BLI_assert(desc.vertex_descriptor.attributes[mtl_attr.location].format !=

View File

@@ -201,11 +201,9 @@ void MTLImmediate::end()
* and will generate an appropriate conversion function when reading the vertex attribute
* value into local shader storage.
* (If no explicit conversion is needed, the function specialize to a pass-through). */
MTLVertexFormat converted_format;
bool can_convert = mtl_vertex_format_resize(
mtl_shader_attribute.format, attr->comp_len, &converted_format);
desc.vertex_descriptor.attributes[i].format = (can_convert) ? converted_format :
mtl_shader_attribute.format;
MTLVertexFormat converted_format = format_resize_comp(mtl_shader_attribute.format,
attr->comp_len);
desc.vertex_descriptor.attributes[i].format = converted_format;
desc.vertex_descriptor.attributes[i].format_conversion_mode = (GPUVertFetchMode)
attr->fetch_mode;
BLI_assert(desc.vertex_descriptor.attributes[i].format != MTLVertexFormatInvalid);

View File

@@ -513,271 +513,46 @@ class MTLShaderCompiler : public ShaderCompiler {
* Implicitly supported conversions in Metal are described here:
* https://developer.apple.com/documentation/metal/mtlvertexattributedescriptor/1516081-format?language=objc
*/
inline bool mtl_vertex_format_resize(MTLVertexFormat mtl_format,
uint32_t components,
MTLVertexFormat *r_convertedFormat)
inline MTLVertexFormat format_resize_comp(MTLVertexFormat mtl_format, uint32_t components)
{
MTLVertexFormat out_vert_format = MTLVertexFormatInvalid;
#define RESIZE_TYPE(_type, _suffix) \
case MTLVertexFormat##_type##_suffix: \
case MTLVertexFormat##_type##2##_suffix: \
case MTLVertexFormat##_type##3##_suffix: \
case MTLVertexFormat##_type##4##_suffix: \
switch (components) { \
case 1: \
return MTLVertexFormat##_type##_suffix; \
case 2: \
return MTLVertexFormat##_type##2##_suffix; \
case 3: \
return MTLVertexFormat##_type##3##_suffix; \
case 4: \
return MTLVertexFormat##_type##4##_suffix; \
} \
break;
switch (mtl_format) {
/* Char. */
case MTLVertexFormatChar:
case MTLVertexFormatChar2:
case MTLVertexFormatChar3:
case MTLVertexFormatChar4:
switch (components) {
case 1:
out_vert_format = MTLVertexFormatChar;
break;
case 2:
out_vert_format = MTLVertexFormatChar2;
break;
case 3:
out_vert_format = MTLVertexFormatChar3;
break;
case 4:
out_vert_format = MTLVertexFormatChar4;
break;
}
break;
/* Normalized Char. */
case MTLVertexFormatCharNormalized:
case MTLVertexFormatChar2Normalized:
case MTLVertexFormatChar3Normalized:
case MTLVertexFormatChar4Normalized:
switch (components) {
case 1:
out_vert_format = MTLVertexFormatCharNormalized;
break;
case 2:
out_vert_format = MTLVertexFormatChar2Normalized;
break;
case 3:
out_vert_format = MTLVertexFormatChar3Normalized;
break;
case 4:
out_vert_format = MTLVertexFormatChar4Normalized;
break;
}
break;
/* Unsigned Char. */
case MTLVertexFormatUChar:
case MTLVertexFormatUChar2:
case MTLVertexFormatUChar3:
case MTLVertexFormatUChar4:
switch (components) {
case 1:
out_vert_format = MTLVertexFormatUChar;
break;
case 2:
out_vert_format = MTLVertexFormatUChar2;
break;
case 3:
out_vert_format = MTLVertexFormatUChar3;
break;
case 4:
out_vert_format = MTLVertexFormatUChar4;
break;
}
break;
/* Normalized Unsigned char */
case MTLVertexFormatUCharNormalized:
case MTLVertexFormatUChar2Normalized:
case MTLVertexFormatUChar3Normalized:
case MTLVertexFormatUChar4Normalized:
switch (components) {
case 1:
out_vert_format = MTLVertexFormatUCharNormalized;
break;
case 2:
out_vert_format = MTLVertexFormatUChar2Normalized;
break;
case 3:
out_vert_format = MTLVertexFormatUChar3Normalized;
break;
case 4:
out_vert_format = MTLVertexFormatUChar4Normalized;
break;
}
break;
/* Short. */
case MTLVertexFormatShort:
case MTLVertexFormatShort2:
case MTLVertexFormatShort3:
case MTLVertexFormatShort4:
switch (components) {
case 1:
out_vert_format = MTLVertexFormatShort;
break;
case 2:
out_vert_format = MTLVertexFormatShort2;
break;
case 3:
out_vert_format = MTLVertexFormatShort3;
break;
case 4:
out_vert_format = MTLVertexFormatShort4;
break;
}
break;
/* Normalized Short. */
case MTLVertexFormatShortNormalized:
case MTLVertexFormatShort2Normalized:
case MTLVertexFormatShort3Normalized:
case MTLVertexFormatShort4Normalized:
switch (components) {
case 1:
out_vert_format = MTLVertexFormatShortNormalized;
break;
case 2:
out_vert_format = MTLVertexFormatShort2Normalized;
break;
case 3:
out_vert_format = MTLVertexFormatShort3Normalized;
break;
case 4:
out_vert_format = MTLVertexFormatShort4Normalized;
break;
}
break;
/* Unsigned Short. */
case MTLVertexFormatUShort:
case MTLVertexFormatUShort2:
case MTLVertexFormatUShort3:
case MTLVertexFormatUShort4:
switch (components) {
case 1:
out_vert_format = MTLVertexFormatUShort;
break;
case 2:
out_vert_format = MTLVertexFormatUShort2;
break;
case 3:
out_vert_format = MTLVertexFormatUShort3;
break;
case 4:
out_vert_format = MTLVertexFormatUShort4;
break;
}
break;
/* Normalized Unsigned Short. */
case MTLVertexFormatUShortNormalized:
case MTLVertexFormatUShort2Normalized:
case MTLVertexFormatUShort3Normalized:
case MTLVertexFormatUShort4Normalized:
switch (components) {
case 1:
out_vert_format = MTLVertexFormatUShortNormalized;
break;
case 2:
out_vert_format = MTLVertexFormatUShort2Normalized;
break;
case 3:
out_vert_format = MTLVertexFormatUShort3Normalized;
break;
case 4:
out_vert_format = MTLVertexFormatUShort4Normalized;
break;
}
break;
/* Integer. */
case MTLVertexFormatInt:
case MTLVertexFormatInt2:
case MTLVertexFormatInt3:
case MTLVertexFormatInt4:
switch (components) {
case 1:
out_vert_format = MTLVertexFormatInt;
break;
case 2:
out_vert_format = MTLVertexFormatInt2;
break;
case 3:
out_vert_format = MTLVertexFormatInt3;
break;
case 4:
out_vert_format = MTLVertexFormatInt4;
break;
}
break;
/* Unsigned Integer. */
case MTLVertexFormatUInt:
case MTLVertexFormatUInt2:
case MTLVertexFormatUInt3:
case MTLVertexFormatUInt4:
switch (components) {
case 1:
out_vert_format = MTLVertexFormatUInt;
break;
case 2:
out_vert_format = MTLVertexFormatUInt2;
break;
case 3:
out_vert_format = MTLVertexFormatUInt3;
break;
case 4:
out_vert_format = MTLVertexFormatUInt4;
break;
}
break;
/* Half. */
case MTLVertexFormatHalf:
case MTLVertexFormatHalf2:
case MTLVertexFormatHalf3:
case MTLVertexFormatHalf4:
switch (components) {
case 1:
out_vert_format = MTLVertexFormatHalf;
break;
case 2:
out_vert_format = MTLVertexFormatHalf2;
break;
case 3:
out_vert_format = MTLVertexFormatHalf3;
break;
case 4:
out_vert_format = MTLVertexFormatHalf4;
break;
}
break;
/* Float. */
case MTLVertexFormatFloat:
case MTLVertexFormatFloat2:
case MTLVertexFormatFloat3:
case MTLVertexFormatFloat4:
switch (components) {
case 1:
out_vert_format = MTLVertexFormatFloat;
break;
case 2:
out_vert_format = MTLVertexFormatFloat2;
break;
case 3:
out_vert_format = MTLVertexFormatFloat3;
break;
case 4:
out_vert_format = MTLVertexFormatFloat4;
break;
}
break;
/* Other formats */
RESIZE_TYPE(Char, )
RESIZE_TYPE(Char, Normalized)
RESIZE_TYPE(UChar, )
RESIZE_TYPE(UChar, Normalized)
RESIZE_TYPE(Short, )
RESIZE_TYPE(Short, Normalized)
RESIZE_TYPE(UShort, )
RESIZE_TYPE(UShort, Normalized)
RESIZE_TYPE(Int, )
RESIZE_TYPE(UInt, )
RESIZE_TYPE(Half, )
RESIZE_TYPE(Float, )
default:
out_vert_format = mtl_format;
/* Can only call this function on format that can be resized. */
BLI_assert_unreachable();
break;
}
*r_convertedFormat = out_vert_format;
return out_vert_format != MTLVertexFormatInvalid;
#undef RESIZE_TYPE
return MTLVertexFormatInvalid;
}
/**
@@ -800,11 +575,9 @@ inline bool mtl_convert_vertex_format(MTLVertexFormat shader_attrib_format,
GPUVertFetchMode fetch_mode,
MTLVertexFormat *r_convertedFormat)
{
bool normalized = (fetch_mode == GPU_FETCH_INT_TO_FLOAT_UNIT);
MTLVertexFormat out_vert_format = MTLVertexFormatInvalid;
switch (component_type) {
case GPU_COMP_I8:
switch (fetch_mode) {
case GPU_FETCH_INT:
@@ -813,14 +586,8 @@ inline bool mtl_convert_vertex_format(MTLVertexFormat shader_attrib_format,
shader_attrib_format == MTLVertexFormatChar3 ||
shader_attrib_format == MTLVertexFormatChar4)
{
/* No conversion Needed (as type matches) - Just a vector resize if needed. */
bool can_convert = mtl_vertex_format_resize(
shader_attrib_format, component_type, &out_vert_format);
/* Ensure format resize successful. */
BLI_assert(can_convert);
UNUSED_VARS_NDEBUG(can_convert);
out_vert_format = format_resize_comp(shader_attrib_format, component_type);
}
else if (shader_attrib_format == MTLVertexFormatInt4 && component_length == 4) {
/* Allow type expansion - Shader expects MTLVertexFormatInt4, we can supply a type
@@ -849,38 +616,33 @@ inline bool mtl_convert_vertex_format(MTLVertexFormat shader_attrib_format,
BLI_assert_msg(false,
"Source vertex data format is either Char, Char2, Char3, Char4 but "
"format in shader interface is NOT compatible.\n");
out_vert_format = MTLVertexFormatInvalid;
}
break;
/* Source vertex data is integer type, but shader interface type is floating point.
* If the input attribute is specified as normalized, we can convert. */
case GPU_FETCH_INT_TO_FLOAT_UNIT:
switch (component_length) {
case 1:
out_vert_format = MTLVertexFormatCharNormalized;
break;
case 2:
out_vert_format = MTLVertexFormatChar2Normalized;
break;
case 3:
out_vert_format = MTLVertexFormatChar3Normalized;
break;
case 4:
out_vert_format = MTLVertexFormatChar4Normalized;
break;
default:
BLI_assert_msg(false, "invalid vertex format");
}
break;
/* Cannot convert. */
case GPU_FETCH_FLOAT:
case GPU_FETCH_INT_TO_FLOAT:
case GPU_FETCH_INT_TO_FLOAT_UNIT:
if (normalized) {
switch (component_length) {
case 1:
out_vert_format = MTLVertexFormatCharNormalized;
break;
case 2:
out_vert_format = MTLVertexFormatChar2Normalized;
break;
case 3:
out_vert_format = MTLVertexFormatChar3Normalized;
break;
case 4:
out_vert_format = MTLVertexFormatChar4Normalized;
break;
default:
BLI_assert_msg(false, "invalid vertex format");
out_vert_format = MTLVertexFormatInvalid;
}
}
else {
/* Cannot convert. */
out_vert_format = MTLVertexFormatInvalid;
}
break;
}
break;
@@ -894,16 +656,8 @@ inline bool mtl_convert_vertex_format(MTLVertexFormat shader_attrib_format,
shader_attrib_format == MTLVertexFormatUChar3 ||
shader_attrib_format == MTLVertexFormatUChar4)
{
/* No conversion Needed (as type matches) - Just a vector resize if needed. */
bool can_convert = mtl_vertex_format_resize(
shader_attrib_format, component_length, &out_vert_format);
/* Ensure format resize successful. */
BLI_assert(can_convert);
UNUSED_VARS_NDEBUG(can_convert);
/* TODO(Metal): Add other format conversions if needed. Currently no attributes hit
* this path. */
out_vert_format = format_resize_comp(shader_attrib_format, component_type);
}
else if (shader_attrib_format == MTLVertexFormatUInt4 && component_length == 4) {
/* Allow type expansion - Shader expects MTLVertexFormatUInt4, we can supply a type
@@ -936,38 +690,33 @@ inline bool mtl_convert_vertex_format(MTLVertexFormat shader_attrib_format,
BLI_assert_msg(false,
"Source vertex data format is either UChar, UChar2, UChar3, UChar4 but "
"format in shader interface is NOT compatible.\n");
out_vert_format = MTLVertexFormatInvalid;
}
break;
/* Source vertex data is integral type, but shader interface type is floating point.
* If the input attribute is specified as normalized, we can convert. */
case GPU_FETCH_INT_TO_FLOAT_UNIT:
switch (component_length) {
case 1:
out_vert_format = MTLVertexFormatUCharNormalized;
break;
case 2:
out_vert_format = MTLVertexFormatUChar2Normalized;
break;
case 3:
out_vert_format = MTLVertexFormatUChar3Normalized;
break;
case 4:
out_vert_format = MTLVertexFormatUChar4Normalized;
break;
default:
BLI_assert_msg(false, "invalid vertex format");
}
break;
/* Cannot convert. */
case GPU_FETCH_FLOAT:
case GPU_FETCH_INT_TO_FLOAT:
case GPU_FETCH_INT_TO_FLOAT_UNIT:
if (normalized) {
switch (component_length) {
case 1:
out_vert_format = MTLVertexFormatUCharNormalized;
break;
case 2:
out_vert_format = MTLVertexFormatUChar2Normalized;
break;
case 3:
out_vert_format = MTLVertexFormatUChar3Normalized;
break;
case 4:
out_vert_format = MTLVertexFormatUChar4Normalized;
break;
default:
BLI_assert_msg(false, "invalid vertex format");
out_vert_format = MTLVertexFormatInvalid;
}
}
else {
/* Cannot convert. */
out_vert_format = MTLVertexFormatInvalid;
}
break;
}
break;
@@ -981,49 +730,39 @@ inline bool mtl_convert_vertex_format(MTLVertexFormat shader_attrib_format,
shader_attrib_format == MTLVertexFormatShort4)
{
/* No conversion Needed (as type matches) - Just a vector resize if needed. */
bool can_convert = mtl_vertex_format_resize(
shader_attrib_format, component_length, &out_vert_format);
/* Ensure conversion successful. */
BLI_assert(can_convert);
UNUSED_VARS_NDEBUG(can_convert);
out_vert_format = format_resize_comp(shader_attrib_format, component_type);
}
else {
BLI_assert_msg(false,
"Source vertex data format is either Short, Short2, Short3, Short4 but "
"format in shader interface is NOT compatible.\n");
out_vert_format = MTLVertexFormatInvalid;
}
break;
/* Source vertex data is integral type, but shader interface type is floating point.
* If the input attribute is specified as normalized, we can convert. */
case GPU_FETCH_INT_TO_FLOAT_UNIT:
switch (component_length) {
case 1:
out_vert_format = MTLVertexFormatShortNormalized;
break;
case 2:
out_vert_format = MTLVertexFormatShort2Normalized;
break;
case 3:
out_vert_format = MTLVertexFormatShort3Normalized;
break;
case 4:
out_vert_format = MTLVertexFormatShort4Normalized;
break;
default:
BLI_assert_msg(false, "invalid vertex format");
}
break;
/* Cannot convert. */
case GPU_FETCH_FLOAT:
case GPU_FETCH_INT_TO_FLOAT:
case GPU_FETCH_INT_TO_FLOAT_UNIT:
if (normalized) {
switch (component_length) {
case 1:
out_vert_format = MTLVertexFormatShortNormalized;
break;
case 2:
out_vert_format = MTLVertexFormatShort2Normalized;
break;
case 3:
out_vert_format = MTLVertexFormatShort3Normalized;
break;
case 4:
out_vert_format = MTLVertexFormatShort4Normalized;
break;
default:
BLI_assert_msg(false, "invalid vertex format");
out_vert_format = MTLVertexFormatInvalid;
}
}
else {
/* Cannot convert. */
out_vert_format = MTLVertexFormatInvalid;
}
break;
}
break;
@@ -1037,49 +776,39 @@ inline bool mtl_convert_vertex_format(MTLVertexFormat shader_attrib_format,
shader_attrib_format == MTLVertexFormatUShort4)
{
/* No conversion Needed (as type matches) - Just a vector resize if needed. */
bool can_convert = mtl_vertex_format_resize(
shader_attrib_format, component_length, &out_vert_format);
/* Ensure format resize successful. */
BLI_assert(can_convert);
UNUSED_VARS_NDEBUG(can_convert);
out_vert_format = format_resize_comp(shader_attrib_format, component_type);
}
else {
BLI_assert_msg(false,
"Source vertex data format is either UShort, UShort2, UShort3, UShort4 "
"but format in shader interface is NOT compatible.\n");
out_vert_format = MTLVertexFormatInvalid;
}
break;
/* Source vertex data is integral type, but shader interface type is floating point.
* If the input attribute is specified as normalized, we can convert. */
case GPU_FETCH_INT_TO_FLOAT_UNIT:
switch (component_length) {
case 1:
out_vert_format = MTLVertexFormatUShortNormalized;
break;
case 2:
out_vert_format = MTLVertexFormatUShort2Normalized;
break;
case 3:
out_vert_format = MTLVertexFormatUShort3Normalized;
break;
case 4:
out_vert_format = MTLVertexFormatUShort4Normalized;
break;
default:
BLI_assert_msg(false, "invalid vertex format");
}
break;
/* Cannot convert. */
case GPU_FETCH_FLOAT:
case GPU_FETCH_INT_TO_FLOAT:
case GPU_FETCH_INT_TO_FLOAT_UNIT:
if (normalized) {
switch (component_length) {
case 1:
out_vert_format = MTLVertexFormatUShortNormalized;
break;
case 2:
out_vert_format = MTLVertexFormatUShort2Normalized;
break;
case 3:
out_vert_format = MTLVertexFormatUShort3Normalized;
break;
case 4:
out_vert_format = MTLVertexFormatUShort4Normalized;
break;
default:
BLI_assert_msg(false, "invalid vertex format");
out_vert_format = MTLVertexFormatInvalid;
}
}
else {
/* Cannot convert. */
out_vert_format = MTLVertexFormatInvalid;
}
break;
}
break;
@@ -1093,25 +822,19 @@ inline bool mtl_convert_vertex_format(MTLVertexFormat shader_attrib_format,
shader_attrib_format == MTLVertexFormatInt4)
{
/* No conversion Needed (as type matches) - Just a vector resize if needed. */
bool can_convert = mtl_vertex_format_resize(
shader_attrib_format, component_length, &out_vert_format);
/* Verify conversion successful. */
BLI_assert(can_convert);
UNUSED_VARS_NDEBUG(can_convert);
out_vert_format = format_resize_comp(shader_attrib_format, component_type);
}
else {
BLI_assert_msg(false,
"Source vertex data format is either Int, Int2, Int3, Int4 but format "
"in shader interface is NOT compatible.\n");
out_vert_format = MTLVertexFormatInvalid;
}
break;
/* Cannot convert. */
case GPU_FETCH_FLOAT:
case GPU_FETCH_INT_TO_FLOAT:
case GPU_FETCH_INT_TO_FLOAT_UNIT:
/* Unfortunately we cannot implicitly convert between Int and Float in METAL. */
out_vert_format = MTLVertexFormatInvalid;
break;
}
break;
@@ -1125,61 +848,48 @@ inline bool mtl_convert_vertex_format(MTLVertexFormat shader_attrib_format,
shader_attrib_format == MTLVertexFormatUInt4)
{
/* No conversion Needed (as type matches) - Just a vector resize if needed. */
bool can_convert = mtl_vertex_format_resize(
shader_attrib_format, component_length, &out_vert_format);
/* Verify conversion successful. */
BLI_assert(can_convert);
UNUSED_VARS_NDEBUG(can_convert);
out_vert_format = format_resize_comp(shader_attrib_format, component_type);
}
else {
BLI_assert_msg(false,
"Source vertex data format is either UInt, UInt2, UInt3, UInt4 but "
"format in shader interface is NOT compatible.\n");
out_vert_format = MTLVertexFormatInvalid;
}
break;
case GPU_FETCH_FLOAT:
case GPU_FETCH_INT_TO_FLOAT:
case GPU_FETCH_INT_TO_FLOAT_UNIT:
BLI_assert_msg(false, "Unsupported GPU_FETCH_INT* mode for float attribute.\n");
/* Unfortunately we cannot convert between UInt and Float in METAL */
out_vert_format = MTLVertexFormatInvalid;
break;
}
break;
case GPU_COMP_F32:
switch (fetch_mode) {
/* Source data is float. This will be compatible
* if type specified in shader is also float. */
case GPU_FETCH_FLOAT:
case GPU_FETCH_INT_TO_FLOAT:
case GPU_FETCH_INT_TO_FLOAT_UNIT:
if (shader_attrib_format == MTLVertexFormatFloat ||
shader_attrib_format == MTLVertexFormatFloat2 ||
shader_attrib_format == MTLVertexFormatFloat3 ||
shader_attrib_format == MTLVertexFormatFloat4)
{
/* No conversion Needed (as type matches) - Just a vector resize, if needed. */
bool can_convert = mtl_vertex_format_resize(
shader_attrib_format, component_length, &out_vert_format);
/* Verify conversion successful. */
BLI_assert(can_convert);
UNUSED_VARS_NDEBUG(can_convert);
out_vert_format = format_resize_comp(shader_attrib_format, component_type);
}
else {
BLI_assert_msg(false,
"Source vertex data format is either Float, Float2, Float3, Float4 but "
"format in shader interface is NOT compatible.\n");
out_vert_format = MTLVertexFormatInvalid;
"Source vertex data format is either GPU_COMP_F32 but "
"format in shader interface is NOT float.\n");
}
break;
case GPU_FETCH_INT_TO_FLOAT:
case GPU_FETCH_INT_TO_FLOAT_UNIT:
case GPU_FETCH_INT:
BLI_assert_msg(false, "Unsupported GPU_FETCH_INT* mode for float attribute.\n");
/* Unfortunately we cannot convert between Float and Int implicitly in METAL. */
out_vert_format = MTLVertexFormatInvalid;
break;
}
break;
@@ -1187,10 +897,12 @@ inline bool mtl_convert_vertex_format(MTLVertexFormat shader_attrib_format,
case GPU_COMP_I10:
out_vert_format = MTLVertexFormatInt1010102Normalized;
break;
case GPU_COMP_MAX:
BLI_assert_unreachable();
break;
}
*r_convertedFormat = out_vert_format;
return (out_vert_format != MTLVertexFormatInvalid);
}