github.com/as/shiny@v0.8.2/driver/internal/swizzle/swizzle_test.go (about)

     1  // Copyright 2018 as
     2  // Copyright 2015 The Go Authors
     3  
     4  package swizzle
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"math/rand"
    10  	"os"
    11  	"strings"
    12  	"testing"
    13  )
    14  
    15  var (
    16  	rgbaslice = "abcdefghijklmnopqrstuvwxyz012345ABCDEFGHIJKLMNOPQRSTUVWXYZ6789@="
    17  	bgraslice = "cbadgfehkjilonmpsrqtwvux0zy14325CBADGFEHKJILONMPSRQTWVUX6ZY7@98="
    18  
    19  	supported = map[string]func(p, q []byte){
    20  		"pure":     pureBGRA,
    21  		"amd64.4":  bgra4sd,
    22  		"ssse.16":  bgra16sd,
    23  		"avx2.128": bgra128sd,
    24  		"avx2.256": bgra256sd,
    25  	}
    26  )
    27  
    28  func TestMain(m *testing.M) {
    29  	const safe = 1024
    30  	rgbaslice = strings.Repeat(rgbaslice, safe)
    31  	bgraslice = strings.Repeat(bgraslice, safe)
    32  
    33  	if !haveAVX2() {
    34  		delete(supported, "avx2.256")
    35  	}
    36  	if !haveAVX() {
    37  		delete(supported, "avx2.128")
    38  	}
    39  	if !haveSSSE3() {
    40  		delete(supported, "ssse.16")
    41  	}
    42  	os.Exit(m.Run())
    43  }
    44  
    45  func TestSwizzleDistinct(t *testing.T) {
    46  	for _, v := range []int{32, 64, 96, 128, 160, 192, 224, 256} {
    47  		t.Run(fmt.Sprint(v), func(t *testing.T) {
    48  			testSwizzle1(t, v, true)
    49  		})
    50  	}
    51  }
    52  func TestSwizzleOverlap(t *testing.T) {
    53  	for _, v := range []int{32, 64, 96, 128, 160, 192, 224, 256} {
    54  		t.Run(fmt.Sprint(v), func(t *testing.T) {
    55  			testSwizzle1(t, v, false)
    56  		})
    57  	}
    58  }
    59  
    60  func testSwizzle1(t *testing.T, N int, distinct bool) {
    61  	t.Helper()
    62  	s := []byte(rgbaslice[:N])
    63  	d := s
    64  	if distinct {
    65  		d = make([]byte, N, N)
    66  	}
    67  	want := bgraslice[:N]
    68  	bgra256sd(s, d)
    69  	if string(d) != want {
    70  		t.Fatalf("have: %s\nwant: %s\n", d, want)
    71  	}
    72  }
    73  
    74  func makeRGBA(len int) []byte {
    75  	if len%4 != 0 {
    76  		panic("makeRGBA: len % 4 != 0")
    77  	}
    78  	return []byte(strings.Repeat("rgba", len/4))
    79  }
    80  
    81  func TestBGRAShort(t *testing.T) {
    82  	var lens = []int{
    83  		4, 8, 12, 16, 24, 32, 48, 64, 128, 192, 256, 512,
    84  	}
    85  	var tab []string
    86  	for _, v := range lens {
    87  		tab = append(tab, rgbaslice[:v])
    88  	}
    89  
    90  	for name, fn := range supported {
    91  		t.Run(name, func(t *testing.T) {
    92  			for i, in := range tab {
    93  				want := append([]byte{}, in...)
    94  				pureBGRA(append([]byte{}, in...), want)
    95  				p := []byte(in)
    96  				q := make([]byte, len(p))
    97  				fn(p, q)
    98  				have := string(q)
    99  				if want := string(want); have != want {
   100  					t.Errorf("len=%d: have %q, want %q", lens[i], have, want)
   101  				}
   102  			}
   103  		})
   104  	}
   105  }
   106  
   107  func TestBGRARandom(t *testing.T) {
   108  	r := rand.New(rand.NewSource(1))
   109  	var (
   110  		p0, q0,
   111  		p1, q1 [1024]byte
   112  	)
   113  	for i := range q0 {
   114  		p0[i] = byte(r.Intn(256))
   115  		p1[i] = p0[0]
   116  	}
   117  	exp := Swizzle
   118  	ctl := pureBGRA
   119  
   120  	for i := 0; i < 100000; i++ {
   121  		o := r.Intn(len(p1))
   122  		n := r.Intn(len(p1)-o) &^ 0x03
   123  		exp(p1[o:o+n], q1[o:o+n])
   124  		ctl(p0[o:o+n], q0[o:o+n])
   125  		if bytes.Equal(q0[:], q1[:]) {
   126  			continue
   127  		}
   128  		for j := range q1 {
   129  			x := q1[j]
   130  			y := q1[j]
   131  			if x != y {
   132  				t.Fatalf("iter %d: swizzling [%d:%d+%d]: bytes differ at offset %d (aka %d+%d): %#02x vs %#02x",
   133  					i, o, o, n, j, o, j-o, x, y)
   134  			}
   135  		}
   136  	}
   137  }
   138  
   139  func BenchmarkSwizzle(b *testing.B) {
   140  	sizes := []string{"64B", "64K", "64M"}
   141  	for name, fn := range supported {
   142  		for i, v := range sizes {
   143  			b.Run(name+"/"+v, func(b *testing.B) {
   144  				d := makeRGBA(64 * 1 << uint(i))
   145  				s := make([]byte, len(d))
   146  				b.SetBytes(int64(len(s)))
   147  				b.ResetTimer()
   148  				for i := 0; i < b.N; i++ {
   149  					fn(s, d)
   150  				}
   151  
   152  			})
   153  		}
   154  	}
   155  }