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:
committed by
Marge Bot
parent
ccd670cc2f
commit
fb9524f5dd
@@ -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)
|
||||
|
||||
|
||||
@@ -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 */
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user