1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2012 Advanced Micro Devices, Inc. 3bf215546Sopenharmony_ci * All Rights Reserved. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "si_pipe.h" 26bf215546Sopenharmony_ci#include "si_build_pm4.h" 27bf215546Sopenharmony_ci#include "sid.h" 28bf215546Sopenharmony_ci#include "util/u_memory.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_cistatic void si_pm4_cmd_begin(struct si_pm4_state *state, unsigned opcode) 31bf215546Sopenharmony_ci{ 32bf215546Sopenharmony_ci if (!state->max_dw) 33bf215546Sopenharmony_ci state->max_dw = ARRAY_SIZE(state->pm4); 34bf215546Sopenharmony_ci assert(state->ndw < state->max_dw); 35bf215546Sopenharmony_ci assert(opcode <= 254); 36bf215546Sopenharmony_ci state->last_opcode = opcode; 37bf215546Sopenharmony_ci state->last_pm4 = state->ndw++; 38bf215546Sopenharmony_ci} 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_civoid si_pm4_cmd_add(struct si_pm4_state *state, uint32_t dw) 41bf215546Sopenharmony_ci{ 42bf215546Sopenharmony_ci if (!state->max_dw) 43bf215546Sopenharmony_ci state->max_dw = ARRAY_SIZE(state->pm4); 44bf215546Sopenharmony_ci assert(state->ndw < state->max_dw); 45bf215546Sopenharmony_ci state->pm4[state->ndw++] = dw; 46bf215546Sopenharmony_ci state->last_opcode = 255; /* invalid opcode */ 47bf215546Sopenharmony_ci} 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_cistatic void si_pm4_cmd_end(struct si_pm4_state *state, bool predicate) 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci unsigned count; 52bf215546Sopenharmony_ci count = state->ndw - state->last_pm4 - 2; 53bf215546Sopenharmony_ci state->pm4[state->last_pm4] = PKT3(state->last_opcode, count, predicate); 54bf215546Sopenharmony_ci} 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_cistatic void si_pm4_set_reg_custom(struct si_pm4_state *state, unsigned reg, uint32_t val, 57bf215546Sopenharmony_ci unsigned opcode, unsigned idx) 58bf215546Sopenharmony_ci{ 59bf215546Sopenharmony_ci reg >>= 2; 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci if (!state->max_dw) 62bf215546Sopenharmony_ci state->max_dw = ARRAY_SIZE(state->pm4); 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci assert(state->ndw + 2 <= state->max_dw); 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci if (opcode != state->last_opcode || reg != (state->last_reg + 1)) { 67bf215546Sopenharmony_ci si_pm4_cmd_begin(state, opcode); 68bf215546Sopenharmony_ci state->pm4[state->ndw++] = reg | (idx << 28); 69bf215546Sopenharmony_ci } 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci assert(reg <= UINT16_MAX); 72bf215546Sopenharmony_ci state->last_reg = reg; 73bf215546Sopenharmony_ci state->pm4[state->ndw++] = val; 74bf215546Sopenharmony_ci si_pm4_cmd_end(state, false); 75bf215546Sopenharmony_ci} 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_civoid si_pm4_set_reg(struct si_pm4_state *state, unsigned reg, uint32_t val) 78bf215546Sopenharmony_ci{ 79bf215546Sopenharmony_ci unsigned opcode; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci SI_CHECK_SHADOWED_REGS(reg, 1); 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci if (reg >= SI_CONFIG_REG_OFFSET && reg < SI_CONFIG_REG_END) { 84bf215546Sopenharmony_ci opcode = PKT3_SET_CONFIG_REG; 85bf215546Sopenharmony_ci reg -= SI_CONFIG_REG_OFFSET; 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci } else if (reg >= SI_SH_REG_OFFSET && reg < SI_SH_REG_END) { 88bf215546Sopenharmony_ci opcode = PKT3_SET_SH_REG; 89bf215546Sopenharmony_ci reg -= SI_SH_REG_OFFSET; 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci } else if (reg >= SI_CONTEXT_REG_OFFSET && reg < SI_CONTEXT_REG_END) { 92bf215546Sopenharmony_ci opcode = PKT3_SET_CONTEXT_REG; 93bf215546Sopenharmony_ci reg -= SI_CONTEXT_REG_OFFSET; 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci } else if (reg >= CIK_UCONFIG_REG_OFFSET && reg < CIK_UCONFIG_REG_END) { 96bf215546Sopenharmony_ci opcode = PKT3_SET_UCONFIG_REG; 97bf215546Sopenharmony_ci reg -= CIK_UCONFIG_REG_OFFSET; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci } else { 100bf215546Sopenharmony_ci PRINT_ERR("Invalid register offset %08x!\n", reg); 101bf215546Sopenharmony_ci return; 102bf215546Sopenharmony_ci } 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci si_pm4_set_reg_custom(state, reg, val, opcode, 0); 105bf215546Sopenharmony_ci} 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_civoid si_pm4_set_reg_idx3(struct si_pm4_state *state, unsigned reg, uint32_t val) 108bf215546Sopenharmony_ci{ 109bf215546Sopenharmony_ci SI_CHECK_SHADOWED_REGS(reg, 1); 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci si_pm4_set_reg_custom(state, reg - SI_SH_REG_OFFSET, val, PKT3_SET_SH_REG_INDEX, 3); 112bf215546Sopenharmony_ci} 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_civoid si_pm4_clear_state(struct si_pm4_state *state) 115bf215546Sopenharmony_ci{ 116bf215546Sopenharmony_ci state->ndw = 0; 117bf215546Sopenharmony_ci} 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_civoid si_pm4_free_state(struct si_context *sctx, struct si_pm4_state *state, unsigned idx) 120bf215546Sopenharmony_ci{ 121bf215546Sopenharmony_ci if (!state) 122bf215546Sopenharmony_ci return; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci if (idx != ~0) { 125bf215546Sopenharmony_ci if (sctx->emitted.array[idx] == state) 126bf215546Sopenharmony_ci sctx->emitted.array[idx] = NULL; 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci if (sctx->queued.array[idx] == state) { 129bf215546Sopenharmony_ci sctx->queued.array[idx] = NULL; 130bf215546Sopenharmony_ci sctx->dirty_states &= ~BITFIELD_BIT(idx); 131bf215546Sopenharmony_ci } 132bf215546Sopenharmony_ci } 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci FREE(state); 135bf215546Sopenharmony_ci} 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_civoid si_pm4_emit(struct si_context *sctx, struct si_pm4_state *state) 138bf215546Sopenharmony_ci{ 139bf215546Sopenharmony_ci struct radeon_cmdbuf *cs = &sctx->gfx_cs; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci if (state->is_shader) { 142bf215546Sopenharmony_ci radeon_add_to_buffer_list(sctx, &sctx->gfx_cs, ((struct si_shader*)state)->bo, 143bf215546Sopenharmony_ci RADEON_USAGE_READ | RADEON_PRIO_SHADER_BINARY); 144bf215546Sopenharmony_ci } 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci radeon_begin(cs); 147bf215546Sopenharmony_ci radeon_emit_array(state->pm4, state->ndw); 148bf215546Sopenharmony_ci radeon_end(); 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci if (state->atom.emit) 151bf215546Sopenharmony_ci state->atom.emit(sctx); 152bf215546Sopenharmony_ci} 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_civoid si_pm4_reset_emitted(struct si_context *sctx, bool first_cs) 155bf215546Sopenharmony_ci{ 156bf215546Sopenharmony_ci if (!first_cs && sctx->shadowed_regs) { 157bf215546Sopenharmony_ci /* Only dirty states that contain buffers, so that they are 158bf215546Sopenharmony_ci * added to the buffer list on the next draw call. 159bf215546Sopenharmony_ci */ 160bf215546Sopenharmony_ci for (unsigned i = 0; i < SI_NUM_STATES; i++) { 161bf215546Sopenharmony_ci struct si_pm4_state *state = sctx->queued.array[i]; 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci if (state && state->is_shader) { 164bf215546Sopenharmony_ci sctx->emitted.array[i] = NULL; 165bf215546Sopenharmony_ci sctx->dirty_states |= 1 << i; 166bf215546Sopenharmony_ci } 167bf215546Sopenharmony_ci } 168bf215546Sopenharmony_ci return; 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci memset(&sctx->emitted, 0, sizeof(sctx->emitted)); 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci for (unsigned i = 0; i < SI_NUM_STATES; i++) { 174bf215546Sopenharmony_ci if (sctx->queued.array[i]) 175bf215546Sopenharmony_ci sctx->dirty_states |= BITFIELD_BIT(i); 176bf215546Sopenharmony_ci } 177bf215546Sopenharmony_ci} 178