2 * Copyright (C) 2020 Collabora Ltd.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * Authors (Collabora):
24 * Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
29 #include "util/half_float.h"
30 #include "bifrost/disassemble.h"
32 /* Instruction packing tests */
35 bit_test_single(struct panfrost_device
*dev
,
38 bool fma
, enum bit_debug debug
)
40 /* First, simulate the instruction */
41 struct bit_state s
= { 0 };
42 memcpy(s
.r
, input
, 16);
43 bit_step(&s
, ins
, fma
);
45 /* Next, wrap it up and pack it */
47 bi_instruction ldubo
= {
48 .type
= BI_LOAD_UNIFORM
,
57 .dest
= BIR_INDEX_REGISTER
| 0,
58 .dest_type
= nir_type_uint32
,
62 bi_instruction ldva
= {
63 .type
= BI_LOAD_VAR_ADDRESS
,
64 .writemask
= (1 << 12) - 1,
65 .dest
= BIR_INDEX_REGISTER
| 32,
66 .dest_type
= nir_type_uint32
,
69 BIR_INDEX_REGISTER
| 61,
70 BIR_INDEX_REGISTER
| 62,
84 BIR_INDEX_REGISTER
| 0,
85 ldva
.dest
, ldva
.dest
+ 1, ldva
.dest
+ 2,
89 nir_type_uint32
, nir_type_uint32
, nir_type_uint32
,
94 bi_context
*ctx
= rzalloc(NULL
, bi_context
);
95 ctx
->stage
= MESA_SHADER_VERTEX
;
97 bi_block
*blk
= rzalloc(ctx
, bi_block
);
98 blk
->scheduled
= true;
100 blk
->base
.predecessors
= _mesa_set_create(blk
,
102 _mesa_key_pointer_equal
);
104 list_inithead(&ctx
->blocks
);
105 list_addtail(&blk
->base
.link
, &ctx
->blocks
);
106 list_inithead(&blk
->clauses
);
108 bi_clause
*clauses
[4] = {
109 rzalloc(ctx
, bi_clause
),
110 rzalloc(ctx
, bi_clause
),
111 rzalloc(ctx
, bi_clause
),
112 rzalloc(ctx
, bi_clause
)
115 for (unsigned i
= 0; i
< 4; ++i
) {
116 clauses
[i
]->bundle_count
= 1;
117 list_addtail(&clauses
[i
]->link
, &blk
->clauses
);
118 clauses
[i
]->scoreboard_id
= (i
& 1);
121 clauses
[i
]->dependencies
= 1 << (~i
& 1);
122 clauses
[i
]->data_register_write_barrier
= true;
126 clauses
[0]->bundles
[0].add
= &ldubo
;
127 clauses
[0]->clause_type
= BIFROST_CLAUSE_UBO
;
130 clauses
[1]->bundles
[0].fma
= ins
;
132 clauses
[1]->bundles
[0].add
= ins
;
134 clauses
[0]->constant_count
= 1;
135 clauses
[1]->constant_count
= 1;
136 clauses
[1]->constants
[0] = ins
->constant
.u64
;
138 clauses
[2]->bundles
[0].add
= &ldva
;
139 clauses
[3]->bundles
[0].add
= &st
;
141 clauses
[2]->clause_type
= BIFROST_CLAUSE_UBO
;
142 clauses
[3]->clause_type
= BIFROST_CLAUSE_SSBO_STORE
;
144 panfrost_program prog
;
145 bi_pack(ctx
, &prog
.compiled
);
147 bool succ
= bit_vertex(dev
, prog
, input
, 16, NULL
, 0,
150 if (debug
>= BIT_DEBUG_ALL
|| (!succ
&& debug
>= BIT_DEBUG_FAIL
)) {
151 bi_print_shader(ctx
, stderr
);
152 disassemble_bifrost(stderr
, prog
.compiled
.data
, prog
.compiled
.size
, true);
158 /* Utilities for generating tests */
161 bit_generate_vector(uint32_t *mem
)
163 for (unsigned i
= 0; i
< 4; ++i
)
167 /* Tests all 64 combinations of floating point modifiers for a given
168 * instruction / floating-type / test type */
171 bit_fmod_helper(struct panfrost_device
*dev
,
172 enum bi_class c
, unsigned size
, bool fma
,
173 uint32_t *input
, enum bit_debug debug
)
175 nir_alu_type T
= nir_type_float
| size
;
177 bi_instruction ins
= {
180 BIR_INDEX_REGISTER
| 0,
181 BIR_INDEX_REGISTER
| 1,
183 .src_types
= { T
, T
},
184 .dest
= BIR_INDEX_REGISTER
| 2,
188 for (unsigned outmod
= 0; outmod
< 4; ++outmod
) {
189 for (unsigned inmod
= 0; inmod
< 16; ++inmod
) {
191 ins
.src_abs
[0] = (inmod
& 0x1);
192 ins
.src_abs
[1] = (inmod
& 0x2);
193 ins
.src_neg
[0] = (inmod
& 0x4);
194 ins
.src_neg
[1] = (inmod
& 0x8);
196 /* Skip over tests that cannot run on FMA */
197 if (fma
&& (size
== 16) && ins
.src_abs
[0] && ins
.src_abs
[1])
200 if (!bit_test_single(dev
, &ins
, input
, fma
, debug
)) {
201 fprintf(stderr
, "FAIL: fmod.%s%u.%s%s.%u\n",
205 outmod
? bi_output_mod_name(outmod
) : ".none",
213 bit_fma_helper(struct panfrost_device
*dev
,
214 unsigned size
, uint32_t *input
, enum bit_debug debug
)
216 nir_alu_type T
= nir_type_float
| size
;
218 bi_instruction ins
= {
221 BIR_INDEX_REGISTER
| 0,
222 BIR_INDEX_REGISTER
| 1,
223 BIR_INDEX_REGISTER
| 2,
225 .src_types
= { T
, T
, T
},
226 .dest
= BIR_INDEX_REGISTER
| 3,
230 for (unsigned outmod
= 0; outmod
< 4; ++outmod
) {
231 for (unsigned inmod
= 0; inmod
< 8; ++inmod
) {
233 ins
.src_neg
[0] = (inmod
& 0x1);
234 ins
.src_neg
[1] = (inmod
& 0x2);
235 ins
.src_neg
[2] = (inmod
& 0x4);
237 if (!bit_test_single(dev
, &ins
, input
, true, debug
)) {
238 fprintf(stderr
, "FAIL: fma%u%s.%u\n",
240 outmod
? bi_output_mod_name(outmod
) : ".none",
250 bit_fmod(struct panfrost_device
*dev
, enum bit_debug debug
)
252 float input32
[4] = { 0.8, 1.7, 0.0, 0.0 };
254 uint32_t input16
[4] = {
255 _mesa_float_to_half(input32
[0]) | (_mesa_float_to_half(-1.2) << 16),
256 _mesa_float_to_half(input32
[1]) | (_mesa_float_to_half(0.9) << 16),
260 for (unsigned sz
= 16; sz
<= 32; sz
*= 2) {
262 (sz
== 16) ? input16
:
263 (uint32_t *) input32
;
265 bit_fmod_helper(dev
, BI_ADD
, sz
, true, input
, debug
);
270 bit_fma(struct panfrost_device
*dev
, enum bit_debug debug
)
272 float input32
[4] = { 0.2, 1.6, -3.5, 0.0 };
274 uint32_t input16
[4] = {
275 _mesa_float_to_half(input32
[0]) | (_mesa_float_to_half(-1.8) << 16),
276 _mesa_float_to_half(input32
[1]) | (_mesa_float_to_half(0.6) << 16),
277 _mesa_float_to_half(input32
[1]) | (_mesa_float_to_half(16.2) << 16),
281 for (unsigned sz
= 16; sz
<= 32; sz
*= 2) {
283 (sz
== 16) ? input16
:
284 (uint32_t *) input32
;
286 bit_fma_helper(dev
, sz
, input
, debug
);