1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2013 Advanced Micro Devices, Inc.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors: Marek Olšák <maraeo@gmail.com>
24bf215546Sopenharmony_ci *
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "r600_pipe_common.h"
28bf215546Sopenharmony_ci#include "r600_cs.h"
29bf215546Sopenharmony_ci#include "evergreen_compute.h"
30bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h"
31bf215546Sopenharmony_ci#include "util/list.h"
32bf215546Sopenharmony_ci#include "util/u_draw_quad.h"
33bf215546Sopenharmony_ci#include "util/u_memory.h"
34bf215546Sopenharmony_ci#include "util/format/u_format_s3tc.h"
35bf215546Sopenharmony_ci#include "util/u_upload_mgr.h"
36bf215546Sopenharmony_ci#include "util/os_time.h"
37bf215546Sopenharmony_ci#include "vl/vl_decoder.h"
38bf215546Sopenharmony_ci#include "vl/vl_video_buffer.h"
39bf215546Sopenharmony_ci#include "radeon_video.h"
40bf215546Sopenharmony_ci#include <inttypes.h>
41bf215546Sopenharmony_ci#include <sys/utsname.h>
42bf215546Sopenharmony_ci#include <stdlib.h>
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci#ifdef LLVM_AVAILABLE
45bf215546Sopenharmony_ci#include <llvm-c/TargetMachine.h>
46bf215546Sopenharmony_ci#endif
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_cistruct r600_multi_fence {
49bf215546Sopenharmony_ci	struct pipe_reference reference;
50bf215546Sopenharmony_ci	struct pipe_fence_handle *gfx;
51bf215546Sopenharmony_ci	struct pipe_fence_handle *sdma;
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci	/* If the context wasn't flushed at fence creation, this is non-NULL. */
54bf215546Sopenharmony_ci	struct {
55bf215546Sopenharmony_ci		struct r600_common_context *ctx;
56bf215546Sopenharmony_ci		unsigned ib_index;
57bf215546Sopenharmony_ci	} gfx_unflushed;
58bf215546Sopenharmony_ci};
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci/*
61bf215546Sopenharmony_ci * pipe_context
62bf215546Sopenharmony_ci */
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci/**
65bf215546Sopenharmony_ci * Write an EOP event.
66bf215546Sopenharmony_ci *
67bf215546Sopenharmony_ci * \param event		EVENT_TYPE_*
68bf215546Sopenharmony_ci * \param event_flags	Optional cache flush flags (TC)
69bf215546Sopenharmony_ci * \param data_sel	1 = fence, 3 = timestamp
70bf215546Sopenharmony_ci * \param buf		Buffer
71bf215546Sopenharmony_ci * \param va		GPU address
72bf215546Sopenharmony_ci * \param old_value	Previous fence value (for a bug workaround)
73bf215546Sopenharmony_ci * \param new_value	Fence value to write for this event.
74bf215546Sopenharmony_ci */
75bf215546Sopenharmony_civoid r600_gfx_write_event_eop(struct r600_common_context *ctx,
76bf215546Sopenharmony_ci			      unsigned event, unsigned event_flags,
77bf215546Sopenharmony_ci			      unsigned data_sel,
78bf215546Sopenharmony_ci			      struct r600_resource *buf, uint64_t va,
79bf215546Sopenharmony_ci			      uint32_t new_fence, unsigned query_type)
80bf215546Sopenharmony_ci{
81bf215546Sopenharmony_ci	struct radeon_cmdbuf *cs = &ctx->gfx.cs;
82bf215546Sopenharmony_ci	unsigned op = EVENT_TYPE(event) |
83bf215546Sopenharmony_ci		      EVENT_INDEX(5) |
84bf215546Sopenharmony_ci		      event_flags;
85bf215546Sopenharmony_ci	unsigned sel = EOP_DATA_SEL(data_sel);
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci	radeon_emit(cs, PKT3(PKT3_EVENT_WRITE_EOP, 4, 0));
88bf215546Sopenharmony_ci	radeon_emit(cs, op);
89bf215546Sopenharmony_ci	radeon_emit(cs, va);
90bf215546Sopenharmony_ci	radeon_emit(cs, ((va >> 32) & 0xffff) | sel);
91bf215546Sopenharmony_ci	radeon_emit(cs, new_fence); /* immediate data */
92bf215546Sopenharmony_ci	radeon_emit(cs, 0); /* unused */
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci	if (buf)
95bf215546Sopenharmony_ci		r600_emit_reloc(ctx, &ctx->gfx, buf, RADEON_USAGE_WRITE |
96bf215546Sopenharmony_ci				RADEON_PRIO_QUERY);
97bf215546Sopenharmony_ci}
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ciunsigned r600_gfx_write_fence_dwords(struct r600_common_screen *screen)
100bf215546Sopenharmony_ci{
101bf215546Sopenharmony_ci	unsigned dwords = 6;
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci	if (!screen->info.r600_has_virtual_memory)
104bf215546Sopenharmony_ci		dwords += 2;
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci	return dwords;
107bf215546Sopenharmony_ci}
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_civoid r600_gfx_wait_fence(struct r600_common_context *ctx,
110bf215546Sopenharmony_ci			 struct r600_resource *buf,
111bf215546Sopenharmony_ci			 uint64_t va, uint32_t ref, uint32_t mask)
112bf215546Sopenharmony_ci{
113bf215546Sopenharmony_ci	struct radeon_cmdbuf *cs = &ctx->gfx.cs;
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci	radeon_emit(cs, PKT3(PKT3_WAIT_REG_MEM, 5, 0));
116bf215546Sopenharmony_ci	radeon_emit(cs, WAIT_REG_MEM_EQUAL | WAIT_REG_MEM_MEM_SPACE(1));
117bf215546Sopenharmony_ci	radeon_emit(cs, va);
118bf215546Sopenharmony_ci	radeon_emit(cs, va >> 32);
119bf215546Sopenharmony_ci	radeon_emit(cs, ref); /* reference value */
120bf215546Sopenharmony_ci	radeon_emit(cs, mask); /* mask */
121bf215546Sopenharmony_ci	radeon_emit(cs, 4); /* poll interval */
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci	if (buf)
124bf215546Sopenharmony_ci		r600_emit_reloc(ctx, &ctx->gfx, buf, RADEON_USAGE_READ |
125bf215546Sopenharmony_ci				RADEON_PRIO_QUERY);
126bf215546Sopenharmony_ci}
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_civoid r600_draw_rectangle(struct blitter_context *blitter,
129bf215546Sopenharmony_ci			 void *vertex_elements_cso,
130bf215546Sopenharmony_ci			 blitter_get_vs_func get_vs,
131bf215546Sopenharmony_ci			 int x1, int y1, int x2, int y2,
132bf215546Sopenharmony_ci			 float depth, unsigned num_instances,
133bf215546Sopenharmony_ci			 enum blitter_attrib_type type,
134bf215546Sopenharmony_ci			 const union blitter_attrib *attrib)
135bf215546Sopenharmony_ci{
136bf215546Sopenharmony_ci	struct r600_common_context *rctx =
137bf215546Sopenharmony_ci		(struct r600_common_context*)util_blitter_get_pipe(blitter);
138bf215546Sopenharmony_ci	struct pipe_viewport_state viewport;
139bf215546Sopenharmony_ci	struct pipe_resource *buf = NULL;
140bf215546Sopenharmony_ci	unsigned offset = 0;
141bf215546Sopenharmony_ci	float *vb;
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci	rctx->b.bind_vertex_elements_state(&rctx->b, vertex_elements_cso);
144bf215546Sopenharmony_ci	rctx->b.bind_vs_state(&rctx->b, get_vs(blitter));
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci	/* Some operations (like color resolve on r6xx) don't work
147bf215546Sopenharmony_ci	 * with the conventional primitive types.
148bf215546Sopenharmony_ci	 * One that works is PT_RECTLIST, which we use here. */
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci	/* setup viewport */
151bf215546Sopenharmony_ci	viewport.scale[0] = 1.0f;
152bf215546Sopenharmony_ci	viewport.scale[1] = 1.0f;
153bf215546Sopenharmony_ci	viewport.scale[2] = 1.0f;
154bf215546Sopenharmony_ci	viewport.translate[0] = 0.0f;
155bf215546Sopenharmony_ci	viewport.translate[1] = 0.0f;
156bf215546Sopenharmony_ci	viewport.translate[2] = 0.0f;
157bf215546Sopenharmony_ci	rctx->b.set_viewport_states(&rctx->b, 0, 1, &viewport);
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci	/* Upload vertices. The hw rectangle has only 3 vertices,
160bf215546Sopenharmony_ci	 * The 4th one is derived from the first 3.
161bf215546Sopenharmony_ci	 * The vertex specification should match u_blitter's vertex element state. */
162bf215546Sopenharmony_ci	u_upload_alloc(rctx->b.stream_uploader, 0, sizeof(float) * 24,
163bf215546Sopenharmony_ci		       rctx->screen->info.tcc_cache_line_size,
164bf215546Sopenharmony_ci                       &offset, &buf, (void**)&vb);
165bf215546Sopenharmony_ci	if (!buf)
166bf215546Sopenharmony_ci		return;
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci	vb[0] = x1;
169bf215546Sopenharmony_ci	vb[1] = y1;
170bf215546Sopenharmony_ci	vb[2] = depth;
171bf215546Sopenharmony_ci	vb[3] = 1;
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci	vb[8] = x1;
174bf215546Sopenharmony_ci	vb[9] = y2;
175bf215546Sopenharmony_ci	vb[10] = depth;
176bf215546Sopenharmony_ci	vb[11] = 1;
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci	vb[16] = x2;
179bf215546Sopenharmony_ci	vb[17] = y1;
180bf215546Sopenharmony_ci	vb[18] = depth;
181bf215546Sopenharmony_ci	vb[19] = 1;
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci	switch (type) {
184bf215546Sopenharmony_ci	case UTIL_BLITTER_ATTRIB_COLOR:
185bf215546Sopenharmony_ci		memcpy(vb+4, attrib->color, sizeof(float)*4);
186bf215546Sopenharmony_ci		memcpy(vb+12, attrib->color, sizeof(float)*4);
187bf215546Sopenharmony_ci		memcpy(vb+20, attrib->color, sizeof(float)*4);
188bf215546Sopenharmony_ci		break;
189bf215546Sopenharmony_ci	case UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW:
190bf215546Sopenharmony_ci	case UTIL_BLITTER_ATTRIB_TEXCOORD_XY:
191bf215546Sopenharmony_ci		vb[6] = vb[14] = vb[22] = attrib->texcoord.z;
192bf215546Sopenharmony_ci		vb[7] = vb[15] = vb[23] = attrib->texcoord.w;
193bf215546Sopenharmony_ci		/* fall through */
194bf215546Sopenharmony_ci		vb[4] = attrib->texcoord.x1;
195bf215546Sopenharmony_ci		vb[5] = attrib->texcoord.y1;
196bf215546Sopenharmony_ci		vb[12] = attrib->texcoord.x1;
197bf215546Sopenharmony_ci		vb[13] = attrib->texcoord.y2;
198bf215546Sopenharmony_ci		vb[20] = attrib->texcoord.x2;
199bf215546Sopenharmony_ci		vb[21] = attrib->texcoord.y1;
200bf215546Sopenharmony_ci		break;
201bf215546Sopenharmony_ci	default:; /* Nothing to do. */
202bf215546Sopenharmony_ci	}
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci	/* draw */
205bf215546Sopenharmony_ci	struct pipe_vertex_buffer vbuffer = {};
206bf215546Sopenharmony_ci	vbuffer.buffer.resource = buf;
207bf215546Sopenharmony_ci	vbuffer.stride = 2 * 4 * sizeof(float); /* vertex size */
208bf215546Sopenharmony_ci	vbuffer.buffer_offset = offset;
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci	rctx->b.set_vertex_buffers(&rctx->b, blitter->vb_slot, 1, 0, false, &vbuffer);
211bf215546Sopenharmony_ci	util_draw_arrays_instanced(&rctx->b, R600_PRIM_RECTANGLE_LIST, 0, 3,
212bf215546Sopenharmony_ci				   0, num_instances);
213bf215546Sopenharmony_ci	pipe_resource_reference(&buf, NULL);
214bf215546Sopenharmony_ci}
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_cistatic void r600_dma_emit_wait_idle(struct r600_common_context *rctx)
217bf215546Sopenharmony_ci{
218bf215546Sopenharmony_ci	struct radeon_cmdbuf *cs = &rctx->dma.cs;
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_ci	if (rctx->gfx_level >= EVERGREEN)
221bf215546Sopenharmony_ci		radeon_emit(cs, 0xf0000000); /* NOP */
222bf215546Sopenharmony_ci	else {
223bf215546Sopenharmony_ci		/* TODO: R600-R700 should use the FENCE packet.
224bf215546Sopenharmony_ci		 * CS checker support is required. */
225bf215546Sopenharmony_ci	}
226bf215546Sopenharmony_ci}
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_civoid r600_need_dma_space(struct r600_common_context *ctx, unsigned num_dw,
229bf215546Sopenharmony_ci                         struct r600_resource *dst, struct r600_resource *src)
230bf215546Sopenharmony_ci{
231bf215546Sopenharmony_ci	uint64_t vram = (uint64_t)ctx->dma.cs.used_vram_kb * 1024;
232bf215546Sopenharmony_ci	uint64_t gtt = (uint64_t)ctx->dma.cs.used_gart_kb * 1024;
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci	if (dst) {
235bf215546Sopenharmony_ci		vram += dst->vram_usage;
236bf215546Sopenharmony_ci		gtt += dst->gart_usage;
237bf215546Sopenharmony_ci	}
238bf215546Sopenharmony_ci	if (src) {
239bf215546Sopenharmony_ci		vram += src->vram_usage;
240bf215546Sopenharmony_ci		gtt += src->gart_usage;
241bf215546Sopenharmony_ci	}
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci	/* Flush the GFX IB if DMA depends on it. */
244bf215546Sopenharmony_ci	if (radeon_emitted(&ctx->gfx.cs, ctx->initial_gfx_cs_size) &&
245bf215546Sopenharmony_ci	    ((dst &&
246bf215546Sopenharmony_ci	      ctx->ws->cs_is_buffer_referenced(&ctx->gfx.cs, dst->buf,
247bf215546Sopenharmony_ci					       RADEON_USAGE_READWRITE)) ||
248bf215546Sopenharmony_ci	     (src &&
249bf215546Sopenharmony_ci	      ctx->ws->cs_is_buffer_referenced(&ctx->gfx.cs, src->buf,
250bf215546Sopenharmony_ci					       RADEON_USAGE_WRITE))))
251bf215546Sopenharmony_ci		ctx->gfx.flush(ctx, PIPE_FLUSH_ASYNC, NULL);
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci	/* Flush if there's not enough space, or if the memory usage per IB
254bf215546Sopenharmony_ci	 * is too large.
255bf215546Sopenharmony_ci	 *
256bf215546Sopenharmony_ci	 * IBs using too little memory are limited by the IB submission overhead.
257bf215546Sopenharmony_ci	 * IBs using too much memory are limited by the kernel/TTM overhead.
258bf215546Sopenharmony_ci	 * Too long IBs create CPU-GPU pipeline bubbles and add latency.
259bf215546Sopenharmony_ci	 *
260bf215546Sopenharmony_ci	 * This heuristic makes sure that DMA requests are executed
261bf215546Sopenharmony_ci	 * very soon after the call is made and lowers memory usage.
262bf215546Sopenharmony_ci	 * It improves texture upload performance by keeping the DMA
263bf215546Sopenharmony_ci	 * engine busy while uploads are being submitted.
264bf215546Sopenharmony_ci	 */
265bf215546Sopenharmony_ci	num_dw++; /* for emit_wait_idle below */
266bf215546Sopenharmony_ci	if (!ctx->ws->cs_check_space(&ctx->dma.cs, num_dw) ||
267bf215546Sopenharmony_ci	    ctx->dma.cs.used_vram_kb + ctx->dma.cs.used_gart_kb > 64 * 1024 ||
268bf215546Sopenharmony_ci	    !radeon_cs_memory_below_limit(ctx->screen, &ctx->dma.cs, vram, gtt)) {
269bf215546Sopenharmony_ci		ctx->dma.flush(ctx, PIPE_FLUSH_ASYNC, NULL);
270bf215546Sopenharmony_ci		assert((num_dw + ctx->dma.cs.current.cdw) <= ctx->dma.cs.current.max_dw);
271bf215546Sopenharmony_ci	}
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_ci	/* Wait for idle if either buffer has been used in the IB before to
274bf215546Sopenharmony_ci	 * prevent read-after-write hazards.
275bf215546Sopenharmony_ci	 */
276bf215546Sopenharmony_ci	if ((dst &&
277bf215546Sopenharmony_ci	     ctx->ws->cs_is_buffer_referenced(&ctx->dma.cs, dst->buf,
278bf215546Sopenharmony_ci					      RADEON_USAGE_READWRITE)) ||
279bf215546Sopenharmony_ci	    (src &&
280bf215546Sopenharmony_ci	     ctx->ws->cs_is_buffer_referenced(&ctx->dma.cs, src->buf,
281bf215546Sopenharmony_ci					      RADEON_USAGE_WRITE)))
282bf215546Sopenharmony_ci		r600_dma_emit_wait_idle(ctx);
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci	/* If GPUVM is not supported, the CS checker needs 2 entries
285bf215546Sopenharmony_ci	 * in the buffer list per packet, which has to be done manually.
286bf215546Sopenharmony_ci	 */
287bf215546Sopenharmony_ci	if (ctx->screen->info.r600_has_virtual_memory) {
288bf215546Sopenharmony_ci		if (dst)
289bf215546Sopenharmony_ci			radeon_add_to_buffer_list(ctx, &ctx->dma, dst,
290bf215546Sopenharmony_ci						  RADEON_USAGE_WRITE);
291bf215546Sopenharmony_ci		if (src)
292bf215546Sopenharmony_ci			radeon_add_to_buffer_list(ctx, &ctx->dma, src,
293bf215546Sopenharmony_ci						  RADEON_USAGE_READ);
294bf215546Sopenharmony_ci	}
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci	/* this function is called before all DMA calls, so increment this. */
297bf215546Sopenharmony_ci	ctx->num_dma_calls++;
298bf215546Sopenharmony_ci}
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_civoid r600_preflush_suspend_features(struct r600_common_context *ctx)
301bf215546Sopenharmony_ci{
302bf215546Sopenharmony_ci	/* suspend queries */
303bf215546Sopenharmony_ci	if (!list_is_empty(&ctx->active_queries))
304bf215546Sopenharmony_ci		r600_suspend_queries(ctx);
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ci	ctx->streamout.suspended = false;
307bf215546Sopenharmony_ci	if (ctx->streamout.begin_emitted) {
308bf215546Sopenharmony_ci		r600_emit_streamout_end(ctx);
309bf215546Sopenharmony_ci		ctx->streamout.suspended = true;
310bf215546Sopenharmony_ci	}
311bf215546Sopenharmony_ci}
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_civoid r600_postflush_resume_features(struct r600_common_context *ctx)
314bf215546Sopenharmony_ci{
315bf215546Sopenharmony_ci	if (ctx->streamout.suspended) {
316bf215546Sopenharmony_ci		ctx->streamout.append_bitmask = ctx->streamout.enabled_mask;
317bf215546Sopenharmony_ci		r600_streamout_buffers_dirty(ctx);
318bf215546Sopenharmony_ci	}
319bf215546Sopenharmony_ci
320bf215546Sopenharmony_ci	/* resume queries */
321bf215546Sopenharmony_ci	if (!list_is_empty(&ctx->active_queries))
322bf215546Sopenharmony_ci		r600_resume_queries(ctx);
323bf215546Sopenharmony_ci}
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_cistatic void r600_fence_server_sync(struct pipe_context *ctx,
326bf215546Sopenharmony_ci				   struct pipe_fence_handle *fence)
327bf215546Sopenharmony_ci{
328bf215546Sopenharmony_ci	/* radeon synchronizes all rings by default and will not implement
329bf215546Sopenharmony_ci	 * fence imports.
330bf215546Sopenharmony_ci	 */
331bf215546Sopenharmony_ci}
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_cistatic void r600_flush_from_st(struct pipe_context *ctx,
334bf215546Sopenharmony_ci			       struct pipe_fence_handle **fence,
335bf215546Sopenharmony_ci			       unsigned flags)
336bf215546Sopenharmony_ci{
337bf215546Sopenharmony_ci	struct pipe_screen *screen = ctx->screen;
338bf215546Sopenharmony_ci	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
339bf215546Sopenharmony_ci	struct radeon_winsys *ws = rctx->ws;
340bf215546Sopenharmony_ci	struct pipe_fence_handle *gfx_fence = NULL;
341bf215546Sopenharmony_ci	struct pipe_fence_handle *sdma_fence = NULL;
342bf215546Sopenharmony_ci	bool deferred_fence = false;
343bf215546Sopenharmony_ci	unsigned rflags = PIPE_FLUSH_ASYNC;
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci	if (flags & PIPE_FLUSH_END_OF_FRAME)
346bf215546Sopenharmony_ci		rflags |= PIPE_FLUSH_END_OF_FRAME;
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_ci	/* DMA IBs are preambles to gfx IBs, therefore must be flushed first. */
349bf215546Sopenharmony_ci	if (rctx->dma.cs.priv)
350bf215546Sopenharmony_ci		rctx->dma.flush(rctx, rflags, fence ? &sdma_fence : NULL);
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci	if (!radeon_emitted(&rctx->gfx.cs, rctx->initial_gfx_cs_size)) {
353bf215546Sopenharmony_ci		if (fence)
354bf215546Sopenharmony_ci			ws->fence_reference(&gfx_fence, rctx->last_gfx_fence);
355bf215546Sopenharmony_ci		if (!(flags & PIPE_FLUSH_DEFERRED))
356bf215546Sopenharmony_ci			ws->cs_sync_flush(&rctx->gfx.cs);
357bf215546Sopenharmony_ci	} else {
358bf215546Sopenharmony_ci		/* Instead of flushing, create a deferred fence. Constraints:
359bf215546Sopenharmony_ci		 * - the gallium frontend must allow a deferred flush.
360bf215546Sopenharmony_ci		 * - the gallium frontend must request a fence.
361bf215546Sopenharmony_ci		 * Thread safety in fence_finish must be ensured by the gallium frontend.
362bf215546Sopenharmony_ci		 */
363bf215546Sopenharmony_ci		if (flags & PIPE_FLUSH_DEFERRED && fence) {
364bf215546Sopenharmony_ci			gfx_fence = rctx->ws->cs_get_next_fence(&rctx->gfx.cs);
365bf215546Sopenharmony_ci			deferred_fence = true;
366bf215546Sopenharmony_ci		} else {
367bf215546Sopenharmony_ci			rctx->gfx.flush(rctx, rflags, fence ? &gfx_fence : NULL);
368bf215546Sopenharmony_ci		}
369bf215546Sopenharmony_ci	}
370bf215546Sopenharmony_ci
371bf215546Sopenharmony_ci	/* Both engines can signal out of order, so we need to keep both fences. */
372bf215546Sopenharmony_ci	if (fence) {
373bf215546Sopenharmony_ci		struct r600_multi_fence *multi_fence =
374bf215546Sopenharmony_ci			CALLOC_STRUCT(r600_multi_fence);
375bf215546Sopenharmony_ci		if (!multi_fence) {
376bf215546Sopenharmony_ci			ws->fence_reference(&sdma_fence, NULL);
377bf215546Sopenharmony_ci			ws->fence_reference(&gfx_fence, NULL);
378bf215546Sopenharmony_ci			goto finish;
379bf215546Sopenharmony_ci		}
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci		multi_fence->reference.count = 1;
382bf215546Sopenharmony_ci		/* If both fences are NULL, fence_finish will always return true. */
383bf215546Sopenharmony_ci		multi_fence->gfx = gfx_fence;
384bf215546Sopenharmony_ci		multi_fence->sdma = sdma_fence;
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci		if (deferred_fence) {
387bf215546Sopenharmony_ci			multi_fence->gfx_unflushed.ctx = rctx;
388bf215546Sopenharmony_ci			multi_fence->gfx_unflushed.ib_index = rctx->num_gfx_cs_flushes;
389bf215546Sopenharmony_ci		}
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci		screen->fence_reference(screen, fence, NULL);
392bf215546Sopenharmony_ci		*fence = (struct pipe_fence_handle*)multi_fence;
393bf215546Sopenharmony_ci	}
394bf215546Sopenharmony_cifinish:
395bf215546Sopenharmony_ci	if (!(flags & PIPE_FLUSH_DEFERRED)) {
396bf215546Sopenharmony_ci		if (rctx->dma.cs.priv)
397bf215546Sopenharmony_ci			ws->cs_sync_flush(&rctx->dma.cs);
398bf215546Sopenharmony_ci		ws->cs_sync_flush(&rctx->gfx.cs);
399bf215546Sopenharmony_ci	}
400bf215546Sopenharmony_ci}
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_cistatic void r600_flush_dma_ring(void *ctx, unsigned flags,
403bf215546Sopenharmony_ci				struct pipe_fence_handle **fence)
404bf215546Sopenharmony_ci{
405bf215546Sopenharmony_ci	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
406bf215546Sopenharmony_ci	struct radeon_cmdbuf *cs = &rctx->dma.cs;
407bf215546Sopenharmony_ci	struct radeon_saved_cs saved;
408bf215546Sopenharmony_ci	bool check_vm =
409bf215546Sopenharmony_ci		(rctx->screen->debug_flags & DBG_CHECK_VM) &&
410bf215546Sopenharmony_ci		rctx->check_vm_faults;
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci	if (!radeon_emitted(cs, 0)) {
413bf215546Sopenharmony_ci		if (fence)
414bf215546Sopenharmony_ci			rctx->ws->fence_reference(fence, rctx->last_sdma_fence);
415bf215546Sopenharmony_ci		return;
416bf215546Sopenharmony_ci	}
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ci	if (check_vm)
419bf215546Sopenharmony_ci		radeon_save_cs(rctx->ws, cs, &saved, true);
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ci	rctx->ws->cs_flush(cs, flags, &rctx->last_sdma_fence);
422bf215546Sopenharmony_ci	if (fence)
423bf215546Sopenharmony_ci		rctx->ws->fence_reference(fence, rctx->last_sdma_fence);
424bf215546Sopenharmony_ci
425bf215546Sopenharmony_ci	if (check_vm) {
426bf215546Sopenharmony_ci		/* Use conservative timeout 800ms, after which we won't wait any
427bf215546Sopenharmony_ci		 * longer and assume the GPU is hung.
428bf215546Sopenharmony_ci		 */
429bf215546Sopenharmony_ci		rctx->ws->fence_wait(rctx->ws, rctx->last_sdma_fence, 800*1000*1000);
430bf215546Sopenharmony_ci
431bf215546Sopenharmony_ci		rctx->check_vm_faults(rctx, &saved, AMD_IP_SDMA);
432bf215546Sopenharmony_ci		radeon_clear_saved_cs(&saved);
433bf215546Sopenharmony_ci	}
434bf215546Sopenharmony_ci}
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci/**
437bf215546Sopenharmony_ci * Store a linearized copy of all chunks of \p cs together with the buffer
438bf215546Sopenharmony_ci * list in \p saved.
439bf215546Sopenharmony_ci */
440bf215546Sopenharmony_civoid radeon_save_cs(struct radeon_winsys *ws, struct radeon_cmdbuf *cs,
441bf215546Sopenharmony_ci		    struct radeon_saved_cs *saved, bool get_buffer_list)
442bf215546Sopenharmony_ci{
443bf215546Sopenharmony_ci	uint32_t *buf;
444bf215546Sopenharmony_ci	unsigned i;
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_ci	/* Save the IB chunks. */
447bf215546Sopenharmony_ci	saved->num_dw = cs->prev_dw + cs->current.cdw;
448bf215546Sopenharmony_ci	saved->ib = MALLOC(4 * saved->num_dw);
449bf215546Sopenharmony_ci	if (!saved->ib)
450bf215546Sopenharmony_ci		goto oom;
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci	buf = saved->ib;
453bf215546Sopenharmony_ci	for (i = 0; i < cs->num_prev; ++i) {
454bf215546Sopenharmony_ci		memcpy(buf, cs->prev[i].buf, cs->prev[i].cdw * 4);
455bf215546Sopenharmony_ci		buf += cs->prev[i].cdw;
456bf215546Sopenharmony_ci	}
457bf215546Sopenharmony_ci	memcpy(buf, cs->current.buf, cs->current.cdw * 4);
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci	if (!get_buffer_list)
460bf215546Sopenharmony_ci		return;
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci	/* Save the buffer list. */
463bf215546Sopenharmony_ci	saved->bo_count = ws->cs_get_buffer_list(cs, NULL);
464bf215546Sopenharmony_ci	saved->bo_list = CALLOC(saved->bo_count,
465bf215546Sopenharmony_ci				sizeof(saved->bo_list[0]));
466bf215546Sopenharmony_ci	if (!saved->bo_list) {
467bf215546Sopenharmony_ci		FREE(saved->ib);
468bf215546Sopenharmony_ci		goto oom;
469bf215546Sopenharmony_ci	}
470bf215546Sopenharmony_ci	ws->cs_get_buffer_list(cs, saved->bo_list);
471bf215546Sopenharmony_ci
472bf215546Sopenharmony_ci	return;
473bf215546Sopenharmony_ci
474bf215546Sopenharmony_cioom:
475bf215546Sopenharmony_ci	fprintf(stderr, "%s: out of memory\n", __func__);
476bf215546Sopenharmony_ci	memset(saved, 0, sizeof(*saved));
477bf215546Sopenharmony_ci}
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_civoid radeon_clear_saved_cs(struct radeon_saved_cs *saved)
480bf215546Sopenharmony_ci{
481bf215546Sopenharmony_ci	FREE(saved->ib);
482bf215546Sopenharmony_ci	FREE(saved->bo_list);
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci	memset(saved, 0, sizeof(*saved));
485bf215546Sopenharmony_ci}
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_cistatic enum pipe_reset_status r600_get_reset_status(struct pipe_context *ctx)
488bf215546Sopenharmony_ci{
489bf215546Sopenharmony_ci	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci	return rctx->ws->ctx_query_reset_status(rctx->ctx, false, NULL);
492bf215546Sopenharmony_ci}
493bf215546Sopenharmony_ci
494bf215546Sopenharmony_cistatic void r600_set_debug_callback(struct pipe_context *ctx,
495bf215546Sopenharmony_ci				    const struct util_debug_callback *cb)
496bf215546Sopenharmony_ci{
497bf215546Sopenharmony_ci	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_ci	if (cb)
500bf215546Sopenharmony_ci		rctx->debug = *cb;
501bf215546Sopenharmony_ci	else
502bf215546Sopenharmony_ci		memset(&rctx->debug, 0, sizeof(rctx->debug));
503bf215546Sopenharmony_ci}
504bf215546Sopenharmony_ci
505bf215546Sopenharmony_cistatic void r600_set_device_reset_callback(struct pipe_context *ctx,
506bf215546Sopenharmony_ci					   const struct pipe_device_reset_callback *cb)
507bf215546Sopenharmony_ci{
508bf215546Sopenharmony_ci	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
509bf215546Sopenharmony_ci
510bf215546Sopenharmony_ci	if (cb)
511bf215546Sopenharmony_ci		rctx->device_reset_callback = *cb;
512bf215546Sopenharmony_ci	else
513bf215546Sopenharmony_ci		memset(&rctx->device_reset_callback, 0,
514bf215546Sopenharmony_ci		       sizeof(rctx->device_reset_callback));
515bf215546Sopenharmony_ci}
516bf215546Sopenharmony_ci
517bf215546Sopenharmony_cibool r600_check_device_reset(struct r600_common_context *rctx)
518bf215546Sopenharmony_ci{
519bf215546Sopenharmony_ci	enum pipe_reset_status status;
520bf215546Sopenharmony_ci
521bf215546Sopenharmony_ci	if (!rctx->device_reset_callback.reset)
522bf215546Sopenharmony_ci		return false;
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_ci	if (!rctx->b.get_device_reset_status)
525bf215546Sopenharmony_ci		return false;
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_ci	status = rctx->b.get_device_reset_status(&rctx->b);
528bf215546Sopenharmony_ci	if (status == PIPE_NO_RESET)
529bf215546Sopenharmony_ci		return false;
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ci	rctx->device_reset_callback.reset(rctx->device_reset_callback.data, status);
532bf215546Sopenharmony_ci	return true;
533bf215546Sopenharmony_ci}
534bf215546Sopenharmony_ci
535bf215546Sopenharmony_cistatic void r600_dma_clear_buffer_fallback(struct pipe_context *ctx,
536bf215546Sopenharmony_ci					   struct pipe_resource *dst,
537bf215546Sopenharmony_ci					   uint64_t offset, uint64_t size,
538bf215546Sopenharmony_ci					   unsigned value)
539bf215546Sopenharmony_ci{
540bf215546Sopenharmony_ci	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ci	rctx->clear_buffer(ctx, dst, offset, size, value, R600_COHERENCY_NONE);
543bf215546Sopenharmony_ci}
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_cistatic bool r600_resource_commit(struct pipe_context *pctx,
546bf215546Sopenharmony_ci				 struct pipe_resource *resource,
547bf215546Sopenharmony_ci				 unsigned level, struct pipe_box *box,
548bf215546Sopenharmony_ci				 bool commit)
549bf215546Sopenharmony_ci{
550bf215546Sopenharmony_ci	struct r600_common_context *ctx = (struct r600_common_context *)pctx;
551bf215546Sopenharmony_ci	struct r600_resource *res = r600_resource(resource);
552bf215546Sopenharmony_ci
553bf215546Sopenharmony_ci	/*
554bf215546Sopenharmony_ci	 * Since buffer commitment changes cannot be pipelined, we need to
555bf215546Sopenharmony_ci	 * (a) flush any pending commands that refer to the buffer we're about
556bf215546Sopenharmony_ci	 *     to change, and
557bf215546Sopenharmony_ci	 * (b) wait for threaded submit to finish, including those that were
558bf215546Sopenharmony_ci	 *     triggered by some other, earlier operation.
559bf215546Sopenharmony_ci	 */
560bf215546Sopenharmony_ci	if (radeon_emitted(&ctx->gfx.cs, ctx->initial_gfx_cs_size) &&
561bf215546Sopenharmony_ci	    ctx->ws->cs_is_buffer_referenced(&ctx->gfx.cs,
562bf215546Sopenharmony_ci					     res->buf, RADEON_USAGE_READWRITE)) {
563bf215546Sopenharmony_ci		ctx->gfx.flush(ctx, PIPE_FLUSH_ASYNC, NULL);
564bf215546Sopenharmony_ci	}
565bf215546Sopenharmony_ci	if (radeon_emitted(&ctx->dma.cs, 0) &&
566bf215546Sopenharmony_ci	    ctx->ws->cs_is_buffer_referenced(&ctx->dma.cs,
567bf215546Sopenharmony_ci					     res->buf, RADEON_USAGE_READWRITE)) {
568bf215546Sopenharmony_ci		ctx->dma.flush(ctx, PIPE_FLUSH_ASYNC, NULL);
569bf215546Sopenharmony_ci	}
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_ci	ctx->ws->cs_sync_flush(&ctx->dma.cs);
572bf215546Sopenharmony_ci	ctx->ws->cs_sync_flush(&ctx->gfx.cs);
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci	assert(resource->target == PIPE_BUFFER);
575bf215546Sopenharmony_ci
576bf215546Sopenharmony_ci	return ctx->ws->buffer_commit(ctx->ws, res->buf, box->x, box->width, commit);
577bf215546Sopenharmony_ci}
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_cibool r600_common_context_init(struct r600_common_context *rctx,
580bf215546Sopenharmony_ci			      struct r600_common_screen *rscreen,
581bf215546Sopenharmony_ci			      unsigned context_flags)
582bf215546Sopenharmony_ci{
583bf215546Sopenharmony_ci	slab_create_child(&rctx->pool_transfers, &rscreen->pool_transfers);
584bf215546Sopenharmony_ci	slab_create_child(&rctx->pool_transfers_unsync, &rscreen->pool_transfers);
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_ci	rctx->screen = rscreen;
587bf215546Sopenharmony_ci	rctx->ws = rscreen->ws;
588bf215546Sopenharmony_ci	rctx->family = rscreen->family;
589bf215546Sopenharmony_ci	rctx->gfx_level = rscreen->gfx_level;
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_ci	rctx->b.invalidate_resource = r600_invalidate_resource;
592bf215546Sopenharmony_ci	rctx->b.resource_commit = r600_resource_commit;
593bf215546Sopenharmony_ci	rctx->b.buffer_map = r600_buffer_transfer_map;
594bf215546Sopenharmony_ci        rctx->b.texture_map = r600_texture_transfer_map;
595bf215546Sopenharmony_ci	rctx->b.transfer_flush_region = r600_buffer_flush_region;
596bf215546Sopenharmony_ci	rctx->b.buffer_unmap = r600_buffer_transfer_unmap;
597bf215546Sopenharmony_ci        rctx->b.texture_unmap = r600_texture_transfer_unmap;
598bf215546Sopenharmony_ci	rctx->b.texture_subdata = u_default_texture_subdata;
599bf215546Sopenharmony_ci	rctx->b.flush = r600_flush_from_st;
600bf215546Sopenharmony_ci	rctx->b.set_debug_callback = r600_set_debug_callback;
601bf215546Sopenharmony_ci	rctx->b.fence_server_sync = r600_fence_server_sync;
602bf215546Sopenharmony_ci	rctx->dma_clear_buffer = r600_dma_clear_buffer_fallback;
603bf215546Sopenharmony_ci
604bf215546Sopenharmony_ci	/* evergreen_compute.c has a special codepath for global buffers.
605bf215546Sopenharmony_ci	 * Everything else can use the direct path.
606bf215546Sopenharmony_ci	 */
607bf215546Sopenharmony_ci	if ((rscreen->gfx_level == EVERGREEN || rscreen->gfx_level == CAYMAN) &&
608bf215546Sopenharmony_ci	    (context_flags & PIPE_CONTEXT_COMPUTE_ONLY))
609bf215546Sopenharmony_ci		rctx->b.buffer_subdata = u_default_buffer_subdata;
610bf215546Sopenharmony_ci	else
611bf215546Sopenharmony_ci		rctx->b.buffer_subdata = r600_buffer_subdata;
612bf215546Sopenharmony_ci
613bf215546Sopenharmony_ci	rctx->b.get_device_reset_status = r600_get_reset_status;
614bf215546Sopenharmony_ci	rctx->b.set_device_reset_callback = r600_set_device_reset_callback;
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_ci	r600_init_context_texture_functions(rctx);
617bf215546Sopenharmony_ci	r600_init_viewport_functions(rctx);
618bf215546Sopenharmony_ci	r600_streamout_init(rctx);
619bf215546Sopenharmony_ci	r600_query_init(rctx);
620bf215546Sopenharmony_ci	cayman_init_msaa(&rctx->b);
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_ci	u_suballocator_init(&rctx->allocator_zeroed_memory, &rctx->b, rscreen->info.gart_page_size,
623bf215546Sopenharmony_ci			    0, PIPE_USAGE_DEFAULT, 0, true);
624bf215546Sopenharmony_ci
625bf215546Sopenharmony_ci	rctx->b.stream_uploader = u_upload_create(&rctx->b, 1024 * 1024,
626bf215546Sopenharmony_ci						  0, PIPE_USAGE_STREAM, 0);
627bf215546Sopenharmony_ci	if (!rctx->b.stream_uploader)
628bf215546Sopenharmony_ci		return false;
629bf215546Sopenharmony_ci
630bf215546Sopenharmony_ci	rctx->b.const_uploader = u_upload_create(&rctx->b, 128 * 1024,
631bf215546Sopenharmony_ci						 0, PIPE_USAGE_DEFAULT, 0);
632bf215546Sopenharmony_ci	if (!rctx->b.const_uploader)
633bf215546Sopenharmony_ci		return false;
634bf215546Sopenharmony_ci
635bf215546Sopenharmony_ci	rctx->ctx = rctx->ws->ctx_create(rctx->ws, RADEON_CTX_PRIORITY_MEDIUM);
636bf215546Sopenharmony_ci	if (!rctx->ctx)
637bf215546Sopenharmony_ci		return false;
638bf215546Sopenharmony_ci
639bf215546Sopenharmony_ci	if (rscreen->info.ip[AMD_IP_SDMA].num_queues && !(rscreen->debug_flags & DBG_NO_ASYNC_DMA)) {
640bf215546Sopenharmony_ci		rctx->ws->cs_create(&rctx->dma.cs, rctx->ctx, AMD_IP_SDMA,
641bf215546Sopenharmony_ci                                    r600_flush_dma_ring, rctx, false);
642bf215546Sopenharmony_ci		rctx->dma.flush = r600_flush_dma_ring;
643bf215546Sopenharmony_ci	}
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci	return true;
646bf215546Sopenharmony_ci}
647bf215546Sopenharmony_ci
648bf215546Sopenharmony_civoid r600_common_context_cleanup(struct r600_common_context *rctx)
649bf215546Sopenharmony_ci{
650bf215546Sopenharmony_ci	if (rctx->query_result_shader)
651bf215546Sopenharmony_ci		rctx->b.delete_compute_state(&rctx->b, rctx->query_result_shader);
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_ci	rctx->ws->cs_destroy(&rctx->gfx.cs);
654bf215546Sopenharmony_ci	rctx->ws->cs_destroy(&rctx->dma.cs);
655bf215546Sopenharmony_ci	if (rctx->ctx)
656bf215546Sopenharmony_ci		rctx->ws->ctx_destroy(rctx->ctx);
657bf215546Sopenharmony_ci
658bf215546Sopenharmony_ci	if (rctx->b.stream_uploader)
659bf215546Sopenharmony_ci		u_upload_destroy(rctx->b.stream_uploader);
660bf215546Sopenharmony_ci	if (rctx->b.const_uploader)
661bf215546Sopenharmony_ci		u_upload_destroy(rctx->b.const_uploader);
662bf215546Sopenharmony_ci
663bf215546Sopenharmony_ci	slab_destroy_child(&rctx->pool_transfers);
664bf215546Sopenharmony_ci	slab_destroy_child(&rctx->pool_transfers_unsync);
665bf215546Sopenharmony_ci
666bf215546Sopenharmony_ci	u_suballocator_destroy(&rctx->allocator_zeroed_memory);
667bf215546Sopenharmony_ci	rctx->ws->fence_reference(&rctx->last_gfx_fence, NULL);
668bf215546Sopenharmony_ci	rctx->ws->fence_reference(&rctx->last_sdma_fence, NULL);
669bf215546Sopenharmony_ci	r600_resource_reference(&rctx->eop_bug_scratch, NULL);
670bf215546Sopenharmony_ci}
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_ci/*
673bf215546Sopenharmony_ci * pipe_screen
674bf215546Sopenharmony_ci */
675bf215546Sopenharmony_ci
676bf215546Sopenharmony_cistatic const struct debug_named_value common_debug_options[] = {
677bf215546Sopenharmony_ci	/* logging */
678bf215546Sopenharmony_ci	{ "tex", DBG_TEX, "Print texture info" },
679bf215546Sopenharmony_ci	{ "nir", DBG_NIR, "Enable experimental NIR shaders" },
680bf215546Sopenharmony_ci	{ "compute", DBG_COMPUTE, "Print compute info" },
681bf215546Sopenharmony_ci	{ "vm", DBG_VM, "Print virtual addresses when creating resources" },
682bf215546Sopenharmony_ci	{ "info", DBG_INFO, "Print driver information" },
683bf215546Sopenharmony_ci
684bf215546Sopenharmony_ci	/* shaders */
685bf215546Sopenharmony_ci	{ "fs", DBG_FS, "Print fetch shaders" },
686bf215546Sopenharmony_ci	{ "vs", DBG_VS, "Print vertex shaders" },
687bf215546Sopenharmony_ci	{ "gs", DBG_GS, "Print geometry shaders" },
688bf215546Sopenharmony_ci	{ "ps", DBG_PS, "Print pixel shaders" },
689bf215546Sopenharmony_ci	{ "cs", DBG_CS, "Print compute shaders" },
690bf215546Sopenharmony_ci	{ "tcs", DBG_TCS, "Print tessellation control shaders" },
691bf215546Sopenharmony_ci	{ "tes", DBG_TES, "Print tessellation evaluation shaders" },
692bf215546Sopenharmony_ci	{ "preoptir", DBG_PREOPT_IR, "Print the LLVM IR before initial optimizations" },
693bf215546Sopenharmony_ci	{ "checkir", DBG_CHECK_IR, "Enable additional sanity checks on shader IR" },
694bf215546Sopenharmony_ci	{ "use_tgsi", DBG_USE_TGSI, "Take TGSI directly instead of using NIR-to-TGSI"},
695bf215546Sopenharmony_ci
696bf215546Sopenharmony_ci	{ "testdma", DBG_TEST_DMA, "Invoke SDMA tests and exit." },
697bf215546Sopenharmony_ci	{ "testvmfaultcp", DBG_TEST_VMFAULT_CP, "Invoke a CP VM fault test and exit." },
698bf215546Sopenharmony_ci	{ "testvmfaultsdma", DBG_TEST_VMFAULT_SDMA, "Invoke a SDMA VM fault test and exit." },
699bf215546Sopenharmony_ci	{ "testvmfaultshader", DBG_TEST_VMFAULT_SHADER, "Invoke a shader VM fault test and exit." },
700bf215546Sopenharmony_ci
701bf215546Sopenharmony_ci	/* features */
702bf215546Sopenharmony_ci	{ "nodma", DBG_NO_ASYNC_DMA, "Disable asynchronous DMA" },
703bf215546Sopenharmony_ci	{ "nohyperz", DBG_NO_HYPERZ, "Disable Hyper-Z" },
704bf215546Sopenharmony_ci	/* GL uses the word INVALIDATE, gallium uses the word DISCARD */
705bf215546Sopenharmony_ci	{ "noinvalrange", DBG_NO_DISCARD_RANGE, "Disable handling of INVALIDATE_RANGE map flags" },
706bf215546Sopenharmony_ci	{ "no2d", DBG_NO_2D_TILING, "Disable 2D tiling" },
707bf215546Sopenharmony_ci	{ "notiling", DBG_NO_TILING, "Disable tiling" },
708bf215546Sopenharmony_ci	{ "switch_on_eop", DBG_SWITCH_ON_EOP, "Program WD/IA to switch on end-of-packet." },
709bf215546Sopenharmony_ci	{ "forcedma", DBG_FORCE_DMA, "Use asynchronous DMA for all operations when possible." },
710bf215546Sopenharmony_ci	{ "nowc", DBG_NO_WC, "Disable GTT write combining" },
711bf215546Sopenharmony_ci	{ "check_vm", DBG_CHECK_VM, "Check VM faults and dump debug info." },
712bf215546Sopenharmony_ci
713bf215546Sopenharmony_ci	DEBUG_NAMED_VALUE_END /* must be last */
714bf215546Sopenharmony_ci};
715bf215546Sopenharmony_ci
716bf215546Sopenharmony_cistatic const char* r600_get_vendor(struct pipe_screen* pscreen)
717bf215546Sopenharmony_ci{
718bf215546Sopenharmony_ci	return "X.Org";
719bf215546Sopenharmony_ci}
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_cistatic const char* r600_get_device_vendor(struct pipe_screen* pscreen)
722bf215546Sopenharmony_ci{
723bf215546Sopenharmony_ci	return "AMD";
724bf215546Sopenharmony_ci}
725bf215546Sopenharmony_ci
726bf215546Sopenharmony_cistatic const char *r600_get_family_name(const struct r600_common_screen *rscreen)
727bf215546Sopenharmony_ci{
728bf215546Sopenharmony_ci	switch (rscreen->info.family) {
729bf215546Sopenharmony_ci	case CHIP_R600: return "AMD R600";
730bf215546Sopenharmony_ci	case CHIP_RV610: return "AMD RV610";
731bf215546Sopenharmony_ci	case CHIP_RV630: return "AMD RV630";
732bf215546Sopenharmony_ci	case CHIP_RV670: return "AMD RV670";
733bf215546Sopenharmony_ci	case CHIP_RV620: return "AMD RV620";
734bf215546Sopenharmony_ci	case CHIP_RV635: return "AMD RV635";
735bf215546Sopenharmony_ci	case CHIP_RS780: return "AMD RS780";
736bf215546Sopenharmony_ci	case CHIP_RS880: return "AMD RS880";
737bf215546Sopenharmony_ci	case CHIP_RV770: return "AMD RV770";
738bf215546Sopenharmony_ci	case CHIP_RV730: return "AMD RV730";
739bf215546Sopenharmony_ci	case CHIP_RV710: return "AMD RV710";
740bf215546Sopenharmony_ci	case CHIP_RV740: return "AMD RV740";
741bf215546Sopenharmony_ci	case CHIP_CEDAR: return "AMD CEDAR";
742bf215546Sopenharmony_ci	case CHIP_REDWOOD: return "AMD REDWOOD";
743bf215546Sopenharmony_ci	case CHIP_JUNIPER: return "AMD JUNIPER";
744bf215546Sopenharmony_ci	case CHIP_CYPRESS: return "AMD CYPRESS";
745bf215546Sopenharmony_ci	case CHIP_HEMLOCK: return "AMD HEMLOCK";
746bf215546Sopenharmony_ci	case CHIP_PALM: return "AMD PALM";
747bf215546Sopenharmony_ci	case CHIP_SUMO: return "AMD SUMO";
748bf215546Sopenharmony_ci	case CHIP_SUMO2: return "AMD SUMO2";
749bf215546Sopenharmony_ci	case CHIP_BARTS: return "AMD BARTS";
750bf215546Sopenharmony_ci	case CHIP_TURKS: return "AMD TURKS";
751bf215546Sopenharmony_ci	case CHIP_CAICOS: return "AMD CAICOS";
752bf215546Sopenharmony_ci	case CHIP_CAYMAN: return "AMD CAYMAN";
753bf215546Sopenharmony_ci	case CHIP_ARUBA: return "AMD ARUBA";
754bf215546Sopenharmony_ci	default: return "AMD unknown";
755bf215546Sopenharmony_ci	}
756bf215546Sopenharmony_ci}
757bf215546Sopenharmony_ci
758bf215546Sopenharmony_cistatic void r600_disk_cache_create(struct r600_common_screen *rscreen)
759bf215546Sopenharmony_ci{
760bf215546Sopenharmony_ci	/* Don't use the cache if shader dumping is enabled. */
761bf215546Sopenharmony_ci	if (rscreen->debug_flags & DBG_ALL_SHADERS)
762bf215546Sopenharmony_ci		return;
763bf215546Sopenharmony_ci
764bf215546Sopenharmony_ci	struct mesa_sha1 ctx;
765bf215546Sopenharmony_ci	unsigned char sha1[20];
766bf215546Sopenharmony_ci	char cache_id[20 * 2 + 1];
767bf215546Sopenharmony_ci
768bf215546Sopenharmony_ci	_mesa_sha1_init(&ctx);
769bf215546Sopenharmony_ci	if (!disk_cache_get_function_identifier(r600_disk_cache_create,
770bf215546Sopenharmony_ci						&ctx))
771bf215546Sopenharmony_ci		return;
772bf215546Sopenharmony_ci
773bf215546Sopenharmony_ci	_mesa_sha1_final(&ctx, sha1);
774bf215546Sopenharmony_ci	disk_cache_format_hex_id(cache_id, sha1, 20 * 2);
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_ci	/* These flags affect shader compilation. */
777bf215546Sopenharmony_ci	uint64_t shader_debug_flags =
778bf215546Sopenharmony_ci		rscreen->debug_flags &
779bf215546Sopenharmony_ci		(DBG_NIR |
780bf215546Sopenharmony_ci		 DBG_NIR_PREFERRED |
781bf215546Sopenharmony_ci		 DBG_USE_TGSI);
782bf215546Sopenharmony_ci
783bf215546Sopenharmony_ci	rscreen->disk_shader_cache =
784bf215546Sopenharmony_ci		disk_cache_create(r600_get_family_name(rscreen),
785bf215546Sopenharmony_ci				  cache_id,
786bf215546Sopenharmony_ci				  shader_debug_flags);
787bf215546Sopenharmony_ci}
788bf215546Sopenharmony_ci
789bf215546Sopenharmony_cistatic struct disk_cache *r600_get_disk_shader_cache(struct pipe_screen *pscreen)
790bf215546Sopenharmony_ci{
791bf215546Sopenharmony_ci	struct r600_common_screen *rscreen = (struct r600_common_screen*)pscreen;
792bf215546Sopenharmony_ci	return rscreen->disk_shader_cache;
793bf215546Sopenharmony_ci}
794bf215546Sopenharmony_ci
795bf215546Sopenharmony_cistatic const char* r600_get_name(struct pipe_screen* pscreen)
796bf215546Sopenharmony_ci{
797bf215546Sopenharmony_ci	struct r600_common_screen *rscreen = (struct r600_common_screen*)pscreen;
798bf215546Sopenharmony_ci
799bf215546Sopenharmony_ci	return rscreen->renderer_string;
800bf215546Sopenharmony_ci}
801bf215546Sopenharmony_ci
802bf215546Sopenharmony_cistatic float r600_get_paramf(struct pipe_screen* pscreen,
803bf215546Sopenharmony_ci			     enum pipe_capf param)
804bf215546Sopenharmony_ci{
805bf215546Sopenharmony_ci	switch (param) {
806bf215546Sopenharmony_ci	case PIPE_CAPF_MIN_LINE_WIDTH:
807bf215546Sopenharmony_ci	case PIPE_CAPF_MIN_LINE_WIDTH_AA:
808bf215546Sopenharmony_ci	case PIPE_CAPF_MIN_POINT_SIZE:
809bf215546Sopenharmony_ci	case PIPE_CAPF_MIN_POINT_SIZE_AA:
810bf215546Sopenharmony_ci		return 1;
811bf215546Sopenharmony_ci
812bf215546Sopenharmony_ci	case PIPE_CAPF_POINT_SIZE_GRANULARITY:
813bf215546Sopenharmony_ci	case PIPE_CAPF_LINE_WIDTH_GRANULARITY:
814bf215546Sopenharmony_ci		return 0.1;
815bf215546Sopenharmony_ci
816bf215546Sopenharmony_ci	case PIPE_CAPF_MAX_LINE_WIDTH:
817bf215546Sopenharmony_ci	case PIPE_CAPF_MAX_LINE_WIDTH_AA:
818bf215546Sopenharmony_ci	case PIPE_CAPF_MAX_POINT_SIZE:
819bf215546Sopenharmony_ci	case PIPE_CAPF_MAX_POINT_SIZE_AA:
820bf215546Sopenharmony_ci         return 8191.0f;
821bf215546Sopenharmony_ci	case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
822bf215546Sopenharmony_ci		return 16.0f;
823bf215546Sopenharmony_ci	case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
824bf215546Sopenharmony_ci		return 16.0f;
825bf215546Sopenharmony_ci    case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:
826bf215546Sopenharmony_ci    case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:
827bf215546Sopenharmony_ci    case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:
828bf215546Sopenharmony_ci        return 0.0f;
829bf215546Sopenharmony_ci	}
830bf215546Sopenharmony_ci	return 0.0f;
831bf215546Sopenharmony_ci}
832bf215546Sopenharmony_ci
833bf215546Sopenharmony_cistatic int r600_get_video_param(struct pipe_screen *screen,
834bf215546Sopenharmony_ci				enum pipe_video_profile profile,
835bf215546Sopenharmony_ci				enum pipe_video_entrypoint entrypoint,
836bf215546Sopenharmony_ci				enum pipe_video_cap param)
837bf215546Sopenharmony_ci{
838bf215546Sopenharmony_ci	switch (param) {
839bf215546Sopenharmony_ci	case PIPE_VIDEO_CAP_SUPPORTED:
840bf215546Sopenharmony_ci		return vl_profile_supported(screen, profile, entrypoint);
841bf215546Sopenharmony_ci	case PIPE_VIDEO_CAP_NPOT_TEXTURES:
842bf215546Sopenharmony_ci		return 1;
843bf215546Sopenharmony_ci	case PIPE_VIDEO_CAP_MAX_WIDTH:
844bf215546Sopenharmony_ci	case PIPE_VIDEO_CAP_MAX_HEIGHT:
845bf215546Sopenharmony_ci		return vl_video_buffer_max_size(screen);
846bf215546Sopenharmony_ci	case PIPE_VIDEO_CAP_PREFERED_FORMAT:
847bf215546Sopenharmony_ci		return PIPE_FORMAT_NV12;
848bf215546Sopenharmony_ci	case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
849bf215546Sopenharmony_ci		return false;
850bf215546Sopenharmony_ci	case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
851bf215546Sopenharmony_ci		return false;
852bf215546Sopenharmony_ci	case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
853bf215546Sopenharmony_ci		return true;
854bf215546Sopenharmony_ci	case PIPE_VIDEO_CAP_MAX_LEVEL:
855bf215546Sopenharmony_ci		return vl_level_supported(screen, profile);
856bf215546Sopenharmony_ci	default:
857bf215546Sopenharmony_ci		return 0;
858bf215546Sopenharmony_ci	}
859bf215546Sopenharmony_ci}
860bf215546Sopenharmony_ci
861bf215546Sopenharmony_ciconst char *r600_get_llvm_processor_name(enum radeon_family family)
862bf215546Sopenharmony_ci{
863bf215546Sopenharmony_ci	switch (family) {
864bf215546Sopenharmony_ci	case CHIP_R600:
865bf215546Sopenharmony_ci	case CHIP_RV630:
866bf215546Sopenharmony_ci	case CHIP_RV635:
867bf215546Sopenharmony_ci	case CHIP_RV670:
868bf215546Sopenharmony_ci		return "r600";
869bf215546Sopenharmony_ci	case CHIP_RV610:
870bf215546Sopenharmony_ci	case CHIP_RV620:
871bf215546Sopenharmony_ci	case CHIP_RS780:
872bf215546Sopenharmony_ci	case CHIP_RS880:
873bf215546Sopenharmony_ci		return "rs880";
874bf215546Sopenharmony_ci	case CHIP_RV710:
875bf215546Sopenharmony_ci		return "rv710";
876bf215546Sopenharmony_ci	case CHIP_RV730:
877bf215546Sopenharmony_ci		return "rv730";
878bf215546Sopenharmony_ci	case CHIP_RV740:
879bf215546Sopenharmony_ci	case CHIP_RV770:
880bf215546Sopenharmony_ci		return "rv770";
881bf215546Sopenharmony_ci	case CHIP_PALM:
882bf215546Sopenharmony_ci	case CHIP_CEDAR:
883bf215546Sopenharmony_ci		return "cedar";
884bf215546Sopenharmony_ci	case CHIP_SUMO:
885bf215546Sopenharmony_ci	case CHIP_SUMO2:
886bf215546Sopenharmony_ci		return "sumo";
887bf215546Sopenharmony_ci	case CHIP_REDWOOD:
888bf215546Sopenharmony_ci		return "redwood";
889bf215546Sopenharmony_ci	case CHIP_JUNIPER:
890bf215546Sopenharmony_ci		return "juniper";
891bf215546Sopenharmony_ci	case CHIP_HEMLOCK:
892bf215546Sopenharmony_ci	case CHIP_CYPRESS:
893bf215546Sopenharmony_ci		return "cypress";
894bf215546Sopenharmony_ci	case CHIP_BARTS:
895bf215546Sopenharmony_ci		return "barts";
896bf215546Sopenharmony_ci	case CHIP_TURKS:
897bf215546Sopenharmony_ci		return "turks";
898bf215546Sopenharmony_ci	case CHIP_CAICOS:
899bf215546Sopenharmony_ci		return "caicos";
900bf215546Sopenharmony_ci	case CHIP_CAYMAN:
901bf215546Sopenharmony_ci        case CHIP_ARUBA:
902bf215546Sopenharmony_ci		return "cayman";
903bf215546Sopenharmony_ci
904bf215546Sopenharmony_ci	default:
905bf215546Sopenharmony_ci		return "";
906bf215546Sopenharmony_ci	}
907bf215546Sopenharmony_ci}
908bf215546Sopenharmony_ci
909bf215546Sopenharmony_cistatic unsigned get_max_threads_per_block(struct r600_common_screen *screen,
910bf215546Sopenharmony_ci					  enum pipe_shader_ir ir_type)
911bf215546Sopenharmony_ci{
912bf215546Sopenharmony_ci	if (ir_type != PIPE_SHADER_IR_TGSI &&
913bf215546Sopenharmony_ci	    ir_type != PIPE_SHADER_IR_NIR)
914bf215546Sopenharmony_ci		return 256;
915bf215546Sopenharmony_ci	if (screen->gfx_level >= EVERGREEN)
916bf215546Sopenharmony_ci		return 1024;
917bf215546Sopenharmony_ci	return 256;
918bf215546Sopenharmony_ci}
919bf215546Sopenharmony_ci
920bf215546Sopenharmony_cistatic int r600_get_compute_param(struct pipe_screen *screen,
921bf215546Sopenharmony_ci        enum pipe_shader_ir ir_type,
922bf215546Sopenharmony_ci        enum pipe_compute_cap param,
923bf215546Sopenharmony_ci        void *ret)
924bf215546Sopenharmony_ci{
925bf215546Sopenharmony_ci	struct r600_common_screen *rscreen = (struct r600_common_screen *)screen;
926bf215546Sopenharmony_ci
927bf215546Sopenharmony_ci	//TODO: select these params by asic
928bf215546Sopenharmony_ci	switch (param) {
929bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_IR_TARGET: {
930bf215546Sopenharmony_ci		const char *gpu;
931bf215546Sopenharmony_ci		const char *triple = "r600--";
932bf215546Sopenharmony_ci		gpu = r600_get_llvm_processor_name(rscreen->family);
933bf215546Sopenharmony_ci		if (ret) {
934bf215546Sopenharmony_ci			sprintf(ret, "%s-%s", gpu, triple);
935bf215546Sopenharmony_ci		}
936bf215546Sopenharmony_ci		/* +2 for dash and terminating NIL byte */
937bf215546Sopenharmony_ci		return (strlen(triple) + strlen(gpu) + 2) * sizeof(char);
938bf215546Sopenharmony_ci	}
939bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_GRID_DIMENSION:
940bf215546Sopenharmony_ci		if (ret) {
941bf215546Sopenharmony_ci			uint64_t *grid_dimension = ret;
942bf215546Sopenharmony_ci			grid_dimension[0] = 3;
943bf215546Sopenharmony_ci		}
944bf215546Sopenharmony_ci		return 1 * sizeof(uint64_t);
945bf215546Sopenharmony_ci
946bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_MAX_GRID_SIZE:
947bf215546Sopenharmony_ci		if (ret) {
948bf215546Sopenharmony_ci			uint64_t *grid_size = ret;
949bf215546Sopenharmony_ci			grid_size[0] = 65535;
950bf215546Sopenharmony_ci			grid_size[1] = 65535;
951bf215546Sopenharmony_ci			grid_size[2] = 65535;
952bf215546Sopenharmony_ci		}
953bf215546Sopenharmony_ci		return 3 * sizeof(uint64_t) ;
954bf215546Sopenharmony_ci
955bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE:
956bf215546Sopenharmony_ci		if (ret) {
957bf215546Sopenharmony_ci			uint64_t *block_size = ret;
958bf215546Sopenharmony_ci			unsigned threads_per_block = get_max_threads_per_block(rscreen, ir_type);
959bf215546Sopenharmony_ci			block_size[0] = threads_per_block;
960bf215546Sopenharmony_ci			block_size[1] = threads_per_block;
961bf215546Sopenharmony_ci			block_size[2] = threads_per_block;
962bf215546Sopenharmony_ci		}
963bf215546Sopenharmony_ci		return 3 * sizeof(uint64_t);
964bf215546Sopenharmony_ci
965bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK:
966bf215546Sopenharmony_ci		if (ret) {
967bf215546Sopenharmony_ci			uint64_t *max_threads_per_block = ret;
968bf215546Sopenharmony_ci			*max_threads_per_block = get_max_threads_per_block(rscreen, ir_type);
969bf215546Sopenharmony_ci		}
970bf215546Sopenharmony_ci		return sizeof(uint64_t);
971bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_ADDRESS_BITS:
972bf215546Sopenharmony_ci		if (ret) {
973bf215546Sopenharmony_ci			uint32_t *address_bits = ret;
974bf215546Sopenharmony_ci			address_bits[0] = 32;
975bf215546Sopenharmony_ci		}
976bf215546Sopenharmony_ci		return 1 * sizeof(uint32_t);
977bf215546Sopenharmony_ci
978bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE:
979bf215546Sopenharmony_ci		if (ret) {
980bf215546Sopenharmony_ci			uint64_t *max_global_size = ret;
981bf215546Sopenharmony_ci			uint64_t max_mem_alloc_size;
982bf215546Sopenharmony_ci
983bf215546Sopenharmony_ci			r600_get_compute_param(screen, ir_type,
984bf215546Sopenharmony_ci				PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE,
985bf215546Sopenharmony_ci				&max_mem_alloc_size);
986bf215546Sopenharmony_ci
987bf215546Sopenharmony_ci			/* In OpenCL, the MAX_MEM_ALLOC_SIZE must be at least
988bf215546Sopenharmony_ci			 * 1/4 of the MAX_GLOBAL_SIZE.  Since the
989bf215546Sopenharmony_ci			 * MAX_MEM_ALLOC_SIZE is fixed for older kernels,
990bf215546Sopenharmony_ci			 * make sure we never report more than
991bf215546Sopenharmony_ci			 * 4 * MAX_MEM_ALLOC_SIZE.
992bf215546Sopenharmony_ci			 */
993bf215546Sopenharmony_ci			*max_global_size = MIN2(4 * max_mem_alloc_size,
994bf215546Sopenharmony_ci						rscreen->info.max_heap_size_kb * 1024ull);
995bf215546Sopenharmony_ci		}
996bf215546Sopenharmony_ci		return sizeof(uint64_t);
997bf215546Sopenharmony_ci
998bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE:
999bf215546Sopenharmony_ci		if (ret) {
1000bf215546Sopenharmony_ci			uint64_t *max_local_size = ret;
1001bf215546Sopenharmony_ci			/* Value reported by the closed source driver. */
1002bf215546Sopenharmony_ci			*max_local_size = 32768;
1003bf215546Sopenharmony_ci		}
1004bf215546Sopenharmony_ci		return sizeof(uint64_t);
1005bf215546Sopenharmony_ci
1006bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_MAX_INPUT_SIZE:
1007bf215546Sopenharmony_ci		if (ret) {
1008bf215546Sopenharmony_ci			uint64_t *max_input_size = ret;
1009bf215546Sopenharmony_ci			/* Value reported by the closed source driver. */
1010bf215546Sopenharmony_ci			*max_input_size = 1024;
1011bf215546Sopenharmony_ci		}
1012bf215546Sopenharmony_ci		return sizeof(uint64_t);
1013bf215546Sopenharmony_ci
1014bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE:
1015bf215546Sopenharmony_ci		if (ret) {
1016bf215546Sopenharmony_ci			uint64_t *max_mem_alloc_size = ret;
1017bf215546Sopenharmony_ci
1018bf215546Sopenharmony_ci			*max_mem_alloc_size = (rscreen->info.max_heap_size_kb / 4) * 1024ull;
1019bf215546Sopenharmony_ci		}
1020bf215546Sopenharmony_ci		return sizeof(uint64_t);
1021bf215546Sopenharmony_ci
1022bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_MAX_CLOCK_FREQUENCY:
1023bf215546Sopenharmony_ci		if (ret) {
1024bf215546Sopenharmony_ci			uint32_t *max_clock_frequency = ret;
1025bf215546Sopenharmony_ci			*max_clock_frequency = rscreen->info.max_gpu_freq_mhz;
1026bf215546Sopenharmony_ci		}
1027bf215546Sopenharmony_ci		return sizeof(uint32_t);
1028bf215546Sopenharmony_ci
1029bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_MAX_COMPUTE_UNITS:
1030bf215546Sopenharmony_ci		if (ret) {
1031bf215546Sopenharmony_ci			uint32_t *max_compute_units = ret;
1032bf215546Sopenharmony_ci			*max_compute_units = rscreen->info.num_cu;
1033bf215546Sopenharmony_ci		}
1034bf215546Sopenharmony_ci		return sizeof(uint32_t);
1035bf215546Sopenharmony_ci
1036bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_IMAGES_SUPPORTED:
1037bf215546Sopenharmony_ci		if (ret) {
1038bf215546Sopenharmony_ci			uint32_t *images_supported = ret;
1039bf215546Sopenharmony_ci			*images_supported = 0;
1040bf215546Sopenharmony_ci		}
1041bf215546Sopenharmony_ci		return sizeof(uint32_t);
1042bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_MAX_PRIVATE_SIZE:
1043bf215546Sopenharmony_ci		break; /* unused */
1044bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_SUBGROUP_SIZE:
1045bf215546Sopenharmony_ci		if (ret) {
1046bf215546Sopenharmony_ci			uint32_t *subgroup_size = ret;
1047bf215546Sopenharmony_ci			*subgroup_size = r600_wavefront_size(rscreen->family);
1048bf215546Sopenharmony_ci		}
1049bf215546Sopenharmony_ci		return sizeof(uint32_t);
1050bf215546Sopenharmony_ci	case PIPE_COMPUTE_CAP_MAX_VARIABLE_THREADS_PER_BLOCK:
1051bf215546Sopenharmony_ci		if (ret) {
1052bf215546Sopenharmony_ci			uint64_t *max_variable_threads_per_block = ret;
1053bf215546Sopenharmony_ci			*max_variable_threads_per_block = 0;
1054bf215546Sopenharmony_ci		}
1055bf215546Sopenharmony_ci		return sizeof(uint64_t);
1056bf215546Sopenharmony_ci	}
1057bf215546Sopenharmony_ci
1058bf215546Sopenharmony_ci        fprintf(stderr, "unknown PIPE_COMPUTE_CAP %d\n", param);
1059bf215546Sopenharmony_ci        return 0;
1060bf215546Sopenharmony_ci}
1061bf215546Sopenharmony_ci
1062bf215546Sopenharmony_cistatic uint64_t r600_get_timestamp(struct pipe_screen *screen)
1063bf215546Sopenharmony_ci{
1064bf215546Sopenharmony_ci	struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;
1065bf215546Sopenharmony_ci
1066bf215546Sopenharmony_ci	return 1000000 * rscreen->ws->query_value(rscreen->ws, RADEON_TIMESTAMP) /
1067bf215546Sopenharmony_ci			rscreen->info.clock_crystal_freq;
1068bf215546Sopenharmony_ci}
1069bf215546Sopenharmony_ci
1070bf215546Sopenharmony_cistatic void r600_fence_reference(struct pipe_screen *screen,
1071bf215546Sopenharmony_ci				 struct pipe_fence_handle **dst,
1072bf215546Sopenharmony_ci				 struct pipe_fence_handle *src)
1073bf215546Sopenharmony_ci{
1074bf215546Sopenharmony_ci	struct radeon_winsys *ws = ((struct r600_common_screen*)screen)->ws;
1075bf215546Sopenharmony_ci	struct r600_multi_fence **rdst = (struct r600_multi_fence **)dst;
1076bf215546Sopenharmony_ci	struct r600_multi_fence *rsrc = (struct r600_multi_fence *)src;
1077bf215546Sopenharmony_ci
1078bf215546Sopenharmony_ci	if (pipe_reference(&(*rdst)->reference, &rsrc->reference)) {
1079bf215546Sopenharmony_ci		ws->fence_reference(&(*rdst)->gfx, NULL);
1080bf215546Sopenharmony_ci		ws->fence_reference(&(*rdst)->sdma, NULL);
1081bf215546Sopenharmony_ci		FREE(*rdst);
1082bf215546Sopenharmony_ci	}
1083bf215546Sopenharmony_ci        *rdst = rsrc;
1084bf215546Sopenharmony_ci}
1085bf215546Sopenharmony_ci
1086bf215546Sopenharmony_cistatic bool r600_fence_finish(struct pipe_screen *screen,
1087bf215546Sopenharmony_ci			      struct pipe_context *ctx,
1088bf215546Sopenharmony_ci			      struct pipe_fence_handle *fence,
1089bf215546Sopenharmony_ci			      uint64_t timeout)
1090bf215546Sopenharmony_ci{
1091bf215546Sopenharmony_ci	struct radeon_winsys *rws = ((struct r600_common_screen*)screen)->ws;
1092bf215546Sopenharmony_ci	struct r600_multi_fence *rfence = (struct r600_multi_fence *)fence;
1093bf215546Sopenharmony_ci	struct r600_common_context *rctx;
1094bf215546Sopenharmony_ci	int64_t abs_timeout = os_time_get_absolute_timeout(timeout);
1095bf215546Sopenharmony_ci
1096bf215546Sopenharmony_ci	ctx = threaded_context_unwrap_sync(ctx);
1097bf215546Sopenharmony_ci	rctx = ctx ? (struct r600_common_context*)ctx : NULL;
1098bf215546Sopenharmony_ci
1099bf215546Sopenharmony_ci	if (rfence->sdma) {
1100bf215546Sopenharmony_ci		if (!rws->fence_wait(rws, rfence->sdma, timeout))
1101bf215546Sopenharmony_ci			return false;
1102bf215546Sopenharmony_ci
1103bf215546Sopenharmony_ci		/* Recompute the timeout after waiting. */
1104bf215546Sopenharmony_ci		if (timeout && timeout != PIPE_TIMEOUT_INFINITE) {
1105bf215546Sopenharmony_ci			int64_t time = os_time_get_nano();
1106bf215546Sopenharmony_ci			timeout = abs_timeout > time ? abs_timeout - time : 0;
1107bf215546Sopenharmony_ci		}
1108bf215546Sopenharmony_ci	}
1109bf215546Sopenharmony_ci
1110bf215546Sopenharmony_ci	if (!rfence->gfx)
1111bf215546Sopenharmony_ci		return true;
1112bf215546Sopenharmony_ci
1113bf215546Sopenharmony_ci	/* Flush the gfx IB if it hasn't been flushed yet. */
1114bf215546Sopenharmony_ci	if (rctx &&
1115bf215546Sopenharmony_ci	    rfence->gfx_unflushed.ctx == rctx &&
1116bf215546Sopenharmony_ci	    rfence->gfx_unflushed.ib_index == rctx->num_gfx_cs_flushes) {
1117bf215546Sopenharmony_ci		rctx->gfx.flush(rctx, timeout ? 0 : PIPE_FLUSH_ASYNC, NULL);
1118bf215546Sopenharmony_ci		rfence->gfx_unflushed.ctx = NULL;
1119bf215546Sopenharmony_ci
1120bf215546Sopenharmony_ci		if (!timeout)
1121bf215546Sopenharmony_ci			return false;
1122bf215546Sopenharmony_ci
1123bf215546Sopenharmony_ci		/* Recompute the timeout after all that. */
1124bf215546Sopenharmony_ci		if (timeout && timeout != PIPE_TIMEOUT_INFINITE) {
1125bf215546Sopenharmony_ci			int64_t time = os_time_get_nano();
1126bf215546Sopenharmony_ci			timeout = abs_timeout > time ? abs_timeout - time : 0;
1127bf215546Sopenharmony_ci		}
1128bf215546Sopenharmony_ci	}
1129bf215546Sopenharmony_ci
1130bf215546Sopenharmony_ci	return rws->fence_wait(rws, rfence->gfx, timeout);
1131bf215546Sopenharmony_ci}
1132bf215546Sopenharmony_ci
1133bf215546Sopenharmony_cistatic void r600_query_memory_info(struct pipe_screen *screen,
1134bf215546Sopenharmony_ci				   struct pipe_memory_info *info)
1135bf215546Sopenharmony_ci{
1136bf215546Sopenharmony_ci	struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;
1137bf215546Sopenharmony_ci	struct radeon_winsys *ws = rscreen->ws;
1138bf215546Sopenharmony_ci	unsigned vram_usage, gtt_usage;
1139bf215546Sopenharmony_ci
1140bf215546Sopenharmony_ci	info->total_device_memory = rscreen->info.vram_size_kb;
1141bf215546Sopenharmony_ci	info->total_staging_memory = rscreen->info.gart_size_kb;
1142bf215546Sopenharmony_ci
1143bf215546Sopenharmony_ci	/* The real TTM memory usage is somewhat random, because:
1144bf215546Sopenharmony_ci	 *
1145bf215546Sopenharmony_ci	 * 1) TTM delays freeing memory, because it can only free it after
1146bf215546Sopenharmony_ci	 *    fences expire.
1147bf215546Sopenharmony_ci	 *
1148bf215546Sopenharmony_ci	 * 2) The memory usage can be really low if big VRAM evictions are
1149bf215546Sopenharmony_ci	 *    taking place, but the real usage is well above the size of VRAM.
1150bf215546Sopenharmony_ci	 *
1151bf215546Sopenharmony_ci	 * Instead, return statistics of this process.
1152bf215546Sopenharmony_ci	 */
1153bf215546Sopenharmony_ci	vram_usage = ws->query_value(ws, RADEON_REQUESTED_VRAM_MEMORY) / 1024;
1154bf215546Sopenharmony_ci	gtt_usage =  ws->query_value(ws, RADEON_REQUESTED_GTT_MEMORY) / 1024;
1155bf215546Sopenharmony_ci
1156bf215546Sopenharmony_ci	info->avail_device_memory =
1157bf215546Sopenharmony_ci		vram_usage <= info->total_device_memory ?
1158bf215546Sopenharmony_ci				info->total_device_memory - vram_usage : 0;
1159bf215546Sopenharmony_ci	info->avail_staging_memory =
1160bf215546Sopenharmony_ci		gtt_usage <= info->total_staging_memory ?
1161bf215546Sopenharmony_ci				info->total_staging_memory - gtt_usage : 0;
1162bf215546Sopenharmony_ci
1163bf215546Sopenharmony_ci	info->device_memory_evicted =
1164bf215546Sopenharmony_ci		ws->query_value(ws, RADEON_NUM_BYTES_MOVED) / 1024;
1165bf215546Sopenharmony_ci
1166bf215546Sopenharmony_ci	/* Just return the number of evicted 64KB pages. */
1167bf215546Sopenharmony_ci	info->nr_device_memory_evictions = info->device_memory_evicted / 64;
1168bf215546Sopenharmony_ci}
1169bf215546Sopenharmony_ci
1170bf215546Sopenharmony_cistruct pipe_resource *r600_resource_create_common(struct pipe_screen *screen,
1171bf215546Sopenharmony_ci						  const struct pipe_resource *templ)
1172bf215546Sopenharmony_ci{
1173bf215546Sopenharmony_ci	if (templ->target == PIPE_BUFFER) {
1174bf215546Sopenharmony_ci		return r600_buffer_create(screen, templ, 256);
1175bf215546Sopenharmony_ci	} else {
1176bf215546Sopenharmony_ci		return r600_texture_create(screen, templ);
1177bf215546Sopenharmony_ci	}
1178bf215546Sopenharmony_ci}
1179bf215546Sopenharmony_ci
1180bf215546Sopenharmony_cistatic const void *
1181bf215546Sopenharmony_cir600_get_compiler_options(struct pipe_screen *screen,
1182bf215546Sopenharmony_ci			  enum pipe_shader_ir ir,
1183bf215546Sopenharmony_ci			  enum pipe_shader_type shader)
1184bf215546Sopenharmony_ci{
1185bf215546Sopenharmony_ci       assert(ir == PIPE_SHADER_IR_NIR);
1186bf215546Sopenharmony_ci
1187bf215546Sopenharmony_ci       struct r600_common_screen *rscreen = (struct r600_common_screen *)screen;
1188bf215546Sopenharmony_ci
1189bf215546Sopenharmony_ci       if (shader != PIPE_SHADER_FRAGMENT)
1190bf215546Sopenharmony_ci          return &rscreen->nir_options;
1191bf215546Sopenharmony_ci       else
1192bf215546Sopenharmony_ci          return &rscreen->nir_options_fs;
1193bf215546Sopenharmony_ci}
1194bf215546Sopenharmony_ci
1195bf215546Sopenharmony_ciextern bool r600_lower_to_scalar_instr_filter(const nir_instr *instr, const void *);
1196bf215546Sopenharmony_ci
1197bf215546Sopenharmony_cistatic void r600_resource_destroy(struct pipe_screen *screen,
1198bf215546Sopenharmony_ci				  struct pipe_resource *res)
1199bf215546Sopenharmony_ci{
1200bf215546Sopenharmony_ci	if (res->target == PIPE_BUFFER) {
1201bf215546Sopenharmony_ci		if (r600_resource(res)->compute_global_bo)
1202bf215546Sopenharmony_ci			r600_compute_global_buffer_destroy(screen, res);
1203bf215546Sopenharmony_ci		else
1204bf215546Sopenharmony_ci			r600_buffer_destroy(screen, res);
1205bf215546Sopenharmony_ci	} else {
1206bf215546Sopenharmony_ci		r600_texture_destroy(screen, res);
1207bf215546Sopenharmony_ci	}
1208bf215546Sopenharmony_ci}
1209bf215546Sopenharmony_ci
1210bf215546Sopenharmony_cibool r600_common_screen_init(struct r600_common_screen *rscreen,
1211bf215546Sopenharmony_ci			     struct radeon_winsys *ws)
1212bf215546Sopenharmony_ci{
1213bf215546Sopenharmony_ci	char family_name[32] = {}, kernel_version[128] = {};
1214bf215546Sopenharmony_ci	struct utsname uname_data;
1215bf215546Sopenharmony_ci	const char *chip_name;
1216bf215546Sopenharmony_ci
1217bf215546Sopenharmony_ci	ws->query_info(ws, &rscreen->info, false, false);
1218bf215546Sopenharmony_ci	rscreen->ws = ws;
1219bf215546Sopenharmony_ci
1220bf215546Sopenharmony_ci	chip_name = r600_get_family_name(rscreen);
1221bf215546Sopenharmony_ci
1222bf215546Sopenharmony_ci	if (uname(&uname_data) == 0)
1223bf215546Sopenharmony_ci		snprintf(kernel_version, sizeof(kernel_version),
1224bf215546Sopenharmony_ci			 " / %s", uname_data.release);
1225bf215546Sopenharmony_ci
1226bf215546Sopenharmony_ci	snprintf(rscreen->renderer_string, sizeof(rscreen->renderer_string),
1227bf215546Sopenharmony_ci		 "%s (%sDRM %i.%i.%i%s"
1228bf215546Sopenharmony_ci#ifdef LLVM_AVAILABLE
1229bf215546Sopenharmony_ci		 ", LLVM " MESA_LLVM_VERSION_STRING
1230bf215546Sopenharmony_ci#endif
1231bf215546Sopenharmony_ci		 ")",
1232bf215546Sopenharmony_ci		 chip_name, family_name, rscreen->info.drm_major,
1233bf215546Sopenharmony_ci		 rscreen->info.drm_minor, rscreen->info.drm_patchlevel,
1234bf215546Sopenharmony_ci		 kernel_version);
1235bf215546Sopenharmony_ci
1236bf215546Sopenharmony_ci	rscreen->b.get_name = r600_get_name;
1237bf215546Sopenharmony_ci	rscreen->b.get_vendor = r600_get_vendor;
1238bf215546Sopenharmony_ci	rscreen->b.get_device_vendor = r600_get_device_vendor;
1239bf215546Sopenharmony_ci	rscreen->b.get_disk_shader_cache = r600_get_disk_shader_cache;
1240bf215546Sopenharmony_ci	rscreen->b.get_compute_param = r600_get_compute_param;
1241bf215546Sopenharmony_ci	rscreen->b.get_paramf = r600_get_paramf;
1242bf215546Sopenharmony_ci	rscreen->b.get_timestamp = r600_get_timestamp;
1243bf215546Sopenharmony_ci	rscreen->b.get_compiler_options = r600_get_compiler_options;
1244bf215546Sopenharmony_ci	rscreen->b.fence_finish = r600_fence_finish;
1245bf215546Sopenharmony_ci	rscreen->b.fence_reference = r600_fence_reference;
1246bf215546Sopenharmony_ci	rscreen->b.resource_destroy = r600_resource_destroy;
1247bf215546Sopenharmony_ci	rscreen->b.resource_from_user_memory = r600_buffer_from_user_memory;
1248bf215546Sopenharmony_ci	rscreen->b.query_memory_info = r600_query_memory_info;
1249bf215546Sopenharmony_ci
1250bf215546Sopenharmony_ci	if (rscreen->info.ip[AMD_IP_UVD].num_queues) {
1251bf215546Sopenharmony_ci		rscreen->b.get_video_param = rvid_get_video_param;
1252bf215546Sopenharmony_ci		rscreen->b.is_video_format_supported = rvid_is_format_supported;
1253bf215546Sopenharmony_ci	} else {
1254bf215546Sopenharmony_ci		rscreen->b.get_video_param = r600_get_video_param;
1255bf215546Sopenharmony_ci		rscreen->b.is_video_format_supported = vl_video_buffer_is_format_supported;
1256bf215546Sopenharmony_ci	}
1257bf215546Sopenharmony_ci
1258bf215546Sopenharmony_ci	r600_init_screen_texture_functions(rscreen);
1259bf215546Sopenharmony_ci	r600_init_screen_query_functions(rscreen);
1260bf215546Sopenharmony_ci
1261bf215546Sopenharmony_ci	rscreen->family = rscreen->info.family;
1262bf215546Sopenharmony_ci	rscreen->gfx_level = rscreen->info.gfx_level;
1263bf215546Sopenharmony_ci	rscreen->debug_flags |= debug_get_flags_option("R600_DEBUG", common_debug_options, 0);
1264bf215546Sopenharmony_ci
1265bf215546Sopenharmony_ci	r600_disk_cache_create(rscreen);
1266bf215546Sopenharmony_ci
1267bf215546Sopenharmony_ci	slab_create_parent(&rscreen->pool_transfers, sizeof(struct r600_transfer), 64);
1268bf215546Sopenharmony_ci
1269bf215546Sopenharmony_ci	rscreen->force_aniso = MIN2(16, debug_get_num_option("R600_TEX_ANISO", -1));
1270bf215546Sopenharmony_ci	if (rscreen->force_aniso >= 0) {
1271bf215546Sopenharmony_ci		printf("radeon: Forcing anisotropy filter to %ix\n",
1272bf215546Sopenharmony_ci		       /* round down to a power of two */
1273bf215546Sopenharmony_ci		       1 << util_logbase2(rscreen->force_aniso));
1274bf215546Sopenharmony_ci	}
1275bf215546Sopenharmony_ci
1276bf215546Sopenharmony_ci	(void) mtx_init(&rscreen->aux_context_lock, mtx_plain);
1277bf215546Sopenharmony_ci	(void) mtx_init(&rscreen->gpu_load_mutex, mtx_plain);
1278bf215546Sopenharmony_ci
1279bf215546Sopenharmony_ci	if (rscreen->debug_flags & DBG_INFO) {
1280bf215546Sopenharmony_ci		printf("pci (domain:bus:dev.func): %04x:%02x:%02x.%x\n",
1281bf215546Sopenharmony_ci		       rscreen->info.pci_domain, rscreen->info.pci_bus,
1282bf215546Sopenharmony_ci		       rscreen->info.pci_dev, rscreen->info.pci_func);
1283bf215546Sopenharmony_ci		printf("pci_id = 0x%x\n", rscreen->info.pci_id);
1284bf215546Sopenharmony_ci		printf("family = %i (%s)\n", rscreen->info.family,
1285bf215546Sopenharmony_ci		       r600_get_family_name(rscreen));
1286bf215546Sopenharmony_ci		printf("gfx_level = %i\n", rscreen->info.gfx_level);
1287bf215546Sopenharmony_ci		printf("pte_fragment_size = %u\n", rscreen->info.pte_fragment_size);
1288bf215546Sopenharmony_ci		printf("gart_page_size = %u\n", rscreen->info.gart_page_size);
1289bf215546Sopenharmony_ci		printf("gart_size = %i MB\n", (int)DIV_ROUND_UP(rscreen->info.gart_size_kb, 1024));
1290bf215546Sopenharmony_ci		printf("vram_size = %i MB\n", (int)DIV_ROUND_UP(rscreen->info.vram_size_kb, 1024));
1291bf215546Sopenharmony_ci		printf("vram_vis_size = %i MB\n", (int)DIV_ROUND_UP(rscreen->info.vram_vis_size_kb, 1024));
1292bf215546Sopenharmony_ci		printf("max_heap_size = %i MB\n",
1293bf215546Sopenharmony_ci		       (int)DIV_ROUND_UP(rscreen->info.max_heap_size_kb, 1024));
1294bf215546Sopenharmony_ci		printf("min_alloc_size = %u\n", rscreen->info.min_alloc_size);
1295bf215546Sopenharmony_ci		printf("has_dedicated_vram = %u\n", rscreen->info.has_dedicated_vram);
1296bf215546Sopenharmony_ci		printf("r600_has_virtual_memory = %i\n", rscreen->info.r600_has_virtual_memory);
1297bf215546Sopenharmony_ci		printf("gfx_ib_pad_with_type2 = %i\n", rscreen->info.gfx_ib_pad_with_type2);
1298bf215546Sopenharmony_ci		printf("ip[AMD_IP_UVD] = %u\n", rscreen->info.ip[AMD_IP_UVD].num_queues);
1299bf215546Sopenharmony_ci		printf("ip[AMD_IP_SDMA] = %i\n", rscreen->info.ip[AMD_IP_SDMA].num_queues);
1300bf215546Sopenharmony_ci		printf("ip[AMD_IP_COMPUTE] = %u\n", rscreen->info.ip[AMD_IP_COMPUTE].num_queues);
1301bf215546Sopenharmony_ci		printf("uvd_fw_version = %u\n", rscreen->info.uvd_fw_version);
1302bf215546Sopenharmony_ci		printf("vce_fw_version = %u\n", rscreen->info.vce_fw_version);
1303bf215546Sopenharmony_ci		printf("me_fw_version = %i\n", rscreen->info.me_fw_version);
1304bf215546Sopenharmony_ci		printf("pfp_fw_version = %i\n", rscreen->info.pfp_fw_version);
1305bf215546Sopenharmony_ci		printf("vce_harvest_config = %i\n", rscreen->info.vce_harvest_config);
1306bf215546Sopenharmony_ci		printf("clock_crystal_freq = %i\n", rscreen->info.clock_crystal_freq);
1307bf215546Sopenharmony_ci		printf("tcc_cache_line_size = %u\n", rscreen->info.tcc_cache_line_size);
1308bf215546Sopenharmony_ci		printf("drm = %i.%i.%i\n", rscreen->info.drm_major,
1309bf215546Sopenharmony_ci		       rscreen->info.drm_minor, rscreen->info.drm_patchlevel);
1310bf215546Sopenharmony_ci		printf("has_userptr = %i\n", rscreen->info.has_userptr);
1311bf215546Sopenharmony_ci		printf("has_syncobj = %u\n", rscreen->info.has_syncobj);
1312bf215546Sopenharmony_ci
1313bf215546Sopenharmony_ci		printf("r600_max_quad_pipes = %i\n", rscreen->info.r600_max_quad_pipes);
1314bf215546Sopenharmony_ci		printf("max_gpu_freq_mhz = %i\n", rscreen->info.max_gpu_freq_mhz);
1315bf215546Sopenharmony_ci		printf("num_cu = %i\n", rscreen->info.num_cu);
1316bf215546Sopenharmony_ci		printf("max_se = %i\n", rscreen->info.max_se);
1317bf215546Sopenharmony_ci		printf("max_sh_per_se = %i\n", rscreen->info.max_sa_per_se);
1318bf215546Sopenharmony_ci
1319bf215546Sopenharmony_ci		printf("r600_gb_backend_map = %i\n", rscreen->info.r600_gb_backend_map);
1320bf215546Sopenharmony_ci		printf("r600_gb_backend_map_valid = %i\n", rscreen->info.r600_gb_backend_map_valid);
1321bf215546Sopenharmony_ci		printf("r600_num_banks = %i\n", rscreen->info.r600_num_banks);
1322bf215546Sopenharmony_ci		printf("num_render_backends = %i\n", rscreen->info.max_render_backends);
1323bf215546Sopenharmony_ci		printf("num_tile_pipes = %i\n", rscreen->info.num_tile_pipes);
1324bf215546Sopenharmony_ci		printf("pipe_interleave_bytes = %i\n", rscreen->info.pipe_interleave_bytes);
1325bf215546Sopenharmony_ci		printf("enabled_rb_mask = 0x%x\n", rscreen->info.enabled_rb_mask);
1326bf215546Sopenharmony_ci		printf("max_alignment = %u\n", (unsigned)rscreen->info.max_alignment);
1327bf215546Sopenharmony_ci	}
1328bf215546Sopenharmony_ci
1329bf215546Sopenharmony_ci	const struct nir_shader_compiler_options nir_options = {
1330bf215546Sopenharmony_ci		.fuse_ffma16 = true,
1331bf215546Sopenharmony_ci		.fuse_ffma32 = true,
1332bf215546Sopenharmony_ci		.fuse_ffma64 = true,
1333bf215546Sopenharmony_ci		.lower_flrp32 = true,
1334bf215546Sopenharmony_ci		.lower_flrp64 = true,
1335bf215546Sopenharmony_ci		.lower_fdiv = true,
1336bf215546Sopenharmony_ci		.lower_isign = true,
1337bf215546Sopenharmony_ci		.lower_fsign = true,
1338bf215546Sopenharmony_ci		.lower_fmod = true,
1339bf215546Sopenharmony_ci		.lower_extract_byte = true,
1340bf215546Sopenharmony_ci		.lower_extract_word = true,
1341bf215546Sopenharmony_ci		.lower_insert_byte = true,
1342bf215546Sopenharmony_ci		.lower_insert_word = true,
1343bf215546Sopenharmony_ci		.lower_rotate = true,
1344bf215546Sopenharmony_ci		/* due to a bug in the shader compiler, some loops hang
1345bf215546Sopenharmony_ci		 * if they are not unrolled, see:
1346bf215546Sopenharmony_ci		 *    https://bugs.freedesktop.org/show_bug.cgi?id=86720
1347bf215546Sopenharmony_ci		 */
1348bf215546Sopenharmony_ci		.max_unroll_iterations = 255,
1349bf215546Sopenharmony_ci		.lower_interpolate_at = true,
1350bf215546Sopenharmony_ci		.vectorize_io = true,
1351bf215546Sopenharmony_ci		.has_umad24 = true,
1352bf215546Sopenharmony_ci		.has_umul24 = true,
1353bf215546Sopenharmony_ci		.has_fmulz = true,
1354bf215546Sopenharmony_ci		.use_interpolated_input_intrinsics = true,
1355bf215546Sopenharmony_ci		.has_fsub = true,
1356bf215546Sopenharmony_ci		.has_isub = true,
1357bf215546Sopenharmony_ci		.lower_iabs = true,
1358bf215546Sopenharmony_ci		.lower_uadd_sat = true,
1359bf215546Sopenharmony_ci		.lower_usub_sat = true,
1360bf215546Sopenharmony_ci		.lower_bitfield_extract = true,
1361bf215546Sopenharmony_ci		.lower_bitfield_insert_to_bitfield_select = true,
1362bf215546Sopenharmony_ci		.has_fused_comp_and_csel = true,
1363bf215546Sopenharmony_ci		.lower_find_msb_to_reverse = true,
1364bf215546Sopenharmony_ci		.lower_to_scalar = true,
1365bf215546Sopenharmony_ci		.lower_to_scalar_filter = r600_lower_to_scalar_instr_filter,
1366bf215546Sopenharmony_ci		.linker_ignore_precision = true,
1367bf215546Sopenharmony_ci		.lower_fpow = true,
1368bf215546Sopenharmony_ci		.lower_int64_options = ~0
1369bf215546Sopenharmony_ci	};
1370bf215546Sopenharmony_ci
1371bf215546Sopenharmony_ci	rscreen->nir_options = nir_options;
1372bf215546Sopenharmony_ci
1373bf215546Sopenharmony_ci	if (rscreen->info.family < CHIP_CEDAR)
1374bf215546Sopenharmony_ci		rscreen->nir_options.force_indirect_unrolling_sampler = true;
1375bf215546Sopenharmony_ci
1376bf215546Sopenharmony_ci	if (rscreen->info.gfx_level < EVERGREEN) {
1377bf215546Sopenharmony_ci		/* Pre-EG doesn't have these ALU ops */
1378bf215546Sopenharmony_ci		rscreen->nir_options.lower_bit_count = true;
1379bf215546Sopenharmony_ci		rscreen->nir_options.lower_bitfield_reverse = true;
1380bf215546Sopenharmony_ci	}
1381bf215546Sopenharmony_ci
1382bf215546Sopenharmony_ci	if (rscreen->info.gfx_level < CAYMAN) {
1383bf215546Sopenharmony_ci		rscreen->nir_options.lower_doubles_options = nir_lower_fp64_full_software;
1384bf215546Sopenharmony_ci	} else {
1385bf215546Sopenharmony_ci		rscreen->nir_options.lower_doubles_options =
1386bf215546Sopenharmony_ci			nir_lower_ddiv |
1387bf215546Sopenharmony_ci			nir_lower_dfloor |
1388bf215546Sopenharmony_ci			nir_lower_dceil |
1389bf215546Sopenharmony_ci			nir_lower_dmod |
1390bf215546Sopenharmony_ci			nir_lower_dsub |
1391bf215546Sopenharmony_ci			nir_lower_dtrunc;
1392bf215546Sopenharmony_ci	}
1393bf215546Sopenharmony_ci
1394bf215546Sopenharmony_ci	if (!(rscreen->debug_flags & DBG_NIR_PREFERRED)) {
1395bf215546Sopenharmony_ci
1396bf215546Sopenharmony_ci		rscreen->nir_options.lower_fpow = false;
1397bf215546Sopenharmony_ci		/* TGSI is vector, and NIR-to-TGSI doesn't like it when the
1398bf215546Sopenharmony_ci		 * input vars have been scalarized.
1399bf215546Sopenharmony_ci		 */
1400bf215546Sopenharmony_ci		rscreen->nir_options.lower_to_scalar = false;
1401bf215546Sopenharmony_ci
1402bf215546Sopenharmony_ci		/* NIR-to-TGSI can't do fused integer csel, and it can't just
1403bf215546Sopenharmony_ci		 * override the flag and get the code lowered back when we ask
1404bf215546Sopenharmony_ci		 * it to handle it.
1405bf215546Sopenharmony_ci		 */
1406bf215546Sopenharmony_ci		rscreen->nir_options.has_fused_comp_and_csel = false;
1407bf215546Sopenharmony_ci
1408bf215546Sopenharmony_ci		/* r600 has a bitfield_select and bitfield_extract opcode
1409bf215546Sopenharmony_ci		 * (called bfi/bfe), but TGSI's BFI/BFE isn't that.
1410bf215546Sopenharmony_ci		 */
1411bf215546Sopenharmony_ci		rscreen->nir_options.lower_bitfield_extract = false;
1412bf215546Sopenharmony_ci		rscreen->nir_options.lower_bitfield_insert_to_bitfield_select = false;
1413bf215546Sopenharmony_ci
1414bf215546Sopenharmony_ci		/* TGSI's ifind is reversed from ours, keep it the TGSI way. */
1415bf215546Sopenharmony_ci		rscreen->nir_options.lower_find_msb_to_reverse = false;
1416bf215546Sopenharmony_ci	} else {
1417bf215546Sopenharmony_ci      rscreen->nir_options.has_fmulz = true;
1418bf215546Sopenharmony_ci   }
1419bf215546Sopenharmony_ci
1420bf215546Sopenharmony_ci	rscreen->nir_options_fs = rscreen->nir_options;
1421bf215546Sopenharmony_ci	rscreen->nir_options_fs.lower_all_io_to_temps = true;
1422bf215546Sopenharmony_ci
1423bf215546Sopenharmony_ci	return true;
1424bf215546Sopenharmony_ci}
1425bf215546Sopenharmony_ci
1426bf215546Sopenharmony_civoid r600_destroy_common_screen(struct r600_common_screen *rscreen)
1427bf215546Sopenharmony_ci{
1428bf215546Sopenharmony_ci	r600_perfcounters_destroy(rscreen);
1429bf215546Sopenharmony_ci	r600_gpu_load_kill_thread(rscreen);
1430bf215546Sopenharmony_ci
1431bf215546Sopenharmony_ci	mtx_destroy(&rscreen->gpu_load_mutex);
1432bf215546Sopenharmony_ci	mtx_destroy(&rscreen->aux_context_lock);
1433bf215546Sopenharmony_ci	rscreen->aux_context->destroy(rscreen->aux_context);
1434bf215546Sopenharmony_ci
1435bf215546Sopenharmony_ci	slab_destroy_parent(&rscreen->pool_transfers);
1436bf215546Sopenharmony_ci
1437bf215546Sopenharmony_ci	disk_cache_destroy(rscreen->disk_shader_cache);
1438bf215546Sopenharmony_ci	rscreen->ws->destroy(rscreen->ws);
1439bf215546Sopenharmony_ci	FREE(rscreen);
1440bf215546Sopenharmony_ci}
1441bf215546Sopenharmony_ci
1442bf215546Sopenharmony_cibool r600_can_dump_shader(struct r600_common_screen *rscreen,
1443bf215546Sopenharmony_ci			  unsigned processor)
1444bf215546Sopenharmony_ci{
1445bf215546Sopenharmony_ci	return rscreen->debug_flags & (1 << processor);
1446bf215546Sopenharmony_ci}
1447bf215546Sopenharmony_ci
1448bf215546Sopenharmony_cibool r600_extra_shader_checks(struct r600_common_screen *rscreen, unsigned processor)
1449bf215546Sopenharmony_ci{
1450bf215546Sopenharmony_ci	return (rscreen->debug_flags & DBG_CHECK_IR) ||
1451bf215546Sopenharmony_ci	       r600_can_dump_shader(rscreen, processor);
1452bf215546Sopenharmony_ci}
1453bf215546Sopenharmony_ci
1454bf215546Sopenharmony_civoid r600_screen_clear_buffer(struct r600_common_screen *rscreen, struct pipe_resource *dst,
1455bf215546Sopenharmony_ci			      uint64_t offset, uint64_t size, unsigned value)
1456bf215546Sopenharmony_ci{
1457bf215546Sopenharmony_ci	struct r600_common_context *rctx = (struct r600_common_context*)rscreen->aux_context;
1458bf215546Sopenharmony_ci
1459bf215546Sopenharmony_ci	mtx_lock(&rscreen->aux_context_lock);
1460bf215546Sopenharmony_ci	rctx->dma_clear_buffer(&rctx->b, dst, offset, size, value);
1461bf215546Sopenharmony_ci	rscreen->aux_context->flush(rscreen->aux_context, NULL, 0);
1462bf215546Sopenharmony_ci	mtx_unlock(&rscreen->aux_context_lock);
1463bf215546Sopenharmony_ci}
1464