2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
27 #include <amdgpu_drm.h>
30 #include "amdgpu_id.h"
31 #include "radv_radeon_winsys.h"
32 #include "radv_amdgpu_cs.h"
33 #include "radv_amdgpu_bo.h"
36 struct radv_amdgpu_cs
{
37 struct radeon_winsys_cs base
;
38 struct radv_amdgpu_winsys
*ws
;
40 struct amdgpu_cs_ib_info ib
;
42 struct radeon_winsys_bo
*ib_buffer
;
44 unsigned max_num_buffers
;
46 amdgpu_bo_handle
*handles
;
49 struct radeon_winsys_bo
**old_ib_buffers
;
50 unsigned num_old_ib_buffers
;
51 unsigned max_num_old_ib_buffers
;
52 unsigned *ib_size_ptr
;
56 int buffer_hash_table
[1024];
59 static inline struct radv_amdgpu_cs
*
60 radv_amdgpu_cs(struct radeon_winsys_cs
*base
)
62 return (struct radv_amdgpu_cs
*)base
;
66 static struct radeon_winsys_fence
*radv_amdgpu_create_fence()
68 struct radv_amdgpu_cs_fence
*fence
= calloc(1, sizeof(struct amdgpu_cs_fence
));
69 return (struct radeon_winsys_fence
*)fence
;
72 static void radv_amdgpu_destroy_fence(struct radeon_winsys_fence
*_fence
)
74 struct amdgpu_cs_fence
*fence
= (struct amdgpu_cs_fence
*)_fence
;
78 static bool radv_amdgpu_fence_wait(struct radeon_winsys
*_ws
,
79 struct radeon_winsys_fence
*_fence
,
83 struct amdgpu_cs_fence
*fence
= (struct amdgpu_cs_fence
*)_fence
;
84 unsigned flags
= absolute
? AMDGPU_QUERY_FENCE_TIMEOUT_IS_ABSOLUTE
: 0;
88 /* Now use the libdrm query. */
89 r
= amdgpu_cs_query_fence_status(fence
,
95 fprintf(stderr
, "amdgpu: radv_amdgpu_cs_query_fence_status failed.\n");
105 static void radv_amdgpu_cs_destroy(struct radeon_winsys_cs
*rcs
)
107 struct radv_amdgpu_cs
*cs
= radv_amdgpu_cs(rcs
);
110 cs
->ws
->base
.buffer_destroy(cs
->ib_buffer
);
114 for (unsigned i
= 0; i
< cs
->num_old_ib_buffers
; ++i
)
115 cs
->ws
->base
.buffer_destroy(cs
->old_ib_buffers
[i
]);
117 free(cs
->old_ib_buffers
);
119 free(cs
->priorities
);
123 static boolean
radv_amdgpu_init_cs(struct radv_amdgpu_cs
*cs
,
124 enum ring_type ring_type
)
126 for (int i
= 0; i
< ARRAY_SIZE(cs
->buffer_hash_table
); ++i
)
127 cs
->buffer_hash_table
[i
] = -1;
132 static struct radeon_winsys_cs
*
133 radv_amdgpu_cs_create(struct radeon_winsys
*ws
,
134 enum ring_type ring_type
)
136 struct radv_amdgpu_cs
*cs
;
137 uint32_t ib_size
= 20 * 1024 * 4;
138 cs
= calloc(1, sizeof(struct radv_amdgpu_cs
));
142 cs
->ws
= radv_amdgpu_winsys(ws
);
143 radv_amdgpu_init_cs(cs
, RING_GFX
);
145 if (cs
->ws
->use_ib_bos
) {
146 cs
->ib_buffer
= ws
->buffer_create(ws
, ib_size
, 0,
148 RADEON_FLAG_CPU_ACCESS
);
149 if (!cs
->ib_buffer
) {
154 cs
->ib_mapped
= ws
->buffer_map(cs
->ib_buffer
);
155 if (!cs
->ib_mapped
) {
156 ws
->buffer_destroy(cs
->ib_buffer
);
161 cs
->ib
.ib_mc_address
= radv_amdgpu_winsys_bo(cs
->ib_buffer
)->va
;
162 cs
->base
.buf
= (uint32_t *)cs
->ib_mapped
;
163 cs
->base
.max_dw
= ib_size
/ 4 - 4;
164 cs
->ib_size_ptr
= &cs
->ib
.size
;
167 ws
->cs_add_buffer(&cs
->base
, cs
->ib_buffer
, 8);
169 cs
->base
.buf
= malloc(16384);
170 cs
->base
.max_dw
= 4096;
180 static void radv_amdgpu_cs_grow(struct radeon_winsys_cs
*_cs
, size_t min_size
)
182 struct radv_amdgpu_cs
*cs
= radv_amdgpu_cs(_cs
);
189 if (!cs
->ws
->use_ib_bos
) {
190 uint64_t ib_size
= MAX2((cs
->base
.cdw
+ min_size
) * 4 + 16,
191 cs
->base
.max_dw
* 4 * 2);
192 uint32_t *new_buf
= realloc(cs
->base
.buf
, ib_size
);
194 cs
->base
.buf
= new_buf
;
195 cs
->base
.max_dw
= ib_size
/ 4;
203 uint64_t ib_size
= MAX2(min_size
* 4 + 16, cs
->base
.max_dw
* 4 * 2);
205 /* max that fits in the chain size field. */
206 ib_size
= MIN2(ib_size
, 0xfffff);
208 while (!cs
->base
.cdw
|| (cs
->base
.cdw
& 7) != 4)
209 cs
->base
.buf
[cs
->base
.cdw
++] = 0xffff1000;
211 *cs
->ib_size_ptr
|= cs
->base
.cdw
+ 4;
213 if (cs
->num_old_ib_buffers
== cs
->max_num_old_ib_buffers
) {
214 cs
->max_num_old_ib_buffers
= MAX2(1, cs
->max_num_old_ib_buffers
* 2);
215 cs
->old_ib_buffers
= realloc(cs
->old_ib_buffers
,
216 cs
->max_num_old_ib_buffers
* sizeof(void*));
219 cs
->old_ib_buffers
[cs
->num_old_ib_buffers
++] = cs
->ib_buffer
;
221 cs
->ib_buffer
= cs
->ws
->base
.buffer_create(&cs
->ws
->base
, ib_size
, 0,
223 RADEON_FLAG_CPU_ACCESS
);
225 if (!cs
->ib_buffer
) {
228 cs
->ib_buffer
= cs
->old_ib_buffers
[--cs
->num_old_ib_buffers
];
231 cs
->ib_mapped
= cs
->ws
->base
.buffer_map(cs
->ib_buffer
);
232 if (!cs
->ib_mapped
) {
233 cs
->ws
->base
.buffer_destroy(cs
->ib_buffer
);
236 cs
->ib_buffer
= cs
->old_ib_buffers
[--cs
->num_old_ib_buffers
];
239 cs
->ws
->base
.cs_add_buffer(&cs
->base
, cs
->ib_buffer
, 8);
241 cs
->base
.buf
[cs
->base
.cdw
++] = PKT3(PKT3_INDIRECT_BUFFER_CIK
, 2, 0);
242 cs
->base
.buf
[cs
->base
.cdw
++] = radv_amdgpu_winsys_bo(cs
->ib_buffer
)->va
;
243 cs
->base
.buf
[cs
->base
.cdw
++] = radv_amdgpu_winsys_bo(cs
->ib_buffer
)->va
>> 32;
244 cs
->ib_size_ptr
= cs
->base
.buf
+ cs
->base
.cdw
;
245 cs
->base
.buf
[cs
->base
.cdw
++] = S_3F2_CHAIN(1) | S_3F2_VALID(1);
247 cs
->base
.buf
= (uint32_t *)cs
->ib_mapped
;
249 cs
->base
.max_dw
= ib_size
/ 4 - 4;
253 static bool radv_amdgpu_cs_finalize(struct radeon_winsys_cs
*_cs
)
255 struct radv_amdgpu_cs
*cs
= radv_amdgpu_cs(_cs
);
257 if (cs
->ws
->use_ib_bos
) {
258 while (!cs
->base
.cdw
|| (cs
->base
.cdw
& 7) != 0)
259 cs
->base
.buf
[cs
->base
.cdw
++] = 0xffff1000;
261 *cs
->ib_size_ptr
|= cs
->base
.cdw
;
263 cs
->is_chained
= false;
269 static void radv_amdgpu_cs_reset(struct radeon_winsys_cs
*_cs
)
271 struct radv_amdgpu_cs
*cs
= radv_amdgpu_cs(_cs
);
275 for (unsigned i
= 0; i
< cs
->num_buffers
; ++i
) {
276 unsigned hash
= ((uintptr_t)cs
->handles
[i
] >> 6) &
277 (ARRAY_SIZE(cs
->buffer_hash_table
) - 1);
278 cs
->buffer_hash_table
[hash
] = -1;
283 if (cs
->ws
->use_ib_bos
) {
284 cs
->ws
->base
.cs_add_buffer(&cs
->base
, cs
->ib_buffer
, 8);
286 for (unsigned i
= 0; i
< cs
->num_old_ib_buffers
; ++i
)
287 cs
->ws
->base
.buffer_destroy(cs
->old_ib_buffers
[i
]);
289 cs
->num_old_ib_buffers
= 0;
290 cs
->ib
.ib_mc_address
= radv_amdgpu_winsys_bo(cs
->ib_buffer
)->va
;
291 cs
->ib_size_ptr
= &cs
->ib
.size
;
296 static int radv_amdgpu_cs_find_buffer(struct radv_amdgpu_cs
*cs
,
299 unsigned hash
= ((uintptr_t)bo
>> 6) & (ARRAY_SIZE(cs
->buffer_hash_table
) - 1);
300 int index
= cs
->buffer_hash_table
[hash
];
305 if (cs
->handles
[index
] == bo
)
308 for (unsigned i
= 0; i
< cs
->num_buffers
; ++i
) {
309 if (cs
->handles
[i
] == bo
) {
310 cs
->buffer_hash_table
[hash
] = i
;
318 static void radv_amdgpu_cs_add_buffer_internal(struct radv_amdgpu_cs
*cs
,
323 int index
= radv_amdgpu_cs_find_buffer(cs
, bo
);
326 cs
->priorities
[index
] = MAX2(cs
->priorities
[index
], priority
);
330 if (cs
->num_buffers
== cs
->max_num_buffers
) {
331 unsigned new_count
= MAX2(1, cs
->max_num_buffers
* 2);
332 cs
->handles
= realloc(cs
->handles
, new_count
* sizeof(amdgpu_bo_handle
));
333 cs
->priorities
= realloc(cs
->priorities
, new_count
* sizeof(uint8_t));
334 cs
->max_num_buffers
= new_count
;
337 cs
->handles
[cs
->num_buffers
] = bo
;
338 cs
->priorities
[cs
->num_buffers
] = priority
;
340 hash
= ((uintptr_t)bo
>> 6) & (ARRAY_SIZE(cs
->buffer_hash_table
) - 1);
341 cs
->buffer_hash_table
[hash
] = cs
->num_buffers
;
346 static void radv_amdgpu_cs_add_buffer(struct radeon_winsys_cs
*_cs
,
347 struct radeon_winsys_bo
*_bo
,
350 struct radv_amdgpu_cs
*cs
= radv_amdgpu_cs(_cs
);
351 struct radv_amdgpu_winsys_bo
*bo
= radv_amdgpu_winsys_bo(_bo
);
353 radv_amdgpu_cs_add_buffer_internal(cs
, bo
->bo
, priority
);
356 static void radv_amdgpu_cs_execute_secondary(struct radeon_winsys_cs
*_parent
,
357 struct radeon_winsys_cs
*_child
)
359 struct radv_amdgpu_cs
*parent
= radv_amdgpu_cs(_parent
);
360 struct radv_amdgpu_cs
*child
= radv_amdgpu_cs(_child
);
362 for (unsigned i
= 0; i
< child
->num_buffers
; ++i
) {
363 radv_amdgpu_cs_add_buffer_internal(parent
, child
->handles
[i
],
364 child
->priorities
[i
]);
367 if (parent
->ws
->use_ib_bos
) {
368 if (parent
->base
.cdw
+ 4 > parent
->base
.max_dw
)
369 radv_amdgpu_cs_grow(&parent
->base
, 4);
371 parent
->base
.buf
[parent
->base
.cdw
++] = PKT3(PKT3_INDIRECT_BUFFER_CIK
, 2, 0);
372 parent
->base
.buf
[parent
->base
.cdw
++] = child
->ib
.ib_mc_address
;
373 parent
->base
.buf
[parent
->base
.cdw
++] = child
->ib
.ib_mc_address
>> 32;
374 parent
->base
.buf
[parent
->base
.cdw
++] = child
->ib
.size
;
376 if (parent
->base
.cdw
+ child
->base
.cdw
> parent
->base
.max_dw
)
377 radv_amdgpu_cs_grow(&parent
->base
, child
->base
.cdw
);
379 memcpy(parent
->base
.buf
+ parent
->base
.cdw
, child
->base
.buf
, 4 * child
->base
.cdw
);
380 parent
->base
.cdw
+= child
->base
.cdw
;
384 static int radv_amdgpu_create_bo_list(struct radv_amdgpu_winsys
*ws
,
385 struct radeon_winsys_cs
**cs_array
,
387 struct radv_amdgpu_winsys_bo
*extra_bo
,
388 amdgpu_bo_list_handle
*bo_list
)
391 if (ws
->debug_all_bos
) {
392 struct radv_amdgpu_winsys_bo
*bo
;
393 amdgpu_bo_handle
*handles
;
396 pthread_mutex_lock(&ws
->global_bo_list_lock
);
398 handles
= malloc(sizeof(handles
[0]) * ws
->num_buffers
);
400 pthread_mutex_unlock(&ws
->global_bo_list_lock
);
404 LIST_FOR_EACH_ENTRY(bo
, &ws
->global_bo_list
, global_list_item
) {
405 assert(num
< ws
->num_buffers
);
406 handles
[num
++] = bo
->bo
;
409 r
= amdgpu_bo_list_create(ws
->dev
, ws
->num_buffers
,
413 pthread_mutex_unlock(&ws
->global_bo_list_lock
);
414 } else if (count
== 1 && !extra_bo
) {
415 struct radv_amdgpu_cs
*cs
= (struct radv_amdgpu_cs
*)cs_array
[0];
416 r
= amdgpu_bo_list_create(ws
->dev
, cs
->num_buffers
, cs
->handles
,
417 cs
->priorities
, bo_list
);
419 unsigned total_buffer_count
= !!extra_bo
;
420 unsigned unique_bo_count
= !!extra_bo
;
421 for (unsigned i
= 0; i
< count
; ++i
) {
422 struct radv_amdgpu_cs
*cs
= (struct radv_amdgpu_cs
*)cs_array
[i
];
423 total_buffer_count
+= cs
->num_buffers
;
426 amdgpu_bo_handle
*handles
= malloc(sizeof(amdgpu_bo_handle
) * total_buffer_count
);
427 uint8_t *priorities
= malloc(sizeof(uint8_t) * total_buffer_count
);
428 if (!handles
|| !priorities
) {
435 handles
[0] = extra_bo
->bo
;
439 for (unsigned i
= 0; i
< count
; ++i
) {
440 struct radv_amdgpu_cs
*cs
= (struct radv_amdgpu_cs
*)cs_array
[i
];
441 for (unsigned j
= 0; j
< cs
->num_buffers
; ++j
) {
443 for (unsigned k
= 0; k
< unique_bo_count
; ++k
) {
444 if (handles
[k
] == cs
->handles
[j
]) {
446 priorities
[k
] = MAX2(priorities
[k
],
452 handles
[unique_bo_count
] = cs
->handles
[j
];
453 priorities
[unique_bo_count
] = cs
->priorities
[j
];
458 r
= amdgpu_bo_list_create(ws
->dev
, unique_bo_count
, handles
,
459 priorities
, bo_list
);
468 static int radv_amdgpu_winsys_cs_submit_chained(struct radeon_winsys_ctx
*_ctx
,
469 struct radeon_winsys_cs
**cs_array
,
471 struct radeon_winsys_fence
*_fence
)
474 struct radv_amdgpu_ctx
*ctx
= radv_amdgpu_ctx(_ctx
);
475 struct amdgpu_cs_fence
*fence
= (struct amdgpu_cs_fence
*)_fence
;
476 struct radv_amdgpu_cs
*cs0
= radv_amdgpu_cs(cs_array
[0]);
477 amdgpu_bo_list_handle bo_list
;
478 struct amdgpu_cs_request request
= {0};
480 for (unsigned i
= cs_count
; i
--;) {
481 struct radv_amdgpu_cs
*cs
= radv_amdgpu_cs(cs_array
[i
]);
483 if (cs
->is_chained
) {
484 *cs
->ib_size_ptr
-= 4;
485 cs
->is_chained
= false;
488 if (i
+ 1 < cs_count
) {
489 struct radv_amdgpu_cs
*next
= radv_amdgpu_cs(cs_array
[i
+ 1]);
490 assert(cs
->base
.cdw
+ 4 <= cs
->base
.max_dw
);
492 cs
->is_chained
= true;
493 *cs
->ib_size_ptr
+= 4;
495 cs
->base
.buf
[cs
->base
.cdw
+ 0] = PKT3(PKT3_INDIRECT_BUFFER_CIK
, 2, 0);
496 cs
->base
.buf
[cs
->base
.cdw
+ 1] = next
->ib
.ib_mc_address
;
497 cs
->base
.buf
[cs
->base
.cdw
+ 2] = next
->ib
.ib_mc_address
>> 32;
498 cs
->base
.buf
[cs
->base
.cdw
+ 3] = S_3F2_CHAIN(1) | S_3F2_VALID(1) | next
->ib
.size
;
502 r
= radv_amdgpu_create_bo_list(cs0
->ws
, cs_array
, cs_count
, NULL
, &bo_list
);
504 fprintf(stderr
, "amdgpu: Failed to created the BO list for submission\n");
508 request
.ip_type
= AMDGPU_HW_IP_GFX
;
509 request
.number_of_ibs
= 1;
510 request
.ibs
= &cs0
->ib
;
511 request
.resources
= bo_list
;
513 r
= amdgpu_cs_submit(ctx
->ctx
, 0, &request
, 1);
516 fprintf(stderr
, "amdgpu: Not enough memory for command submission.\n");
518 fprintf(stderr
, "amdgpu: The CS has been rejected, "
519 "see dmesg for more information.\n");
522 amdgpu_bo_list_destroy(bo_list
);
525 fence
->context
= ctx
->ctx
;
526 fence
->ip_type
= request
.ip_type
;
527 fence
->ip_instance
= request
.ip_instance
;
528 fence
->ring
= request
.ring
;
529 fence
->fence
= request
.seq_no
;
531 ctx
->last_seq_no
= request
.seq_no
;
536 static int radv_amdgpu_winsys_cs_submit_fallback(struct radeon_winsys_ctx
*_ctx
,
537 struct radeon_winsys_cs
**cs_array
,
539 struct radeon_winsys_fence
*_fence
)
542 struct radv_amdgpu_ctx
*ctx
= radv_amdgpu_ctx(_ctx
);
543 struct amdgpu_cs_fence
*fence
= (struct amdgpu_cs_fence
*)_fence
;
544 amdgpu_bo_list_handle bo_list
;
545 struct amdgpu_cs_request request
;
549 for (unsigned i
= 0; i
< cs_count
;) {
550 struct radv_amdgpu_cs
*cs0
= radv_amdgpu_cs(cs_array
[i
]);
551 struct amdgpu_cs_ib_info ibs
[AMDGPU_CS_MAX_IBS_PER_SUBMIT
];
552 unsigned cnt
= MIN2(AMDGPU_CS_MAX_IBS_PER_SUBMIT
, cs_count
- i
);
554 memset(&request
, 0, sizeof(request
));
556 r
= radv_amdgpu_create_bo_list(cs0
->ws
, &cs_array
[i
], cnt
, NULL
, &bo_list
);
558 fprintf(stderr
, "amdgpu: Failed to created the BO list for submission\n");
562 request
.ip_type
= AMDGPU_HW_IP_GFX
;
563 request
.resources
= bo_list
;
564 request
.number_of_ibs
= cnt
;
567 for (unsigned j
= 0; j
< cnt
; ++j
) {
568 struct radv_amdgpu_cs
*cs
= radv_amdgpu_cs(cs_array
[i
+ j
]);
571 if (cs
->is_chained
) {
572 *cs
->ib_size_ptr
-= 4;
573 cs
->is_chained
= false;
577 r
= amdgpu_cs_submit(ctx
->ctx
, 0, &request
, 1);
580 fprintf(stderr
, "amdgpu: Not enough memory for command submission.\n");
582 fprintf(stderr
, "amdgpu: The CS has been rejected, "
583 "see dmesg for more information.\n");
586 amdgpu_bo_list_destroy(bo_list
);
594 fence
->context
= ctx
->ctx
;
595 fence
->ip_type
= request
.ip_type
;
596 fence
->ip_instance
= request
.ip_instance
;
597 fence
->ring
= request
.ring
;
598 fence
->fence
= request
.seq_no
;
600 ctx
->last_seq_no
= request
.seq_no
;
605 static int radv_amdgpu_winsys_cs_submit_sysmem(struct radeon_winsys_ctx
*_ctx
,
606 struct radeon_winsys_cs
**cs_array
,
608 struct radeon_winsys_fence
*_fence
)
611 struct radv_amdgpu_ctx
*ctx
= radv_amdgpu_ctx(_ctx
);
612 struct amdgpu_cs_fence
*fence
= (struct amdgpu_cs_fence
*)_fence
;
613 struct radv_amdgpu_cs
*cs0
= radv_amdgpu_cs(cs_array
[0]);
614 struct radeon_winsys
*ws
= (struct radeon_winsys
*)cs0
->ws
;
615 amdgpu_bo_list_handle bo_list
;
616 struct amdgpu_cs_request request
;
617 uint32_t pad_word
= 0xffff1000U
;
619 if (radv_amdgpu_winsys(ws
)->family
== FAMILY_SI
)
620 pad_word
= 0x80000000;
624 for (unsigned i
= 0; i
< cs_count
;) {
625 struct amdgpu_cs_ib_info ib
= {0};
626 struct radeon_winsys_bo
*bo
= NULL
;
631 while (i
+ cnt
< cs_count
&& 0xffff8 - size
>= radv_amdgpu_cs(cs_array
[i
+ cnt
])->base
.cdw
) {
632 size
+= radv_amdgpu_cs(cs_array
[i
+ cnt
])->base
.cdw
;
638 bo
= ws
->buffer_create(ws
, 4 * size
, 4096, RADEON_DOMAIN_GTT
, RADEON_FLAG_CPU_ACCESS
);
639 ptr
= ws
->buffer_map(bo
);
641 for (unsigned j
= 0; j
< cnt
; ++j
) {
642 struct radv_amdgpu_cs
*cs
= radv_amdgpu_cs(cs_array
[i
+ j
]);
643 memcpy(ptr
, cs
->base
.buf
, 4 * cs
->base
.cdw
);
648 while(!size
|| (size
& 7)) {
653 memset(&request
, 0, sizeof(request
));
656 r
= radv_amdgpu_create_bo_list(cs0
->ws
, &cs_array
[i
], cnt
,
657 (struct radv_amdgpu_winsys_bo
*)bo
, &bo_list
);
659 fprintf(stderr
, "amdgpu: Failed to created the BO list for submission\n");
664 ib
.ib_mc_address
= ws
->buffer_get_va(bo
);
666 request
.ip_type
= AMDGPU_HW_IP_GFX
;
667 request
.resources
= bo_list
;
668 request
.number_of_ibs
= 1;
671 r
= amdgpu_cs_submit(ctx
->ctx
, 0, &request
, 1);
674 fprintf(stderr
, "amdgpu: Not enough memory for command submission.\n");
676 fprintf(stderr
, "amdgpu: The CS has been rejected, "
677 "see dmesg for more information.\n");
680 amdgpu_bo_list_destroy(bo_list
);
682 ws
->buffer_destroy(bo
);
689 fence
->context
= ctx
->ctx
;
690 fence
->ip_type
= request
.ip_type
;
691 fence
->ip_instance
= request
.ip_instance
;
692 fence
->ring
= request
.ring
;
693 fence
->fence
= request
.seq_no
;
695 ctx
->last_seq_no
= request
.seq_no
;
700 static int radv_amdgpu_winsys_cs_submit(struct radeon_winsys_ctx
*_ctx
,
701 struct radeon_winsys_cs
**cs_array
,
704 struct radeon_winsys_fence
*_fence
)
706 struct radv_amdgpu_cs
*cs
= radv_amdgpu_cs(cs_array
[0]);
707 if (!cs
->ws
->use_ib_bos
) {
708 return radv_amdgpu_winsys_cs_submit_sysmem(_ctx
, cs_array
,
710 } else if (can_patch
&& cs_count
> AMDGPU_CS_MAX_IBS_PER_SUBMIT
&& false) {
711 return radv_amdgpu_winsys_cs_submit_chained(_ctx
, cs_array
,
714 return radv_amdgpu_winsys_cs_submit_fallback(_ctx
, cs_array
,
719 static struct radeon_winsys_ctx
*radv_amdgpu_ctx_create(struct radeon_winsys
*_ws
)
721 struct radv_amdgpu_winsys
*ws
= radv_amdgpu_winsys(_ws
);
722 struct radv_amdgpu_ctx
*ctx
= CALLOC_STRUCT(radv_amdgpu_ctx
);
727 r
= amdgpu_cs_ctx_create(ws
->dev
, &ctx
->ctx
);
729 fprintf(stderr
, "amdgpu: radv_amdgpu_cs_ctx_create failed. (%i)\n", r
);
733 return (struct radeon_winsys_ctx
*)ctx
;
738 static void radv_amdgpu_ctx_destroy(struct radeon_winsys_ctx
*rwctx
)
740 struct radv_amdgpu_ctx
*ctx
= (struct radv_amdgpu_ctx
*)rwctx
;
741 amdgpu_cs_ctx_free(ctx
->ctx
);
745 static bool radv_amdgpu_ctx_wait_idle(struct radeon_winsys_ctx
*rwctx
)
747 struct radv_amdgpu_ctx
*ctx
= (struct radv_amdgpu_ctx
*)rwctx
;
749 if (ctx
->last_seq_no
) {
751 struct amdgpu_cs_fence fence
;
753 fence
.context
= ctx
->ctx
;
754 fence
.ip_type
= RING_GFX
;
755 fence
.ip_instance
= 0;
757 fence
.fence
= ctx
->last_seq_no
;
759 int ret
= amdgpu_cs_query_fence_status(&fence
, 1000000000ull, 0,
769 void radv_amdgpu_cs_init_functions(struct radv_amdgpu_winsys
*ws
)
771 ws
->base
.ctx_create
= radv_amdgpu_ctx_create
;
772 ws
->base
.ctx_destroy
= radv_amdgpu_ctx_destroy
;
773 ws
->base
.ctx_wait_idle
= radv_amdgpu_ctx_wait_idle
;
774 ws
->base
.cs_create
= radv_amdgpu_cs_create
;
775 ws
->base
.cs_destroy
= radv_amdgpu_cs_destroy
;
776 ws
->base
.cs_grow
= radv_amdgpu_cs_grow
;
777 ws
->base
.cs_finalize
= radv_amdgpu_cs_finalize
;
778 ws
->base
.cs_reset
= radv_amdgpu_cs_reset
;
779 ws
->base
.cs_add_buffer
= radv_amdgpu_cs_add_buffer
;
780 ws
->base
.cs_execute_secondary
= radv_amdgpu_cs_execute_secondary
;
781 ws
->base
.cs_submit
= radv_amdgpu_winsys_cs_submit
;
782 ws
->base
.create_fence
= radv_amdgpu_create_fence
;
783 ws
->base
.destroy_fence
= radv_amdgpu_destroy_fence
;
784 ws
->base
.fence_wait
= radv_amdgpu_fence_wait
;