1af69d88dSmrg/*
2af69d88dSmrg * Copyright 2012 Advanced Micro Devices, Inc.
301e04c3fSmrg * All Rights Reserved.
4af69d88dSmrg *
5af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
6af69d88dSmrg * copy of this software and associated documentation files (the "Software"),
7af69d88dSmrg * to deal in the Software without restriction, including without limitation
8af69d88dSmrg * on the rights to use, copy, modify, merge, publish, distribute, sub
9af69d88dSmrg * license, and/or sell copies of the Software, and to permit persons to whom
10af69d88dSmrg * the Software is furnished to do so, subject to the following conditions:
11af69d88dSmrg *
12af69d88dSmrg * The above copyright notice and this permission notice (including the next
13af69d88dSmrg * paragraph) shall be included in all copies or substantial portions of the
14af69d88dSmrg * Software.
15af69d88dSmrg *
16af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17af69d88dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19af69d88dSmrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20af69d88dSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21af69d88dSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22af69d88dSmrg * USE OR OTHER DEALINGS IN THE SOFTWARE.
23af69d88dSmrg */
24af69d88dSmrg
25af69d88dSmrg#include "si_pipe.h"
267ec681f3Smrg#include "si_build_pm4.h"
27af69d88dSmrg#include "sid.h"
287ec681f3Smrg#include "util/u_memory.h"
29af69d88dSmrg
307ec681f3Smrgstatic void si_pm4_cmd_begin(struct si_pm4_state *state, unsigned opcode)
31af69d88dSmrg{
327ec681f3Smrg   assert(state->ndw < SI_PM4_MAX_DW);
337ec681f3Smrg   state->last_opcode = opcode;
347ec681f3Smrg   state->last_pm4 = state->ndw++;
35af69d88dSmrg}
36af69d88dSmrg
37af69d88dSmrgvoid si_pm4_cmd_add(struct si_pm4_state *state, uint32_t dw)
38af69d88dSmrg{
397ec681f3Smrg   assert(state->ndw < SI_PM4_MAX_DW);
407ec681f3Smrg   state->pm4[state->ndw++] = dw;
417ec681f3Smrg   state->last_opcode = -1;
42af69d88dSmrg}
43af69d88dSmrg
447ec681f3Smrgstatic void si_pm4_cmd_end(struct si_pm4_state *state, bool predicate)
45af69d88dSmrg{
467ec681f3Smrg   unsigned count;
477ec681f3Smrg   count = state->ndw - state->last_pm4 - 2;
487ec681f3Smrg   state->pm4[state->last_pm4] = PKT3(state->last_opcode, count, predicate);
49af69d88dSmrg}
50af69d88dSmrg
51af69d88dSmrgvoid si_pm4_set_reg(struct si_pm4_state *state, unsigned reg, uint32_t val)
52af69d88dSmrg{
537ec681f3Smrg   unsigned opcode;
54af69d88dSmrg
557ec681f3Smrg   SI_CHECK_SHADOWED_REGS(reg, 1);
56af69d88dSmrg
577ec681f3Smrg   if (reg >= SI_CONFIG_REG_OFFSET && reg < SI_CONFIG_REG_END) {
587ec681f3Smrg      opcode = PKT3_SET_CONFIG_REG;
597ec681f3Smrg      reg -= SI_CONFIG_REG_OFFSET;
60af69d88dSmrg
617ec681f3Smrg   } else if (reg >= SI_SH_REG_OFFSET && reg < SI_SH_REG_END) {
627ec681f3Smrg      opcode = PKT3_SET_SH_REG;
637ec681f3Smrg      reg -= SI_SH_REG_OFFSET;
64af69d88dSmrg
657ec681f3Smrg   } else if (reg >= SI_CONTEXT_REG_OFFSET && reg < SI_CONTEXT_REG_END) {
667ec681f3Smrg      opcode = PKT3_SET_CONTEXT_REG;
677ec681f3Smrg      reg -= SI_CONTEXT_REG_OFFSET;
68af69d88dSmrg
697ec681f3Smrg   } else if (reg >= CIK_UCONFIG_REG_OFFSET && reg < CIK_UCONFIG_REG_END) {
707ec681f3Smrg      opcode = PKT3_SET_UCONFIG_REG;
717ec681f3Smrg      reg -= CIK_UCONFIG_REG_OFFSET;
72af69d88dSmrg
737ec681f3Smrg   } else {
747ec681f3Smrg      PRINT_ERR("Invalid register offset %08x!\n", reg);
757ec681f3Smrg      return;
767ec681f3Smrg   }
77af69d88dSmrg
787ec681f3Smrg   reg >>= 2;
79af69d88dSmrg
807ec681f3Smrg   assert(state->ndw + 2 <= SI_PM4_MAX_DW);
81af69d88dSmrg
827ec681f3Smrg   if (opcode != state->last_opcode || reg != (state->last_reg + 1)) {
837ec681f3Smrg      si_pm4_cmd_begin(state, opcode);
847ec681f3Smrg      state->pm4[state->ndw++] = reg;
857ec681f3Smrg   }
86af69d88dSmrg
877ec681f3Smrg   state->last_reg = reg;
887ec681f3Smrg   state->pm4[state->ndw++] = val;
897ec681f3Smrg   si_pm4_cmd_end(state, false);
90af69d88dSmrg}
91af69d88dSmrg
9201e04c3fSmrgvoid si_pm4_clear_state(struct si_pm4_state *state)
93af69d88dSmrg{
947ec681f3Smrg   state->ndw = 0;
95af69d88dSmrg}
96af69d88dSmrg
977ec681f3Smrgvoid si_pm4_free_state(struct si_context *sctx, struct si_pm4_state *state, unsigned idx)
98af69d88dSmrg{
997ec681f3Smrg   if (!state)
1007ec681f3Smrg      return;
101af69d88dSmrg
1027ec681f3Smrg   if (idx != ~0) {
1037ec681f3Smrg      if (sctx->emitted.array[idx] == state)
1047ec681f3Smrg         sctx->emitted.array[idx] = NULL;
105af69d88dSmrg
1067ec681f3Smrg      if (sctx->queued.array[idx] == state) {
1077ec681f3Smrg         sctx->queued.array[idx] = NULL;
1087ec681f3Smrg         sctx->dirty_states &= ~BITFIELD_BIT(idx);
1097ec681f3Smrg      }
1107ec681f3Smrg   }
1117ec681f3Smrg
1127ec681f3Smrg   si_pm4_clear_state(state);
1137ec681f3Smrg   FREE(state);
114af69d88dSmrg}
115af69d88dSmrg
116af69d88dSmrgvoid si_pm4_emit(struct si_context *sctx, struct si_pm4_state *state)
117af69d88dSmrg{
1187ec681f3Smrg   struct radeon_cmdbuf *cs = &sctx->gfx_cs;
119af69d88dSmrg
1207ec681f3Smrg   if (state->is_shader) {
1217ec681f3Smrg      radeon_add_to_buffer_list(sctx, &sctx->gfx_cs, ((struct si_shader*)state)->bo,
1227ec681f3Smrg                                RADEON_USAGE_READ, RADEON_PRIO_SHADER_BINARY);
1237ec681f3Smrg   }
1247ec681f3Smrg
1257ec681f3Smrg   radeon_begin(cs);
1267ec681f3Smrg   radeon_emit_array(state->pm4, state->ndw);
1277ec681f3Smrg   radeon_end();
1287ec681f3Smrg
1297ec681f3Smrg   if (state->atom.emit)
1307ec681f3Smrg      state->atom.emit(sctx);
131af69d88dSmrg}
132af69d88dSmrg
1337ec681f3Smrgvoid si_pm4_reset_emitted(struct si_context *sctx, bool first_cs)
134af69d88dSmrg{
1357ec681f3Smrg   if (!first_cs && sctx->shadowed_regs) {
1367ec681f3Smrg      /* Only dirty states that contain buffers, so that they are
1377ec681f3Smrg       * added to the buffer list on the next draw call.
1387ec681f3Smrg       */
1397ec681f3Smrg      for (unsigned i = 0; i < SI_NUM_STATES; i++) {
1407ec681f3Smrg         struct si_pm4_state *state = sctx->emitted.array[i];
1417ec681f3Smrg
1427ec681f3Smrg         if (state && state->is_shader) {
1437ec681f3Smrg            sctx->emitted.array[i] = NULL;
1447ec681f3Smrg            sctx->dirty_states |= 1 << i;
1457ec681f3Smrg         }
1467ec681f3Smrg      }
1477ec681f3Smrg      return;
1487ec681f3Smrg   }
1497ec681f3Smrg
1507ec681f3Smrg   memset(&sctx->emitted, 0, sizeof(sctx->emitted));
1517ec681f3Smrg
1527ec681f3Smrg   for (unsigned i = 0; i < SI_NUM_STATES; i++) {
1537ec681f3Smrg      if (sctx->queued.array[i])
1547ec681f3Smrg         sctx->dirty_states |= BITFIELD_BIT(i);
1557ec681f3Smrg   }
156af69d88dSmrg}
157