glsl: Evaluate constant pack/unpack 4x8 expressions
That is, evaluate constant expressions for the following functions: packSnorm4x8, unpackSnorm4x8 packUnorm4x8, unpackUnorm4x8 Reviewed-by: Chad Versace <chad.versace@linux.intel.com> Reviewed-by: Paul Berry <stereotype441@gmail.com>
This commit is contained in:
@@ -75,12 +75,24 @@ bitcast_f2u(float f)
|
|||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate one component of a floating-point 4x8 unpacking function.
|
||||||
|
*/
|
||||||
|
typedef uint8_t
|
||||||
|
(*pack_1x8_func_t)(float);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate one component of a floating-point 2x16 unpacking function.
|
* Evaluate one component of a floating-point 2x16 unpacking function.
|
||||||
*/
|
*/
|
||||||
typedef uint16_t
|
typedef uint16_t
|
||||||
(*pack_1x16_func_t)(float);
|
(*pack_1x16_func_t)(float);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate one component of a floating-point 4x8 unpacking function.
|
||||||
|
*/
|
||||||
|
typedef float
|
||||||
|
(*unpack_1x8_func_t)(uint8_t);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate one component of a floating-point 2x16 unpacking function.
|
* Evaluate one component of a floating-point 2x16 unpacking function.
|
||||||
*/
|
*/
|
||||||
@@ -111,6 +123,32 @@ pack_2x16(pack_1x16_func_t pack_1x16,
|
|||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate a 4x8 floating-point packing function.
|
||||||
|
*/
|
||||||
|
static uint32_t
|
||||||
|
pack_4x8(pack_1x8_func_t pack_1x8,
|
||||||
|
float x, float y, float z, float w)
|
||||||
|
{
|
||||||
|
/* From section 8.4 of the GLSL 4.30 spec:
|
||||||
|
*
|
||||||
|
* packSnorm4x8
|
||||||
|
* ------------
|
||||||
|
* The first component of the vector will be written to the least
|
||||||
|
* significant bits of the output; the last component will be written to
|
||||||
|
* the most significant bits.
|
||||||
|
*
|
||||||
|
* The specifications for the other packing functions contain similar
|
||||||
|
* language.
|
||||||
|
*/
|
||||||
|
uint32_t u = 0;
|
||||||
|
u |= ((uint32_t) pack_1x8(x) << 0);
|
||||||
|
u |= ((uint32_t) pack_1x8(y) << 8);
|
||||||
|
u |= ((uint32_t) pack_1x8(z) << 16);
|
||||||
|
u |= ((uint32_t) pack_1x8(w) << 24);
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate a 2x16 floating-point unpacking function.
|
* Evaluate a 2x16 floating-point unpacking function.
|
||||||
*/
|
*/
|
||||||
@@ -134,6 +172,52 @@ unpack_2x16(unpack_1x16_func_t unpack_1x16,
|
|||||||
*y = unpack_1x16((uint16_t) (u >> 16));
|
*y = unpack_1x16((uint16_t) (u >> 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate a 4x8 floating-point unpacking function.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
unpack_4x8(unpack_1x8_func_t unpack_1x8, uint32_t u,
|
||||||
|
float *x, float *y, float *z, float *w)
|
||||||
|
{
|
||||||
|
/* From section 8.4 of the GLSL 4.30 spec:
|
||||||
|
*
|
||||||
|
* unpackSnorm4x8
|
||||||
|
* --------------
|
||||||
|
* The first component of the returned vector will be extracted from
|
||||||
|
* the least significant bits of the input; the last component will be
|
||||||
|
* extracted from the most significant bits.
|
||||||
|
*
|
||||||
|
* The specifications for the other unpacking functions contain similar
|
||||||
|
* language.
|
||||||
|
*/
|
||||||
|
*x = unpack_1x8((uint8_t) (u & 0xff));
|
||||||
|
*y = unpack_1x8((uint8_t) (u >> 8));
|
||||||
|
*z = unpack_1x8((uint8_t) (u >> 16));
|
||||||
|
*w = unpack_1x8((uint8_t) (u >> 24));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate one component of packSnorm4x8.
|
||||||
|
*/
|
||||||
|
static uint8_t
|
||||||
|
pack_snorm_1x8(float x)
|
||||||
|
{
|
||||||
|
/* From section 8.4 of the GLSL 4.30 spec:
|
||||||
|
*
|
||||||
|
* packSnorm4x8
|
||||||
|
* ------------
|
||||||
|
* The conversion for component c of v to fixed point is done as
|
||||||
|
* follows:
|
||||||
|
*
|
||||||
|
* packSnorm4x8: round(clamp(c, -1, +1) * 127.0)
|
||||||
|
*
|
||||||
|
* We must first cast the float to an int, because casting a negative
|
||||||
|
* float to a uint is undefined.
|
||||||
|
*/
|
||||||
|
return (uint8_t) (int8_t)
|
||||||
|
_mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 127.0f);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate one component of packSnorm2x16.
|
* Evaluate one component of packSnorm2x16.
|
||||||
*/
|
*/
|
||||||
@@ -156,6 +240,24 @@ pack_snorm_1x16(float x)
|
|||||||
_mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 32767.0f);
|
_mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 32767.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate one component of unpackSnorm4x8.
|
||||||
|
*/
|
||||||
|
static float
|
||||||
|
unpack_snorm_1x8(uint8_t u)
|
||||||
|
{
|
||||||
|
/* From section 8.4 of the GLSL 4.30 spec:
|
||||||
|
*
|
||||||
|
* unpackSnorm4x8
|
||||||
|
* --------------
|
||||||
|
* The conversion for unpacked fixed-point value f to floating point is
|
||||||
|
* done as follows:
|
||||||
|
*
|
||||||
|
* unpackSnorm4x8: clamp(f / 127.0, -1, +1)
|
||||||
|
*/
|
||||||
|
return CLAMP((int8_t) u / 127.0f, -1.0f, +1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate one component of unpackSnorm2x16.
|
* Evaluate one component of unpackSnorm2x16.
|
||||||
*/
|
*/
|
||||||
@@ -174,6 +276,24 @@ unpack_snorm_1x16(uint16_t u)
|
|||||||
return CLAMP((int16_t) u / 32767.0f, -1.0f, +1.0f);
|
return CLAMP((int16_t) u / 32767.0f, -1.0f, +1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate one component packUnorm4x8.
|
||||||
|
*/
|
||||||
|
static uint8_t
|
||||||
|
pack_unorm_1x8(float x)
|
||||||
|
{
|
||||||
|
/* From section 8.4 of the GLSL 4.30 spec:
|
||||||
|
*
|
||||||
|
* packUnorm4x8
|
||||||
|
* ------------
|
||||||
|
* The conversion for component c of v to fixed point is done as
|
||||||
|
* follows:
|
||||||
|
*
|
||||||
|
* packUnorm4x8: round(clamp(c, 0, +1) * 255.0)
|
||||||
|
*/
|
||||||
|
return (uint8_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 255.0f);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate one component packUnorm2x16.
|
* Evaluate one component packUnorm2x16.
|
||||||
*/
|
*/
|
||||||
@@ -192,6 +312,24 @@ pack_unorm_1x16(float x)
|
|||||||
return (uint16_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 65535.0f);
|
return (uint16_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 65535.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate one component of unpackUnorm4x8.
|
||||||
|
*/
|
||||||
|
static float
|
||||||
|
unpack_unorm_1x8(uint8_t u)
|
||||||
|
{
|
||||||
|
/* From section 8.4 of the GLSL 4.30 spec:
|
||||||
|
*
|
||||||
|
* unpackUnorm4x8
|
||||||
|
* --------------
|
||||||
|
* The conversion for unpacked fixed-point value f to floating point is
|
||||||
|
* done as follows:
|
||||||
|
*
|
||||||
|
* unpackUnorm4x8: f / 255.0
|
||||||
|
*/
|
||||||
|
return (float) u / 255.0f;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate one component of unpackUnorm2x16.
|
* Evaluate one component of unpackUnorm2x16.
|
||||||
*/
|
*/
|
||||||
@@ -599,24 +737,52 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
|
|||||||
op[0]->value.f[0],
|
op[0]->value.f[0],
|
||||||
op[0]->value.f[1]);
|
op[0]->value.f[1]);
|
||||||
break;
|
break;
|
||||||
|
case ir_unop_pack_snorm_4x8:
|
||||||
|
assert(op[0]->type == glsl_type::vec4_type);
|
||||||
|
data.u[0] = pack_4x8(pack_snorm_1x8,
|
||||||
|
op[0]->value.f[0],
|
||||||
|
op[0]->value.f[1],
|
||||||
|
op[0]->value.f[2],
|
||||||
|
op[0]->value.f[3]);
|
||||||
|
break;
|
||||||
case ir_unop_unpack_snorm_2x16:
|
case ir_unop_unpack_snorm_2x16:
|
||||||
assert(op[0]->type == glsl_type::uint_type);
|
assert(op[0]->type == glsl_type::uint_type);
|
||||||
unpack_2x16(unpack_snorm_1x16,
|
unpack_2x16(unpack_snorm_1x16,
|
||||||
op[0]->value.u[0],
|
op[0]->value.u[0],
|
||||||
&data.f[0], &data.f[1]);
|
&data.f[0], &data.f[1]);
|
||||||
break;
|
break;
|
||||||
|
case ir_unop_unpack_snorm_4x8:
|
||||||
|
assert(op[0]->type == glsl_type::uint_type);
|
||||||
|
unpack_4x8(unpack_snorm_1x8,
|
||||||
|
op[0]->value.u[0],
|
||||||
|
&data.f[0], &data.f[1], &data.f[2], &data.f[3]);
|
||||||
|
break;
|
||||||
case ir_unop_pack_unorm_2x16:
|
case ir_unop_pack_unorm_2x16:
|
||||||
assert(op[0]->type == glsl_type::vec2_type);
|
assert(op[0]->type == glsl_type::vec2_type);
|
||||||
data.u[0] = pack_2x16(pack_unorm_1x16,
|
data.u[0] = pack_2x16(pack_unorm_1x16,
|
||||||
op[0]->value.f[0],
|
op[0]->value.f[0],
|
||||||
op[0]->value.f[1]);
|
op[0]->value.f[1]);
|
||||||
break;
|
break;
|
||||||
|
case ir_unop_pack_unorm_4x8:
|
||||||
|
assert(op[0]->type == glsl_type::vec4_type);
|
||||||
|
data.u[0] = pack_4x8(pack_unorm_1x8,
|
||||||
|
op[0]->value.f[0],
|
||||||
|
op[0]->value.f[1],
|
||||||
|
op[0]->value.f[2],
|
||||||
|
op[0]->value.f[3]);
|
||||||
|
break;
|
||||||
case ir_unop_unpack_unorm_2x16:
|
case ir_unop_unpack_unorm_2x16:
|
||||||
assert(op[0]->type == glsl_type::uint_type);
|
assert(op[0]->type == glsl_type::uint_type);
|
||||||
unpack_2x16(unpack_unorm_1x16,
|
unpack_2x16(unpack_unorm_1x16,
|
||||||
op[0]->value.u[0],
|
op[0]->value.u[0],
|
||||||
&data.f[0], &data.f[1]);
|
&data.f[0], &data.f[1]);
|
||||||
break;
|
break;
|
||||||
|
case ir_unop_unpack_unorm_4x8:
|
||||||
|
assert(op[0]->type == glsl_type::uint_type);
|
||||||
|
unpack_4x8(unpack_unorm_1x8,
|
||||||
|
op[0]->value.u[0],
|
||||||
|
&data.f[0], &data.f[1], &data.f[2], &data.f[3]);
|
||||||
|
break;
|
||||||
case ir_unop_pack_half_2x16:
|
case ir_unop_pack_half_2x16:
|
||||||
assert(op[0]->type == glsl_type::vec2_type);
|
assert(op[0]->type == glsl_type::vec2_type);
|
||||||
data.u[0] = pack_2x16(pack_half_1x16,
|
data.u[0] = pack_2x16(pack_half_1x16,
|
||||||
|
Reference in New Issue
Block a user