Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright 2012 Advanced Micro Devices, Inc.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * on the rights to use, copy, modify, merge, publish, distribute, sub
8
 * license, and/or sell copies of the Software, and to permit persons to whom
9
 * the Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice (including the next
12
 * paragraph) shall be included in all copies or substantial portions of the
13
 * Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18
 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22
 *
23
 * Authors:
24
 *      Christian König 
25
 */
26
 
27
#include "radeon/r600_cs.h"
28
#include "util/u_memory.h"
29
#include "si_pipe.h"
30
#include "sid.h"
31
 
32
#define NUMBER_OF_STATES (sizeof(union si_state) / sizeof(struct si_pm4_state *))
33
 
34
void si_pm4_cmd_begin(struct si_pm4_state *state, unsigned opcode)
35
{
36
	state->last_opcode = opcode;
37
	state->last_pm4 = state->ndw++;
38
}
39
 
40
void si_pm4_cmd_add(struct si_pm4_state *state, uint32_t dw)
41
{
42
	state->pm4[state->ndw++] = dw;
43
}
44
 
45
void si_pm4_cmd_end(struct si_pm4_state *state, bool predicate)
46
{
47
	unsigned count;
48
	count = state->ndw - state->last_pm4 - 2;
49
	state->pm4[state->last_pm4] =
50
		PKT3(state->last_opcode, count, predicate)
51
		   | PKT3_SHADER_TYPE_S(state->compute_pkt);
52
 
53
	assert(state->ndw <= SI_PM4_MAX_DW);
54
}
55
 
56
void si_pm4_set_reg(struct si_pm4_state *state, unsigned reg, uint32_t val)
57
{
58
	unsigned opcode;
59
 
60
	if (reg >= SI_CONFIG_REG_OFFSET && reg < SI_CONFIG_REG_END) {
61
		opcode = PKT3_SET_CONFIG_REG;
62
		reg -= SI_CONFIG_REG_OFFSET;
63
 
64
	} else if (reg >= SI_SH_REG_OFFSET && reg < SI_SH_REG_END) {
65
		opcode = PKT3_SET_SH_REG;
66
		reg -= SI_SH_REG_OFFSET;
67
 
68
	} else if (reg >= SI_CONTEXT_REG_OFFSET && reg < SI_CONTEXT_REG_END) {
69
		opcode = PKT3_SET_CONTEXT_REG;
70
		reg -= SI_CONTEXT_REG_OFFSET;
71
 
72
	} else if (reg >= CIK_UCONFIG_REG_OFFSET && reg < CIK_UCONFIG_REG_END) {
73
		opcode = PKT3_SET_UCONFIG_REG;
74
		reg -= CIK_UCONFIG_REG_OFFSET;
75
 
76
	} else {
77
		R600_ERR("Invalid register offset %08x!\n", reg);
78
		return;
79
	}
80
 
81
	reg >>= 2;
82
 
83
	if (opcode != state->last_opcode || reg != (state->last_reg + 1)) {
84
		si_pm4_cmd_begin(state, opcode);
85
		si_pm4_cmd_add(state, reg);
86
	}
87
 
88
	state->last_reg = reg;
89
	si_pm4_cmd_add(state, val);
90
	si_pm4_cmd_end(state, false);
91
}
92
 
93
void si_pm4_add_bo(struct si_pm4_state *state,
94
                   struct r600_resource *bo,
95
                   enum radeon_bo_usage usage,
96
		   enum radeon_bo_priority priority)
97
{
98
	unsigned idx = state->nbo++;
99
	assert(idx < SI_PM4_MAX_BO);
100
 
101
	r600_resource_reference(&state->bo[idx], bo);
102
	state->bo_usage[idx] = usage;
103
	state->bo_priority[idx] = priority;
104
}
105
 
106
void si_pm4_free_state_simple(struct si_pm4_state *state)
107
{
108
	for (int i = 0; i < state->nbo; ++i)
109
		r600_resource_reference(&state->bo[i], NULL);
110
	FREE(state);
111
}
112
 
113
void si_pm4_free_state(struct si_context *sctx,
114
		       struct si_pm4_state *state,
115
		       unsigned idx)
116
{
117
	if (state == NULL)
118
		return;
119
 
120
	if (idx != ~0 && sctx->emitted.array[idx] == state) {
121
		sctx->emitted.array[idx] = NULL;
122
	}
123
 
124
	si_pm4_free_state_simple(state);
125
}
126
 
127
unsigned si_pm4_dirty_dw(struct si_context *sctx)
128
{
129
	unsigned count = 0;
130
 
131
	for (int i = 0; i < NUMBER_OF_STATES; ++i) {
132
		struct si_pm4_state *state = sctx->queued.array[i];
133
 
134
		if (!state || sctx->emitted.array[i] == state)
135
			continue;
136
 
137
		count += state->ndw;
138
#if SI_TRACE_CS
139
		/* for tracing each states */
140
		if (sctx->screen->b.trace_bo) {
141
			count += SI_TRACE_CS_DWORDS;
142
		}
143
#endif
144
	}
145
 
146
	return count;
147
}
148
 
149
void si_pm4_emit(struct si_context *sctx, struct si_pm4_state *state)
150
{
151
	struct radeon_winsys_cs *cs = sctx->b.rings.gfx.cs;
152
	for (int i = 0; i < state->nbo; ++i) {
153
		r600_context_bo_reloc(&sctx->b, &sctx->b.rings.gfx, state->bo[i],
154
				      state->bo_usage[i], state->bo_priority[i]);
155
	}
156
 
157
	memcpy(&cs->buf[cs->cdw], state->pm4, state->ndw * 4);
158
 
159
	for (int i = 0; i < state->nrelocs; ++i) {
160
		cs->buf[cs->cdw + state->relocs[i]] += cs->cdw << 2;
161
	}
162
 
163
	cs->cdw += state->ndw;
164
 
165
#if SI_TRACE_CS
166
	if (sctx->screen->b.trace_bo) {
167
		si_trace_emit(sctx);
168
	}
169
#endif
170
}
171
 
172
void si_pm4_emit_dirty(struct si_context *sctx)
173
{
174
	for (int i = 0; i < NUMBER_OF_STATES; ++i) {
175
		struct si_pm4_state *state = sctx->queued.array[i];
176
 
177
		if (!state || sctx->emitted.array[i] == state)
178
			continue;
179
 
180
		si_pm4_emit(sctx, state);
181
		sctx->emitted.array[i] = state;
182
	}
183
}
184
 
185
void si_pm4_reset_emitted(struct si_context *sctx)
186
{
187
	memset(&sctx->emitted, 0, sizeof(sctx->emitted));
188
}
189
 
190
void si_pm4_cleanup(struct si_context *sctx)
191
{
192
	for (int i = 0; i < NUMBER_OF_STATES; ++i) {
193
		si_pm4_free_state(sctx, sctx->queued.array[i], i);
194
	}
195
}