finish up constants
For whatever reason, if I swap the condition in the if_then_else tests from < to >= and swap the then/else values, I can use constants in hsl_to_rgb. Still don't understand why, but I'll take it. I suspect it has something to do with SSE, IEEE, and NaN, but I don't care enough to speculate any more concretely. This does that, removes C() and _f, updates some comments, and adds a guard in build_stages.py to yell if it sees trouble like LCPI40_4... This reminds me to try -ffast-math soon. I think that was mostly held back by constants. Change-Id: I3f8a37a4d4642f77422ce3261b750061e9e604a3 Reviewed-on: https://skia-review.googlesource.com/14942 Reviewed-by: Herb Derby <herb@google.com>
This commit is contained in:
parent
879a08ac14
commit
5664e65eb1
@ -48,17 +48,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// SkJumper_stages.cpp has some unusual constraints on what constants it can use.
|
|
||||||
//
|
|
||||||
// If the constant is baked into the instruction, that's ok.
|
|
||||||
// If the constant is synthesized through code, that's ok.
|
|
||||||
// If the constant is loaded from memory, that's no good.
|
|
||||||
//
|
|
||||||
// We offer a couple facilities to get at any other constants you need:
|
|
||||||
// - the C() function usually constrains constants to be directly baked into an instruction; or
|
|
||||||
// - the _i and _f user-defined literal operators call C() for you in a prettier way; or
|
|
||||||
// - you can load values from this struct.
|
|
||||||
|
|
||||||
static const int SkJumper_kMaxStride = 8;
|
static const int SkJumper_kMaxStride = 8;
|
||||||
|
|
||||||
struct SkJumper_constants {
|
struct SkJumper_constants {
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -36,17 +36,4 @@ SI Dst widen_cast(const Src& src) {
|
|||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A couple functions for embedding constants directly into code,
|
|
||||||
// so that no .const or .literal4 section is created.
|
|
||||||
SI float C(float f) {
|
|
||||||
int x = bit_cast<int>(f);
|
|
||||||
#if defined(JUMPER) && defined(__x86_64__)
|
|
||||||
// Move x-the-compile-time-constant as a literal into x-the-register.
|
|
||||||
asm("mov %1, %0" : "=r"(x) : "i"(x));
|
|
||||||
#endif
|
|
||||||
return bit_cast<float>(x);
|
|
||||||
}
|
|
||||||
// Syntax sugar to make C() easy to use for constant literals.
|
|
||||||
SI float operator "" _f(long double f) { return C((float)f); }
|
|
||||||
|
|
||||||
#endif//SkJumper_misc_DEFINED
|
#endif//SkJumper_misc_DEFINED
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SkJumper.h"
|
#include "SkJumper.h"
|
||||||
#include "SkJumper_misc.h" // SI, unaligned_load(), bit_cast(), C(), operator"" and _f.
|
#include "SkJumper_misc.h" // SI, unaligned_load(), bit_cast()
|
||||||
#include "SkJumper_vectors.h" // F, I32, U32, U16, U8, cast(), expand()
|
#include "SkJumper_vectors.h" // F, I32, U32, U16, U8, cast(), expand()
|
||||||
|
|
||||||
// Our fundamental vector depth is our pixel stride.
|
// Our fundamental vector depth is our pixel stride.
|
||||||
@ -17,9 +17,7 @@ static const size_t kStride = sizeof(F) / sizeof(float);
|
|||||||
// and that F, I32, etc. are kStride-deep ext_vector_types of the appropriate type.
|
// and that F, I32, etc. are kStride-deep ext_vector_types of the appropriate type.
|
||||||
// Otherwise, F, I32, etc. just alias the basic scalar types (and so kStride == 1).
|
// Otherwise, F, I32, etc. just alias the basic scalar types (and so kStride == 1).
|
||||||
|
|
||||||
// Another reminder:
|
// You can use most constants in this file, but in a few rare exceptions we read from this struct.
|
||||||
// You can't generally use constants in this file except via C() or operator"" _f.
|
|
||||||
// Not all constants can be generated using C() or _f. Stages read the rest from this struct.
|
|
||||||
using K = const SkJumper_constants;
|
using K = const SkJumper_constants;
|
||||||
|
|
||||||
|
|
||||||
@ -504,16 +502,17 @@ STAGE(hsl_to_rgb) {
|
|||||||
s = g,
|
s = g,
|
||||||
l = b;
|
l = b;
|
||||||
|
|
||||||
F q = l + if_then_else(l < 0.5_f, l*s
|
F q = l + if_then_else(l >= 0.5f, s - l*s, l*s),
|
||||||
, s - l*s);
|
p = 2.0f*l - q;
|
||||||
F p = 2.0f*l - q;
|
|
||||||
|
|
||||||
auto hue_to_rgb = [&](F t) {
|
auto hue_to_rgb = [&](F t) {
|
||||||
t = fract(t);
|
t = fract(t);
|
||||||
return if_then_else(t < C(1/6.0f), p + (q-p)*( 6.0f*t),
|
|
||||||
if_then_else(t < C(3/6.0f), q,
|
F r = p;
|
||||||
if_then_else(t < C(4/6.0f), p + (q-p)*(4.0f - 6.0f*t),
|
r = if_then_else(t >= 4/6.0f, r, p + (q-p)*(4.0f - 6.0f*t));
|
||||||
p)));
|
r = if_then_else(t >= 3/6.0f, r, q);
|
||||||
|
r = if_then_else(t >= 1/6.0f, r, p + (q-p)*( 6.0f*t));
|
||||||
|
return r;
|
||||||
};
|
};
|
||||||
|
|
||||||
r = if_then_else(s == 0, l, hue_to_rgb(h + (1/3.0f)));
|
r = if_then_else(s == 0, l, hue_to_rgb(h + (1/3.0f)));
|
||||||
|
@ -115,6 +115,9 @@ def parse_object_file(dot_o, directive, target=None):
|
|||||||
print sym.replace('.literal', align)
|
print sym.replace('.literal', align)
|
||||||
elif sym.startswith('.const'): # 32-byte constants
|
elif sym.startswith('.const'): # 32-byte constants
|
||||||
print align + '32'
|
print align + '32'
|
||||||
|
elif not sym.startswith('sk_'):
|
||||||
|
print >>sys.stderr, "build_stages.py can't handle '%s' (yet?)." % sym
|
||||||
|
assert sym.startswith('sk_')
|
||||||
else: # a stage function
|
else: # a stage function
|
||||||
if hidden:
|
if hidden:
|
||||||
print hidden + ' _' + sym
|
print hidden + ' _' + sym
|
||||||
|
Loading…
Reference in New Issue
Block a user