101e04c3fSmrg/* 201e04c3fSmrg * Copyright 2013 Advanced Micro Devices, Inc. 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * on the rights to use, copy, modify, merge, publish, distribute, sub 801e04c3fSmrg * license, and/or sell copies of the Software, and to permit persons to whom 901e04c3fSmrg * the Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 1901e04c3fSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2001e04c3fSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 2101e04c3fSmrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 2201e04c3fSmrg * 2301e04c3fSmrg * Authors: Marek Olšák <maraeo@gmail.com> 2401e04c3fSmrg */ 2501e04c3fSmrg 2601e04c3fSmrg/** 2701e04c3fSmrg * This file contains helpers for writing commands to commands streams. 2801e04c3fSmrg */ 2901e04c3fSmrg 3001e04c3fSmrg#ifndef R600_CS_H 3101e04c3fSmrg#define R600_CS_H 3201e04c3fSmrg 3301e04c3fSmrg#include "r600_pipe_common.h" 3401e04c3fSmrg#include "r600d_common.h" 3501e04c3fSmrg 3601e04c3fSmrg/** 3701e04c3fSmrg * Return true if there is enough memory in VRAM and GTT for the buffers 3801e04c3fSmrg * added so far. 3901e04c3fSmrg * 4001e04c3fSmrg * \param vram VRAM memory size not added to the buffer list yet 4101e04c3fSmrg * \param gtt GTT memory size not added to the buffer list yet 4201e04c3fSmrg */ 4301e04c3fSmrgstatic inline bool 4401e04c3fSmrgradeon_cs_memory_below_limit(struct r600_common_screen *screen, 4501e04c3fSmrg struct radeon_cmdbuf *cs, 4601e04c3fSmrg uint64_t vram, uint64_t gtt) 4701e04c3fSmrg{ 487ec681f3Smrg vram += (uint64_t)cs->used_vram_kb * 1024; 497ec681f3Smrg gtt += (uint64_t)cs->used_gart_kb * 1024; 5001e04c3fSmrg 5101e04c3fSmrg /* Anything that goes above the VRAM size should go to GTT. */ 5201e04c3fSmrg if (vram > screen->info.vram_size) 5301e04c3fSmrg gtt += vram - screen->info.vram_size; 5401e04c3fSmrg 5501e04c3fSmrg /* Now we just need to check if we have enough GTT. */ 5601e04c3fSmrg return gtt < screen->info.gart_size * 0.7; 5701e04c3fSmrg} 5801e04c3fSmrg 5901e04c3fSmrg/** 6001e04c3fSmrg * Add a buffer to the buffer list for the given command stream (CS). 6101e04c3fSmrg * 6201e04c3fSmrg * All buffers used by a CS must be added to the list. This tells the kernel 6301e04c3fSmrg * driver which buffers are used by GPU commands. Other buffers can 6401e04c3fSmrg * be swapped out (not accessible) during execution. 6501e04c3fSmrg * 6601e04c3fSmrg * The buffer list becomes empty after every context flush and must be 6701e04c3fSmrg * rebuilt. 6801e04c3fSmrg */ 6901e04c3fSmrgstatic inline unsigned radeon_add_to_buffer_list(struct r600_common_context *rctx, 7001e04c3fSmrg struct r600_ring *ring, 7101e04c3fSmrg struct r600_resource *rbo, 7201e04c3fSmrg enum radeon_bo_usage usage, 7301e04c3fSmrg enum radeon_bo_priority priority) 7401e04c3fSmrg{ 7501e04c3fSmrg assert(usage); 7601e04c3fSmrg return rctx->ws->cs_add_buffer( 777ec681f3Smrg &ring->cs, rbo->buf, 7801e04c3fSmrg (enum radeon_bo_usage)(usage | RADEON_USAGE_SYNCHRONIZED), 7901e04c3fSmrg rbo->domains, priority) * 4; 8001e04c3fSmrg} 8101e04c3fSmrg 8201e04c3fSmrg/** 8301e04c3fSmrg * Same as above, but also checks memory usage and flushes the context 8401e04c3fSmrg * accordingly. 8501e04c3fSmrg * 8601e04c3fSmrg * When this SHOULD NOT be used: 8701e04c3fSmrg * 8801e04c3fSmrg * - if r600_context_add_resource_size has been called for the buffer 8901e04c3fSmrg * followed by *_need_cs_space for checking the memory usage 9001e04c3fSmrg * 9101e04c3fSmrg * - if r600_need_dma_space has been called for the buffer 9201e04c3fSmrg * 9301e04c3fSmrg * - when emitting state packets and draw packets (because preceding packets 9401e04c3fSmrg * can't be re-emitted at that point) 9501e04c3fSmrg * 9601e04c3fSmrg * - if shader resource "enabled_mask" is not up-to-date or there is 9701e04c3fSmrg * a different constraint disallowing a context flush 9801e04c3fSmrg */ 9901e04c3fSmrgstatic inline unsigned 10001e04c3fSmrgradeon_add_to_buffer_list_check_mem(struct r600_common_context *rctx, 10101e04c3fSmrg struct r600_ring *ring, 10201e04c3fSmrg struct r600_resource *rbo, 10301e04c3fSmrg enum radeon_bo_usage usage, 10401e04c3fSmrg enum radeon_bo_priority priority, 10501e04c3fSmrg bool check_mem) 10601e04c3fSmrg{ 10701e04c3fSmrg if (check_mem && 1087ec681f3Smrg !radeon_cs_memory_below_limit(rctx->screen, &ring->cs, 10901e04c3fSmrg rctx->vram + rbo->vram_usage, 11001e04c3fSmrg rctx->gtt + rbo->gart_usage)) 11101e04c3fSmrg ring->flush(rctx, PIPE_FLUSH_ASYNC, NULL); 11201e04c3fSmrg 11301e04c3fSmrg return radeon_add_to_buffer_list(rctx, ring, rbo, usage, priority); 11401e04c3fSmrg} 11501e04c3fSmrg 11601e04c3fSmrgstatic inline void r600_emit_reloc(struct r600_common_context *rctx, 11701e04c3fSmrg struct r600_ring *ring, struct r600_resource *rbo, 11801e04c3fSmrg enum radeon_bo_usage usage, 11901e04c3fSmrg enum radeon_bo_priority priority) 12001e04c3fSmrg{ 1217ec681f3Smrg struct radeon_cmdbuf *cs = &ring->cs; 12201e04c3fSmrg bool has_vm = ((struct r600_common_screen*)rctx->b.screen)->info.r600_has_virtual_memory; 12301e04c3fSmrg unsigned reloc = radeon_add_to_buffer_list(rctx, ring, rbo, usage, priority); 12401e04c3fSmrg 12501e04c3fSmrg if (!has_vm) { 12601e04c3fSmrg radeon_emit(cs, PKT3(PKT3_NOP, 0, 0)); 12701e04c3fSmrg radeon_emit(cs, reloc); 12801e04c3fSmrg } 12901e04c3fSmrg} 13001e04c3fSmrg 13101e04c3fSmrgstatic inline void radeon_set_config_reg_seq(struct radeon_cmdbuf *cs, unsigned reg, unsigned num) 13201e04c3fSmrg{ 13301e04c3fSmrg assert(reg < R600_CONTEXT_REG_OFFSET); 13401e04c3fSmrg assert(cs->current.cdw + 2 + num <= cs->current.max_dw); 13501e04c3fSmrg radeon_emit(cs, PKT3(PKT3_SET_CONFIG_REG, num, 0)); 13601e04c3fSmrg radeon_emit(cs, (reg - R600_CONFIG_REG_OFFSET) >> 2); 13701e04c3fSmrg} 13801e04c3fSmrg 13901e04c3fSmrgstatic inline void radeon_set_config_reg(struct radeon_cmdbuf *cs, unsigned reg, unsigned value) 14001e04c3fSmrg{ 14101e04c3fSmrg radeon_set_config_reg_seq(cs, reg, 1); 14201e04c3fSmrg radeon_emit(cs, value); 14301e04c3fSmrg} 14401e04c3fSmrg 14501e04c3fSmrgstatic inline void radeon_set_context_reg_seq(struct radeon_cmdbuf *cs, unsigned reg, unsigned num) 14601e04c3fSmrg{ 14701e04c3fSmrg assert(reg >= R600_CONTEXT_REG_OFFSET); 14801e04c3fSmrg assert(cs->current.cdw + 2 + num <= cs->current.max_dw); 14901e04c3fSmrg radeon_emit(cs, PKT3(PKT3_SET_CONTEXT_REG, num, 0)); 15001e04c3fSmrg radeon_emit(cs, (reg - R600_CONTEXT_REG_OFFSET) >> 2); 15101e04c3fSmrg} 15201e04c3fSmrg 15301e04c3fSmrgstatic inline void radeon_set_context_reg(struct radeon_cmdbuf *cs, unsigned reg, unsigned value) 15401e04c3fSmrg{ 15501e04c3fSmrg radeon_set_context_reg_seq(cs, reg, 1); 15601e04c3fSmrg radeon_emit(cs, value); 15701e04c3fSmrg} 15801e04c3fSmrg 15901e04c3fSmrgstatic inline void radeon_set_context_reg_idx(struct radeon_cmdbuf *cs, 16001e04c3fSmrg unsigned reg, unsigned idx, 16101e04c3fSmrg unsigned value) 16201e04c3fSmrg{ 16301e04c3fSmrg assert(reg >= R600_CONTEXT_REG_OFFSET); 16401e04c3fSmrg assert(cs->current.cdw + 3 <= cs->current.max_dw); 16501e04c3fSmrg radeon_emit(cs, PKT3(PKT3_SET_CONTEXT_REG, 1, 0)); 16601e04c3fSmrg radeon_emit(cs, (reg - R600_CONTEXT_REG_OFFSET) >> 2 | (idx << 28)); 16701e04c3fSmrg radeon_emit(cs, value); 16801e04c3fSmrg} 16901e04c3fSmrg 17001e04c3fSmrgstatic inline void radeon_set_sh_reg_seq(struct radeon_cmdbuf *cs, unsigned reg, unsigned num) 17101e04c3fSmrg{ 17201e04c3fSmrg assert(reg >= SI_SH_REG_OFFSET && reg < SI_SH_REG_END); 17301e04c3fSmrg assert(cs->current.cdw + 2 + num <= cs->current.max_dw); 17401e04c3fSmrg radeon_emit(cs, PKT3(PKT3_SET_SH_REG, num, 0)); 17501e04c3fSmrg radeon_emit(cs, (reg - SI_SH_REG_OFFSET) >> 2); 17601e04c3fSmrg} 17701e04c3fSmrg 17801e04c3fSmrgstatic inline void radeon_set_sh_reg(struct radeon_cmdbuf *cs, unsigned reg, unsigned value) 17901e04c3fSmrg{ 18001e04c3fSmrg radeon_set_sh_reg_seq(cs, reg, 1); 18101e04c3fSmrg radeon_emit(cs, value); 18201e04c3fSmrg} 18301e04c3fSmrg 18401e04c3fSmrgstatic inline void radeon_set_uconfig_reg_seq(struct radeon_cmdbuf *cs, unsigned reg, unsigned num) 18501e04c3fSmrg{ 18601e04c3fSmrg assert(reg >= CIK_UCONFIG_REG_OFFSET && reg < CIK_UCONFIG_REG_END); 18701e04c3fSmrg assert(cs->current.cdw + 2 + num <= cs->current.max_dw); 18801e04c3fSmrg radeon_emit(cs, PKT3(PKT3_SET_UCONFIG_REG, num, 0)); 18901e04c3fSmrg radeon_emit(cs, (reg - CIK_UCONFIG_REG_OFFSET) >> 2); 19001e04c3fSmrg} 19101e04c3fSmrg 19201e04c3fSmrgstatic inline void radeon_set_uconfig_reg(struct radeon_cmdbuf *cs, unsigned reg, unsigned value) 19301e04c3fSmrg{ 19401e04c3fSmrg radeon_set_uconfig_reg_seq(cs, reg, 1); 19501e04c3fSmrg radeon_emit(cs, value); 19601e04c3fSmrg} 19701e04c3fSmrg 19801e04c3fSmrgstatic inline void radeon_set_uconfig_reg_idx(struct radeon_cmdbuf *cs, 19901e04c3fSmrg unsigned reg, unsigned idx, 20001e04c3fSmrg unsigned value) 20101e04c3fSmrg{ 20201e04c3fSmrg assert(reg >= CIK_UCONFIG_REG_OFFSET && reg < CIK_UCONFIG_REG_END); 20301e04c3fSmrg assert(cs->current.cdw + 3 <= cs->current.max_dw); 20401e04c3fSmrg radeon_emit(cs, PKT3(PKT3_SET_UCONFIG_REG, 1, 0)); 20501e04c3fSmrg radeon_emit(cs, (reg - CIK_UCONFIG_REG_OFFSET) >> 2 | (idx << 28)); 20601e04c3fSmrg radeon_emit(cs, value); 20701e04c3fSmrg} 20801e04c3fSmrg 20901e04c3fSmrg#endif 210