nouveau: Move nv_push and helpers to their own header

We put this in nvidia-headers to separate it from the pushbuf stuff.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
Faith Ekstrand
2023-01-30 20:11:58 -06:00
committed by Marge Bot
parent ccd670cc2f
commit fb9524f5dd
3 changed files with 236 additions and 224 deletions
+2 -2
View File
@@ -114,9 +114,9 @@ __${nvcl}_${mthd}(uint32_t *val_out, struct nv_${nvcl.lower()}_${mthd} st)
uint32_t nvk_p_ret; ${bs}
V_${nvcl}_${mthd}(nvk_p_ret, args); ${bs}
%if mthddict[mthd].is_array:
nvk_push_val(push, ${nvcl}_${mthd}(idx), nvk_p_ret); ${bs}
nv_push_val(push, ${nvcl}_${mthd}(idx), nvk_p_ret); ${bs}
%else:
nvk_push_val(push, ${nvcl}_${mthd}, nvk_p_ret); ${bs}
nv_push_val(push, ${nvcl}_${mthd}, nvk_p_ret); ${bs}
%endif
} while(0)
+233
View File
@@ -0,0 +1,233 @@
#ifndef NV_PUSH_H
#define NV_PUSH_H
#include "nvtypes.h"
#include "util/macros.h"
#include <assert.h>
#include <stddef.h>
#include <string.h>
struct nv_push {
uint32_t *start;
uint32_t *end;
uint32_t *limit;
uint32_t *last_size;
};
static inline void
nv_push_init(struct nv_push *push, uint32_t *start, size_t dw_count)
{
push->start = start;
push->end = start;
push->limit = start + dw_count;
push->last_size = NULL;
}
static inline size_t
nv_push_dw_count(struct nv_push *push)
{
assert(push->start <= push->end);
assert(push->end <= push->limit);
return push->end - push->start;
}
#define SUBC_NV9097 0
#define SUBC_NVA097 0
#define SUBC_NVB097 0
#define SUBC_NVB197 0
#define SUBC_NVC097 0
#define SUBC_NVC397 0
#define SUBC_NVC597 0
#define SUBC_NVA0C0 1
#define SUBC_NVC0C0 1
#define SUBC_NVC3C0 1
#define SUBC_NV902D 3
#define SUBC_NV90B5 4
#define SUBC_NVC1B5 4
static inline uint32_t
NVC0_FIFO_PKHDR_SQ(int subc, int mthd, unsigned size)
{
return 0x20000000 | (size << 16) | (subc << 13) | (mthd >> 2);
}
static inline void
__push_verify(struct nv_push *push)
{
if (!push->last_size)
return;
/* make sure we don't add a new method if the last one wasn't used */
uint32_t last_hdr = *push->last_size;
/* check for immd */
if (last_hdr >> 29 == 4)
return;
UNUSED uint32_t last_count = (last_hdr & 0x1fff0000);
assert(last_count);
}
static inline void
__push_mthd_size(struct nv_push *push, int subc, uint32_t mthd, unsigned size)
{
__push_verify(push);
push->last_size = push->end;
*push->end = NVC0_FIFO_PKHDR_SQ(subc, mthd, size);
push->end++;
}
static inline void
__push_mthd(struct nv_push *push, int subc, uint32_t mthd)
{
__push_mthd_size(push, subc, mthd, 0);
}
#define P_MTHD(push, class, mthd) __push_mthd(push, SUBC_##class, class##_##mthd)
static inline uint32_t
NVC0_FIFO_PKHDR_IL(int subc, int mthd, uint16_t data)
{
assert(!(data & ~0x1fff));
return 0x80000000 | (data << 16) | (subc << 13) | (mthd >> 2);
}
static inline void
__push_immd(struct nv_push *push, int subc, uint32_t mthd, uint32_t val)
{
__push_verify(push);
push->last_size = push->end;
*push->end = NVC0_FIFO_PKHDR_IL(subc, mthd, val);
push->end++;
}
#define P_IMMD(push, class, mthd, args...) do { \
uint32_t __val; \
VA_##class##_##mthd(__val, args); \
if (__builtin_constant_p(__val & ~0x1fff) && !(__val & ~0x1fff)) { \
__push_immd(push, SUBC_##class, class##_##mthd, __val); \
} else { \
__push_mthd_size(push, SUBC_##class, class##_##mthd, 0); \
nv_push_val(push, class##_##mthd, __val); \
} \
} while(0)
static inline uint32_t
NVC0_FIFO_PKHDR_1I(int subc, int mthd, unsigned size)
{
return 0xa0000000 | (size << 16) | (subc << 13) | (mthd >> 2);
}
static inline void
__push_1inc(struct nv_push *push, int subc, uint32_t mthd)
{
__push_verify(push);
push->last_size = push->end;
*push->end = NVC0_FIFO_PKHDR_1I(subc, mthd, 0);
push->end++;
}
#define P_1INC(push, class, mthd) __push_1inc(push, SUBC_##class, class##_##mthd)
static inline uint32_t
NVC0_FIFO_PKHDR_0I(int subc, int mthd, unsigned size)
{
return 0x60000000 | (size << 16) | (subc << 13) | (mthd >> 2);
}
static inline void
__push_0inc(struct nv_push *push, int subc, uint32_t mthd)
{
__push_verify(push);
push->last_size = push->end;
*push->end = NVC0_FIFO_PKHDR_0I(subc, mthd, 0);
push->end++;
}
#define P_0INC(push, class, mthd) __push_0inc(push, SUBC_##class, class##_##mthd)
static inline bool
nv_push_update_count(struct nv_push *push, uint16_t count)
{
uint32_t last_hdr_val = *push->last_size;
assert(count <= 0x1fff);
if (count > 0x1fff)
return false;
/* size is encoded at 28:16 */
uint32_t new_count = (count + (last_hdr_val >> 16)) & 0x1fff;
bool overflow = new_count < count;
/* if we would overflow, don't change anything and just let it be */
assert(!overflow);
if (overflow)
return false;
last_hdr_val &= ~0x1fff0000;
last_hdr_val |= new_count << 16;
*push->last_size = last_hdr_val;
return true;
}
static inline void
P_INLINE_DATA(struct nv_push *push, uint32_t value)
{
if (nv_push_update_count(push, 1)) {
/* push new value */
*push->end = value;
push->end++;
}
}
static inline void
P_INLINE_FLOAT(struct nv_push *push, float value)
{
if (nv_push_update_count(push, 1)) {
/* push new value */
*(float *)push->end = value;
push->end++;
}
}
static inline void
P_INLINE_ARRAY(struct nv_push *push, const uint32_t *data, int num_dw)
{
if (nv_push_update_count(push, num_dw)) {
/* push new value */
memcpy(push->end, data, num_dw * 4);
push->end += num_dw;
}
}
/* internally used by generated inlines. */
static inline void
nv_push_val(struct nv_push *push, uint32_t idx, uint32_t val)
{
UNUSED uint32_t last_hdr_val = *push->last_size;
UNUSED bool is_0inc = (last_hdr_val & 0xe0000000) == 0x60000000;
UNUSED bool is_1inc = (last_hdr_val & 0xe0000000) == 0xa0000000;
UNUSED bool is_immd = (last_hdr_val & 0xe0000000) == 0x80000000;
UNUSED uint16_t last_method = (last_hdr_val & 0x1fff) << 2;
uint16_t distance = push->end - push->last_size - 1;
if (is_0inc)
distance = 0;
else if (is_1inc)
distance = MIN2(1, distance);
last_method += distance * 4;
/* can't have empty headers ever */
assert(last_hdr_val);
assert(!is_immd);
assert(last_method == idx);
assert(push->end < push->limit);
P_INLINE_DATA(push, val);
}
#endif /* NV_PUSH_H */
+1 -222
View File
@@ -4,6 +4,7 @@
#include "nouveau_private.h"
#include "nouveau_bo.h"
#include "nv_push.h"
#include "util/u_dynarray.h"
#ifdef __cplusplus
@@ -18,30 +19,6 @@ struct nouveau_ws_push_bo {
enum nouveau_ws_bo_map_flags flags;
};
struct nv_push {
uint32_t *start;
uint32_t *end;
uint32_t *limit;
uint32_t *last_size;
};
static inline void
nv_push_init(struct nv_push *push, uint32_t *start, size_t dw_count)
{
push->start = start;
push->end = start;
push->limit = start + dw_count;
push->last_size = NULL;
}
static inline size_t
nv_push_dw_count(struct nv_push *push)
{
assert(push->start <= push->end);
assert(push->end <= push->limit);
return push->end - push->start;
}
struct nouveau_ws_push_buffer {
struct nouveau_ws_bo *bo;
struct nv_push push;
@@ -78,204 +55,6 @@ _nouveau_ws_push_top(const struct nouveau_ws_push *push)
return util_dynarray_top_ptr(&push->pushs, struct nouveau_ws_push_buffer);
}
#define SUBC_NV9097 0
#define SUBC_NVA097 0
#define SUBC_NVB097 0
#define SUBC_NVB197 0
#define SUBC_NVC097 0
#define SUBC_NVC397 0
#define SUBC_NVC597 0
#define SUBC_NVA0C0 1
#define SUBC_NVC0C0 1
#define SUBC_NVC3C0 1
#define SUBC_NV902D 3
#define SUBC_NV90B5 4
#define SUBC_NVC1B5 4
static inline uint32_t
NVC0_FIFO_PKHDR_SQ(int subc, int mthd, unsigned size)
{
return 0x20000000 | (size << 16) | (subc << 13) | (mthd >> 2);
}
static inline void
__push_verify(struct nv_push *push)
{
if (!push->last_size)
return;
/* make sure we don't add a new method if the last one wasn't used */
uint32_t last_hdr = *push->last_size;
/* check for immd */
if (last_hdr >> 29 == 4)
return;
UNUSED uint32_t last_count = (last_hdr & 0x1fff0000);
assert(last_count);
}
static inline void
__push_mthd_size(struct nv_push *push, int subc, uint32_t mthd, unsigned size)
{
__push_verify(push);
push->last_size = push->end;
*push->end = NVC0_FIFO_PKHDR_SQ(subc, mthd, size);
push->end++;
}
static inline void
__push_mthd(struct nv_push *push, int subc, uint32_t mthd)
{
__push_mthd_size(push, subc, mthd, 0);
}
#define P_MTHD(push, class, mthd) __push_mthd(push, SUBC_##class, class##_##mthd)
static inline uint32_t
NVC0_FIFO_PKHDR_IL(int subc, int mthd, uint16_t data)
{
assert(!(data & ~0x1fff));
return 0x80000000 | (data << 16) | (subc << 13) | (mthd >> 2);
}
static inline void
__push_immd(struct nv_push *push, int subc, uint32_t mthd, uint32_t val)
{
__push_verify(push);
push->last_size = push->end;
*push->end = NVC0_FIFO_PKHDR_IL(subc, mthd, val);
push->end++;
}
#define P_IMMD(push, class, mthd, args...) do { \
uint32_t __val; \
VA_##class##_##mthd(__val, args); \
if (__builtin_constant_p(__val & ~0x1fff) && !(__val & ~0x1fff)) { \
__push_immd(push, SUBC_##class, class##_##mthd, __val); \
} else { \
__push_mthd_size(push, SUBC_##class, class##_##mthd, 0); \
nvk_push_val(push, class##_##mthd, __val); \
} \
} while(0)
static inline uint32_t
NVC0_FIFO_PKHDR_1I(int subc, int mthd, unsigned size)
{
return 0xa0000000 | (size << 16) | (subc << 13) | (mthd >> 2);
}
static inline void
__push_1inc(struct nv_push *push, int subc, uint32_t mthd)
{
__push_verify(push);
push->last_size = push->end;
*push->end = NVC0_FIFO_PKHDR_1I(subc, mthd, 0);
push->end++;
}
#define P_1INC(push, class, mthd) __push_1inc(push, SUBC_##class, class##_##mthd)
static inline uint32_t
NVC0_FIFO_PKHDR_0I(int subc, int mthd, unsigned size)
{
return 0x60000000 | (size << 16) | (subc << 13) | (mthd >> 2);
}
static inline void
__push_0inc(struct nv_push *push, int subc, uint32_t mthd)
{
__push_verify(push);
push->last_size = push->end;
*push->end = NVC0_FIFO_PKHDR_0I(subc, mthd, 0);
push->end++;
}
#define P_0INC(push, class, mthd) __push_0inc(push, SUBC_##class, class##_##mthd)
static inline bool
nvk_push_update_count(struct nv_push *push, uint16_t count)
{
uint32_t last_hdr_val = *push->last_size;
assert(count <= 0x1fff);
if (count > 0x1fff)
return false;
/* size is encoded at 28:16 */
uint32_t new_count = (count + (last_hdr_val >> 16)) & 0x1fff;
bool overflow = new_count < count;
/* if we would overflow, don't change anything and just let it be */
assert(!overflow);
if (overflow)
return false;
last_hdr_val &= ~0x1fff0000;
last_hdr_val |= new_count << 16;
*push->last_size = last_hdr_val;
return true;
}
static inline void
P_INLINE_DATA(struct nv_push *push, uint32_t value)
{
if (nvk_push_update_count(push, 1)) {
/* push new value */
*push->end = value;
push->end++;
}
}
static inline void
P_INLINE_FLOAT(struct nv_push *push, float value)
{
if (nvk_push_update_count(push, 1)) {
/* push new value */
*(float *)push->end = value;
push->end++;
}
}
static inline void
P_INLINE_ARRAY(struct nv_push *push, const uint32_t *data, int num_dw)
{
if (nvk_push_update_count(push, num_dw)) {
/* push new value */
memcpy(push->end, data, num_dw * 4);
push->end += num_dw;
}
}
/* internally used by generated inlines. */
static inline void
nvk_push_val(struct nv_push *push, uint32_t idx, uint32_t val)
{
UNUSED uint32_t last_hdr_val = *push->last_size;
UNUSED bool is_0inc = (last_hdr_val & 0xe0000000) == 0x60000000;
UNUSED bool is_1inc = (last_hdr_val & 0xe0000000) == 0xa0000000;
UNUSED bool is_immd = (last_hdr_val & 0xe0000000) == 0x80000000;
UNUSED uint16_t last_method = (last_hdr_val & 0x1fff) << 2;
uint16_t distance = push->end - push->last_size - 1;
if (is_0inc)
distance = 0;
else if (is_1inc)
distance = MIN2(1, distance);
last_method += distance * 4;
/* can't have empty headers ever */
assert(last_hdr_val);
assert(!is_immd);
assert(last_method == idx);
assert(push->end < push->limit);
P_INLINE_DATA(push, val);
}
static inline struct nv_push *
P_SPACE(struct nouveau_ws_push *push, uint32_t size)
{