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