2 * Copyright (c) 2014 Scott Mansell
3 * Copyright © 2014 Broadcom
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
27 #include "pipe/p_state.h"
28 #include "util/u_format.h"
29 #include "util/u_hash_table.h"
30 #include "util/u_hash.h"
31 #include "util/u_memory.h"
32 #include "tgsi/tgsi_parse.h"
33 #include "tgsi/tgsi_dump.h"
35 #include "vc4_context.h"
40 struct tgsi_parse_context parser
;
45 struct qreg
*uniforms
;
49 struct vc4_shader_state
*shader_state
;
50 struct vc4_fs_key
*fs_key
;
51 struct vc4_vs_key
*vs_key
;
53 uint32_t *uniform_data
;
54 enum quniform_contents
*uniform_contents
;
55 uint32_t num_uniforms
;
61 struct vc4_shader_state
*shader_state
;
66 enum pipe_format color_format
;
71 enum pipe_format attr_formats
[8];
75 add_uniform(struct tgsi_to_qir
*trans
,
76 enum quniform_contents contents
,
79 uint32_t uniform
= trans
->num_uniforms
++;
80 struct qreg u
= { QFILE_UNIF
, uniform
};
82 trans
->uniform_contents
[uniform
] = contents
;
83 trans
->uniform_data
[uniform
] = data
;
89 get_temp_for_uniform(struct tgsi_to_qir
*trans
, enum quniform_contents contents
,
92 struct qcompile
*c
= trans
->c
;
94 for (int i
= 0; i
< trans
->num_uniforms
; i
++) {
95 if (trans
->uniform_contents
[i
] == contents
&&
96 trans
->uniform_data
[i
] == data
)
97 return trans
->uniforms
[i
];
100 struct qreg u
= add_uniform(trans
, contents
, data
);
101 struct qreg t
= qir_MOV(c
, u
);
103 trans
->uniforms
[u
.index
] = t
;
108 qir_uniform_ui(struct tgsi_to_qir
*trans
, uint32_t ui
)
110 return get_temp_for_uniform(trans
, QUNIFORM_CONSTANT
, ui
);
114 qir_uniform_f(struct tgsi_to_qir
*trans
, float f
)
116 return qir_uniform_ui(trans
, fui(f
));
120 get_src(struct tgsi_to_qir
*trans
, struct tgsi_src_register
*src
, int i
)
122 struct qcompile
*c
= trans
->c
;
123 struct qreg r
= c
->undef
;
143 assert(!src
->Indirect
);
148 case TGSI_FILE_TEMPORARY
:
149 r
= trans
->temps
[src
->Index
* 4 + s
];
151 case TGSI_FILE_IMMEDIATE
:
152 r
= trans
->consts
[src
->Index
* 4 + s
];
154 case TGSI_FILE_CONSTANT
:
155 r
= get_temp_for_uniform(trans
, QUNIFORM_UNIFORM
,
158 case TGSI_FILE_INPUT
:
159 r
= trans
->inputs
[src
->Index
* 4 + s
];
162 fprintf(stderr
, "unknown src file %d\n", src
->File
);
167 r
= qir_FMAXABS(c
, r
, r
);
170 r
= qir_FSUB(c
, qir_uniform_f(trans
, 0), r
);
177 update_dst(struct tgsi_to_qir
*trans
, struct tgsi_full_instruction
*tgsi_inst
,
178 int i
, struct qreg val
)
180 struct tgsi_dst_register
*tgsi_dst
= &tgsi_inst
->Dst
[0].Register
;
182 assert(!tgsi_dst
->Indirect
);
184 switch (tgsi_dst
->File
) {
185 case TGSI_FILE_TEMPORARY
:
186 trans
->temps
[tgsi_dst
->Index
* 4 + i
] = val
;
188 case TGSI_FILE_OUTPUT
:
189 trans
->outputs
[tgsi_dst
->Index
* 4 + i
] = val
;
190 trans
->num_outputs
= MAX2(trans
->num_outputs
,
191 tgsi_dst
->Index
* 4 + i
+ 1);
194 fprintf(stderr
, "unknown dst file %d\n", tgsi_dst
->File
);
200 tgsi_to_qir_alu(struct tgsi_to_qir
*trans
,
201 struct tgsi_full_instruction
*tgsi_inst
,
202 enum qop op
, struct qreg
*src
, int i
)
204 struct qcompile
*c
= trans
->c
;
205 struct qreg dst
= qir_get_temp(c
);
206 qir_emit(c
, qir_inst4(op
, dst
,
215 tgsi_to_qir_mad(struct tgsi_to_qir
*trans
,
216 struct tgsi_full_instruction
*tgsi_inst
,
217 enum qop op
, struct qreg
*src
, int i
)
219 struct qcompile
*c
= trans
->c
;
228 tgsi_to_qir_lit(struct tgsi_to_qir
*trans
,
229 struct tgsi_full_instruction
*tgsi_inst
,
230 enum qop op
, struct qreg
*src
, int i
)
232 struct qcompile
*c
= trans
->c
;
233 struct qreg x
= src
[0 * 4 + 0];
234 struct qreg y
= src
[0 * 4 + 1];
235 struct qreg w
= src
[0 * 4 + 3];
240 return qir_uniform_f(trans
, 1.0);
242 return qir_FMAX(c
, src
[0 * 4 + 0], qir_uniform_f(trans
, 0.0));
244 struct qreg zero
= qir_uniform_f(trans
, 0.0);
246 /* XXX: Clamp w to -128..128 */
250 qir_EXP2(c
, qir_FMUL(c
,
258 assert(!"not reached");
264 tgsi_to_qir_lrp(struct tgsi_to_qir
*trans
,
265 struct tgsi_full_instruction
*tgsi_inst
,
266 enum qop op
, struct qreg
*src
, int i
)
268 struct qcompile
*c
= trans
->c
;
269 struct qreg src0
= src
[0 * 4 + i
];
270 struct qreg src1
= src
[1 * 4 + i
];
271 struct qreg src2
= src
[2 * 4 + i
];
274 * src0 * src1 + (1 - src0) * src2.
275 * -> src0 * src1 + src2 - src0 * src2
276 * -> src2 + src0 * (src1 - src2)
278 return qir_FADD(c
, src2
, qir_FMUL(c
, src0
, qir_FSUB(c
, src1
, src2
)));
283 tgsi_to_qir_pow(struct tgsi_to_qir
*trans
,
284 struct tgsi_full_instruction
*tgsi_inst
,
285 enum qop op
, struct qreg
*src
, int i
)
287 struct qcompile
*c
= trans
->c
;
289 /* Note that this instruction replicates its result from the x channel
291 return qir_EXP2(c
, qir_FMUL(c
,
293 qir_LOG2(c
, src
[0 * 4 + 0])));
297 tgsi_to_qir_dp(struct tgsi_to_qir
*trans
,
298 struct tgsi_full_instruction
*tgsi_inst
,
299 int num
, struct qreg
*src
, int i
)
301 struct qcompile
*c
= trans
->c
;
303 struct qreg sum
= qir_FMUL(c
, src
[0 * 4 + 0], src
[1 * 4 + 0]);
304 for (int j
= 1; j
< num
; j
++) {
305 sum
= qir_FADD(c
, sum
, qir_FMUL(c
,
313 tgsi_to_qir_dp2(struct tgsi_to_qir
*trans
,
314 struct tgsi_full_instruction
*tgsi_inst
,
315 enum qop op
, struct qreg
*src
, int i
)
317 return tgsi_to_qir_dp(trans
, tgsi_inst
, 2, src
, i
);
321 tgsi_to_qir_dp3(struct tgsi_to_qir
*trans
,
322 struct tgsi_full_instruction
*tgsi_inst
,
323 enum qop op
, struct qreg
*src
, int i
)
325 return tgsi_to_qir_dp(trans
, tgsi_inst
, 3, src
, i
);
329 tgsi_to_qir_dp4(struct tgsi_to_qir
*trans
,
330 struct tgsi_full_instruction
*tgsi_inst
,
331 enum qop op
, struct qreg
*src
, int i
)
333 return tgsi_to_qir_dp(trans
, tgsi_inst
, 4, src
, i
);
337 tgsi_to_qir_abs(struct tgsi_to_qir
*trans
,
338 struct tgsi_full_instruction
*tgsi_inst
,
339 enum qop op
, struct qreg
*src
, int i
)
341 struct qcompile
*c
= trans
->c
;
342 struct qreg arg
= src
[0 * 4 + i
];
343 return qir_FMAXABS(c
, arg
, arg
);
347 emit_tgsi_declaration(struct tgsi_to_qir
*trans
,
348 struct tgsi_full_declaration
*decl
)
350 struct qcompile
*c
= trans
->c
;
352 switch (decl
->Declaration
.File
) {
353 case TGSI_FILE_INPUT
:
354 if (c
->stage
== QSTAGE_FRAG
) {
355 for (int index
= decl
->Range
.First
;
356 index
<= decl
->Range
.Last
;
358 for (int i
= 0; i
< 4; i
++) {
364 /* XXX: multiply by W */
365 trans
->inputs
[index
* 4 + i
] =
379 emit_tgsi_instruction(struct tgsi_to_qir
*trans
,
380 struct tgsi_full_instruction
*tgsi_inst
)
382 struct qcompile
*c
= trans
->c
;
385 struct qreg (*func
)(struct tgsi_to_qir
*trans
,
386 struct tgsi_full_instruction
*tgsi_inst
,
388 struct qreg
*src
, int i
);
390 [TGSI_OPCODE_MOV
] = { QOP_MOV
, tgsi_to_qir_alu
},
391 [TGSI_OPCODE_ABS
] = { 0, tgsi_to_qir_abs
},
392 [TGSI_OPCODE_MUL
] = { QOP_FMUL
, tgsi_to_qir_alu
},
393 [TGSI_OPCODE_ADD
] = { QOP_FADD
, tgsi_to_qir_alu
},
394 [TGSI_OPCODE_SUB
] = { QOP_FSUB
, tgsi_to_qir_alu
},
395 [TGSI_OPCODE_MIN
] = { QOP_FMIN
, tgsi_to_qir_alu
},
396 [TGSI_OPCODE_MAX
] = { QOP_FMAX
, tgsi_to_qir_alu
},
397 [TGSI_OPCODE_RSQ
] = { QOP_RSQ
, tgsi_to_qir_alu
},
398 [TGSI_OPCODE_SEQ
] = { QOP_SEQ
, tgsi_to_qir_alu
},
399 [TGSI_OPCODE_SNE
] = { QOP_SNE
, tgsi_to_qir_alu
},
400 [TGSI_OPCODE_SGE
] = { QOP_SGE
, tgsi_to_qir_alu
},
401 [TGSI_OPCODE_SLT
] = { QOP_SLT
, tgsi_to_qir_alu
},
402 [TGSI_OPCODE_CMP
] = { QOP_CMP
, tgsi_to_qir_alu
},
403 [TGSI_OPCODE_MAD
] = { 0, tgsi_to_qir_mad
},
404 [TGSI_OPCODE_DP2
] = { 0, tgsi_to_qir_dp2
},
405 [TGSI_OPCODE_DP3
] = { 0, tgsi_to_qir_dp3
},
406 [TGSI_OPCODE_DP4
] = { 0, tgsi_to_qir_dp4
},
407 [TGSI_OPCODE_RCP
] = { QOP_RCP
, tgsi_to_qir_alu
},
408 [TGSI_OPCODE_RSQ
] = { QOP_RSQ
, tgsi_to_qir_alu
},
409 [TGSI_OPCODE_EX2
] = { QOP_EXP2
, tgsi_to_qir_alu
},
410 [TGSI_OPCODE_LG2
] = { QOP_LOG2
, tgsi_to_qir_alu
},
411 [TGSI_OPCODE_LIT
] = { 0, tgsi_to_qir_lit
},
412 [TGSI_OPCODE_LRP
] = { 0, tgsi_to_qir_lrp
},
413 [TGSI_OPCODE_POW
] = { 0, tgsi_to_qir_pow
},
416 uint32_t tgsi_op
= tgsi_inst
->Instruction
.Opcode
;
418 if (tgsi_op
== TGSI_OPCODE_END
)
421 if (tgsi_op
> ARRAY_SIZE(op_trans
) || !op_trans
[tgsi_op
].func
) {
422 fprintf(stderr
, "unknown tgsi inst: ");
423 tgsi_dump_instruction(tgsi_inst
, asdf
++);
424 fprintf(stderr
, "\n");
428 struct qreg src_regs
[12];
429 for (int s
= 0; s
< 3; s
++) {
430 for (int i
= 0; i
< 4; i
++) {
431 src_regs
[4 * s
+ i
] =
432 get_src(trans
, &tgsi_inst
->Src
[s
].Register
, i
);
436 for (int i
= 0; i
< 4; i
++) {
437 if (!(tgsi_inst
->Dst
[0].Register
.WriteMask
& (1 << i
)))
442 result
= op_trans
[tgsi_op
].func(trans
, tgsi_inst
,
443 op_trans
[tgsi_op
].op
,
446 if (tgsi_inst
->Instruction
.Saturate
) {
447 float low
= (tgsi_inst
->Instruction
.Saturate
==
448 TGSI_SAT_MINUS_PLUS_ONE
? -1.0 : 0.0);
452 qir_uniform_f(trans
, 1.0)),
453 qir_uniform_f(trans
, low
));
456 update_dst(trans
, tgsi_inst
, i
, result
);
461 parse_tgsi_immediate(struct tgsi_to_qir
*trans
, struct tgsi_full_immediate
*imm
)
463 for (int i
= 0; i
< 4; i
++) {
464 unsigned n
= trans
->num_consts
++;
465 trans
->consts
[n
] = qir_uniform_ui(trans
, imm
->u
[i
].Uint
);
470 emit_frag_init(struct tgsi_to_qir
*trans
)
475 emit_vert_init(struct tgsi_to_qir
*trans
)
477 struct qcompile
*c
= trans
->c
;
479 /* XXX: attribute type/size/count */
480 for (int i
= 0; i
< 4; i
++) {
481 trans
->inputs
[i
] = qir_get_temp(c
);
482 qir_emit(c
, qir_inst(QOP_VPM_READ
, trans
->inputs
[i
],
483 c
->undef
, c
->undef
));
488 emit_coord_init(struct tgsi_to_qir
*trans
)
490 struct qcompile
*c
= trans
->c
;
492 /* XXX: attribute type/size/count */
493 for (int i
= 0; i
< 4; i
++) {
494 trans
->inputs
[i
] = qir_get_temp(c
);
495 qir_emit(c
, qir_inst(QOP_VPM_READ
, trans
->inputs
[i
],
496 c
->undef
, c
->undef
));
501 emit_frag_end(struct tgsi_to_qir
*trans
)
503 struct qcompile
*c
= trans
->c
;
505 struct qreg t
= qir_get_temp(c
);
507 const struct util_format_description
*format_desc
=
508 util_format_description(trans
->fs_key
->color_format
);
510 struct qreg swizzled_outputs
[4] = {
511 trans
->outputs
[format_desc
->swizzle
[0]],
512 trans
->outputs
[format_desc
->swizzle
[1]],
513 trans
->outputs
[format_desc
->swizzle
[2]],
514 trans
->outputs
[format_desc
->swizzle
[3]],
517 qir_emit(c
, qir_inst4(QOP_PACK_COLORS
, t
,
521 swizzled_outputs
[3]));
522 qir_emit(c
, qir_inst(QOP_TLB_COLOR_WRITE
, c
->undef
,
527 emit_scaled_viewport_write(struct tgsi_to_qir
*trans
)
529 struct qcompile
*c
= trans
->c
;
532 for (int i
= 0; i
< 2; i
++) {
534 add_uniform(trans
, QUNIFORM_VIEWPORT_X_SCALE
+ i
, 0);
536 xyi
[i
] = qir_FTOI(c
, qir_FMUL(c
, trans
->outputs
[i
], scale
));
539 qir_VPM_WRITE(c
, qir_PACK_SCALED(c
, xyi
[0], xyi
[1]));
543 emit_zs_write(struct tgsi_to_qir
*trans
)
545 struct qcompile
*c
= trans
->c
;
548 qir_VPM_WRITE(c
, trans
->outputs
[2]);
552 emit_1_wc_write(struct tgsi_to_qir
*trans
)
554 struct qcompile
*c
= trans
->c
;
557 qir_VPM_WRITE(c
, trans
->outputs
[3]);
561 emit_vert_end(struct tgsi_to_qir
*trans
)
563 struct qcompile
*c
= trans
->c
;
565 emit_scaled_viewport_write(trans
);
566 emit_zs_write(trans
);
567 emit_1_wc_write(trans
);
569 for (int i
= 4; i
< trans
->num_outputs
; i
++) {
570 qir_VPM_WRITE(c
, trans
->outputs
[i
]);
575 emit_coord_end(struct tgsi_to_qir
*trans
)
577 struct qcompile
*c
= trans
->c
;
579 for (int i
= 0; i
< 4; i
++)
580 qir_VPM_WRITE(c
, trans
->outputs
[i
]);
582 emit_scaled_viewport_write(trans
);
583 emit_zs_write(trans
);
584 emit_1_wc_write(trans
);
587 static struct tgsi_to_qir
*
588 vc4_shader_tgsi_to_qir(struct vc4_compiled_shader
*shader
, enum qstage stage
,
591 struct tgsi_to_qir
*trans
= CALLOC_STRUCT(tgsi_to_qir
);
595 c
= qir_compile_init();
598 memset(trans
, 0, sizeof(*trans
));
600 trans
->temps
= calloc(sizeof(struct qreg
), 1024);
601 trans
->inputs
= calloc(sizeof(struct qreg
), 8 * 4);
602 trans
->outputs
= calloc(sizeof(struct qreg
), 1024);
603 trans
->uniforms
= calloc(sizeof(struct qreg
), 1024);
604 trans
->consts
= calloc(sizeof(struct qreg
), 1024);
606 trans
->uniform_data
= calloc(sizeof(uint32_t), 1024);
607 trans
->uniform_contents
= calloc(sizeof(enum quniform_contents
), 1024);
609 trans
->shader_state
= key
->shader_state
;
611 ret
= tgsi_parse_init(&trans
->parser
, trans
->shader_state
->base
.tokens
);
612 assert(ret
== TGSI_PARSE_OK
);
614 if (vc4_debug
& VC4_DEBUG_TGSI
) {
615 fprintf(stderr
, "TGSI:\n");
616 tgsi_dump(trans
->shader_state
->base
.tokens
, 0);
621 trans
->fs_key
= (struct vc4_fs_key
*)key
;
622 emit_frag_init(trans
);
625 trans
->vs_key
= (struct vc4_vs_key
*)key
;
626 emit_vert_init(trans
);
629 trans
->vs_key
= (struct vc4_vs_key
*)key
;
630 emit_coord_init(trans
);
634 while (!tgsi_parse_end_of_tokens(&trans
->parser
)) {
635 tgsi_parse_token(&trans
->parser
);
637 switch (trans
->parser
.FullToken
.Token
.Type
) {
638 case TGSI_TOKEN_TYPE_DECLARATION
:
639 emit_tgsi_declaration(trans
,
640 &trans
->parser
.FullToken
.FullDeclaration
);
643 case TGSI_TOKEN_TYPE_INSTRUCTION
:
644 emit_tgsi_instruction(trans
,
645 &trans
->parser
.FullToken
.FullInstruction
);
648 case TGSI_TOKEN_TYPE_IMMEDIATE
:
649 parse_tgsi_immediate(trans
,
650 &trans
->parser
.FullToken
.FullImmediate
);
657 emit_frag_end(trans
);
660 emit_vert_end(trans
);
663 emit_coord_end(trans
);
667 tgsi_parse_free(&trans
->parser
);
672 if (vc4_debug
& VC4_DEBUG_QIR
) {
673 fprintf(stderr
, "QIR:\n");
676 vc4_generate_code(c
);
678 if (vc4_debug
& VC4_DEBUG_SHADERDB
) {
679 fprintf(stderr
, "SHADER-DB: %s: %d instructions\n",
680 qir_get_stage_name(c
->stage
), c
->qpu_inst_count
);
681 fprintf(stderr
, "SHADER-DB: %s: %d uniforms\n",
682 qir_get_stage_name(c
->stage
), trans
->num_uniforms
);
689 vc4_shader_state_create(struct pipe_context
*pctx
,
690 const struct pipe_shader_state
*cso
)
692 struct vc4_shader_state
*so
= CALLOC_STRUCT(vc4_shader_state
);
696 so
->base
.tokens
= tgsi_dup_tokens(cso
->tokens
);
702 copy_uniform_state_to_shader(struct vc4_compiled_shader
*shader
,
704 struct tgsi_to_qir
*trans
)
706 int count
= trans
->num_uniforms
;
707 struct vc4_shader_uniform_info
*uinfo
= &shader
->uniforms
[shader_index
];
709 uinfo
->count
= count
;
710 uinfo
->data
= malloc(count
* sizeof(*uinfo
->data
));
711 memcpy(uinfo
->data
, trans
->uniform_data
,
712 count
* sizeof(*uinfo
->data
));
713 uinfo
->contents
= malloc(count
* sizeof(*uinfo
->contents
));
714 memcpy(uinfo
->contents
, trans
->uniform_contents
,
715 count
* sizeof(*uinfo
->contents
));
719 vc4_fs_compile(struct vc4_context
*vc4
, struct vc4_compiled_shader
*shader
,
720 struct vc4_fs_key
*key
)
722 struct tgsi_to_qir
*trans
= vc4_shader_tgsi_to_qir(shader
, QSTAGE_FRAG
,
724 shader
->num_inputs
= trans
->num_inputs
;
725 copy_uniform_state_to_shader(shader
, 0, trans
);
726 shader
->bo
= vc4_bo_alloc_mem(vc4
->screen
, trans
->c
->qpu_insts
,
727 trans
->c
->qpu_inst_count
* sizeof(uint64_t),
730 qir_compile_destroy(trans
->c
);
735 vc4_vs_compile(struct vc4_context
*vc4
, struct vc4_compiled_shader
*shader
,
736 struct vc4_vs_key
*key
)
738 struct tgsi_to_qir
*vs_trans
= vc4_shader_tgsi_to_qir(shader
,
741 copy_uniform_state_to_shader(shader
, 0, vs_trans
);
743 struct tgsi_to_qir
*cs_trans
= vc4_shader_tgsi_to_qir(shader
,
746 copy_uniform_state_to_shader(shader
, 1, cs_trans
);
748 uint32_t vs_size
= vs_trans
->c
->qpu_inst_count
* sizeof(uint64_t);
749 uint32_t cs_size
= cs_trans
->c
->qpu_inst_count
* sizeof(uint64_t);
750 shader
->coord_shader_offset
= vs_size
; /* XXX: alignment? */
751 shader
->bo
= vc4_bo_alloc(vc4
->screen
,
752 shader
->coord_shader_offset
+ cs_size
,
755 void *map
= vc4_bo_map(shader
->bo
);
756 memcpy(map
, vs_trans
->c
->qpu_insts
, vs_size
);
757 memcpy(map
+ shader
->coord_shader_offset
,
758 cs_trans
->c
->qpu_insts
, cs_size
);
760 qir_compile_destroy(vs_trans
->c
);
761 qir_compile_destroy(cs_trans
->c
);
765 vc4_update_compiled_fs(struct vc4_context
*vc4
)
767 struct vc4_fs_key local_key
;
768 struct vc4_fs_key
*key
= &local_key
;
770 memset(key
, 0, sizeof(*key
));
771 key
->base
.shader_state
= vc4
->prog
.bind_fs
;
773 if (vc4
->framebuffer
.cbufs
[0])
774 key
->color_format
= vc4
->framebuffer
.cbufs
[0]->format
;
776 vc4
->prog
.fs
= util_hash_table_get(vc4
->fs_cache
, key
);
780 key
= malloc(sizeof(*key
));
781 memcpy(key
, &local_key
, sizeof(*key
));
783 struct vc4_compiled_shader
*shader
= CALLOC_STRUCT(vc4_compiled_shader
);
784 vc4_fs_compile(vc4
, shader
, key
);
785 util_hash_table_set(vc4
->fs_cache
, key
, shader
);
787 vc4
->prog
.fs
= shader
;
791 vc4_update_compiled_vs(struct vc4_context
*vc4
)
793 struct vc4_vs_key local_key
;
794 struct vc4_vs_key
*key
= &local_key
;
796 memset(key
, 0, sizeof(*key
));
797 key
->base
.shader_state
= vc4
->prog
.bind_vs
;
799 vc4
->prog
.vs
= util_hash_table_get(vc4
->vs_cache
, key
);
803 key
= malloc(sizeof(*key
));
804 memcpy(key
, &local_key
, sizeof(*key
));
806 struct vc4_compiled_shader
*shader
= CALLOC_STRUCT(vc4_compiled_shader
);
807 vc4_vs_compile(vc4
, shader
, key
);
808 util_hash_table_set(vc4
->vs_cache
, key
, shader
);
810 vc4
->prog
.vs
= shader
;
814 vc4_update_compiled_shaders(struct vc4_context
*vc4
)
816 vc4_update_compiled_fs(vc4
);
817 vc4_update_compiled_vs(vc4
);
821 fs_cache_hash(void *key
)
823 return util_hash_crc32(key
, sizeof(struct vc4_fs_key
));
827 vs_cache_hash(void *key
)
829 return util_hash_crc32(key
, sizeof(struct vc4_vs_key
));
833 fs_cache_compare(void *key1
, void *key2
)
835 return memcmp(key1
, key2
, sizeof(struct vc4_fs_key
));
839 vs_cache_compare(void *key1
, void *key2
)
841 return memcmp(key1
, key2
, sizeof(struct vc4_vs_key
));
844 struct delete_state
{
845 struct vc4_context
*vc4
;
846 struct vc4_shader_state
*shader_state
;
849 static enum pipe_error
850 fs_delete_from_cache(void *in_key
, void *in_value
, void *data
)
852 struct delete_state
*del
= data
;
853 struct vc4_fs_key
*key
= in_key
;
854 struct vc4_compiled_shader
*shader
= in_value
;
856 if (key
->base
.shader_state
== data
) {
857 util_hash_table_remove(del
->vc4
->fs_cache
, key
);
858 vc4_bo_unreference(&shader
->bo
);
865 static enum pipe_error
866 vs_delete_from_cache(void *in_key
, void *in_value
, void *data
)
868 struct delete_state
*del
= data
;
869 struct vc4_vs_key
*key
= in_key
;
870 struct vc4_compiled_shader
*shader
= in_value
;
872 if (key
->base
.shader_state
== data
) {
873 util_hash_table_remove(del
->vc4
->vs_cache
, key
);
874 vc4_bo_unreference(&shader
->bo
);
882 vc4_shader_state_delete(struct pipe_context
*pctx
, void *hwcso
)
884 struct vc4_context
*vc4
= vc4_context(pctx
);
885 struct vc4_shader_state
*so
= hwcso
;
886 struct delete_state del
;
889 del
.shader_state
= so
;
890 util_hash_table_foreach(vc4
->fs_cache
, fs_delete_from_cache
, &del
);
891 util_hash_table_foreach(vc4
->vs_cache
, vs_delete_from_cache
, &del
);
893 free((void *)so
->base
.tokens
);
898 vc4_get_uniform_bo(struct vc4_context
*vc4
, struct vc4_compiled_shader
*shader
,
899 struct vc4_constbuf_stateobj
*cb
,
900 int shader_index
, struct vc4_bo
**out_bo
,
901 uint32_t *out_offset
)
903 struct vc4_shader_uniform_info
*uinfo
= &shader
->uniforms
[shader_index
];
904 struct vc4_bo
*ubo
= vc4_bo_alloc(vc4
->screen
,
905 MAX2(1, uinfo
->count
* 4), "ubo");
906 uint32_t *map
= vc4_bo_map(ubo
);
908 for (int i
= 0; i
< uinfo
->count
; i
++) {
909 switch (uinfo
->contents
[i
]) {
910 case QUNIFORM_CONSTANT
:
911 map
[i
] = uinfo
->data
[i
];
913 case QUNIFORM_UNIFORM
:
914 map
[i
] = ((uint32_t *)cb
->cb
[0].user_buffer
)[uinfo
->data
[i
]];
916 case QUNIFORM_VIEWPORT_X_SCALE
:
917 map
[i
] = fui(vc4
->framebuffer
.width
* 16.0f
/ 2.0f
);
919 case QUNIFORM_VIEWPORT_Y_SCALE
:
920 map
[i
] = fui(vc4
->framebuffer
.height
* -16.0f
/ 2.0f
);
924 fprintf(stderr
, "%p/%d: %d: 0x%08x (%f)\n",
925 shader
, shader_index
, i
, map
[i
], uif(map
[i
]));
934 vc4_fp_state_bind(struct pipe_context
*pctx
, void *hwcso
)
936 struct vc4_context
*vc4
= vc4_context(pctx
);
937 vc4
->prog
.bind_fs
= hwcso
;
938 vc4
->prog
.dirty
|= VC4_SHADER_DIRTY_FP
;
939 vc4
->dirty
|= VC4_DIRTY_PROG
;
943 vc4_vp_state_bind(struct pipe_context
*pctx
, void *hwcso
)
945 struct vc4_context
*vc4
= vc4_context(pctx
);
946 vc4
->prog
.bind_vs
= hwcso
;
947 vc4
->prog
.dirty
|= VC4_SHADER_DIRTY_VP
;
948 vc4
->dirty
|= VC4_DIRTY_PROG
;
952 vc4_program_init(struct pipe_context
*pctx
)
954 struct vc4_context
*vc4
= vc4_context(pctx
);
956 pctx
->create_vs_state
= vc4_shader_state_create
;
957 pctx
->delete_vs_state
= vc4_shader_state_delete
;
959 pctx
->create_fs_state
= vc4_shader_state_create
;
960 pctx
->delete_fs_state
= vc4_shader_state_delete
;
962 pctx
->bind_fs_state
= vc4_fp_state_bind
;
963 pctx
->bind_vs_state
= vc4_vp_state_bind
;
965 vc4
->fs_cache
= util_hash_table_create(fs_cache_hash
, fs_cache_compare
);
966 vc4
->vs_cache
= util_hash_table_create(vs_cache_hash
, vs_cache_compare
);