nvk/mme: Add a unit test framework for driver macros

Also add tests for NVK_MME_CLEAR to demonstrate the framework.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30703>
This commit is contained in:
Faith Ekstrand 2024-08-16 17:07:57 -05:00 committed by Marge Bot
parent 03f785083f
commit 7d6cc15ab8
4 changed files with 137 additions and 5 deletions

View file

@ -55,6 +55,34 @@ nvk_mme_clear(struct mme_builder *b)
mme_free_reg(b, view_mask);
}
const struct nvk_mme_test_case nvk_mme_clear_tests[] = {{
.init = (struct nvk_mme_mthd_data[]) {
{ NVK_SET_MME_SCRATCH(VIEW_MASK), 0 },
{ }
},
.params = (uint32_t[]) { 0x3c, 5 },
.expected = (struct nvk_mme_mthd_data[]) {
{ NV9097_CLEAR_SURFACE, 0x003c },
{ NV9097_CLEAR_SURFACE, 0x043c },
{ NV9097_CLEAR_SURFACE, 0x083c },
{ NV9097_CLEAR_SURFACE, 0x0c3c },
{ NV9097_CLEAR_SURFACE, 0x103c },
{ }
},
}, {
.init = (struct nvk_mme_mthd_data[]) {
{ NVK_SET_MME_SCRATCH(VIEW_MASK), 0xb },
{ }
},
.params = (uint32_t[]) { 0x3c },
.expected = (struct nvk_mme_mthd_data[]) {
{ NV9097_CLEAR_SURFACE, 0x03c },
{ NV9097_CLEAR_SURFACE, 0x43c },
{ NV9097_CLEAR_SURFACE, 0xc3c },
{ }
},
}, {}};
static void
emit_clear_rects(struct nvk_cmd_buffer *cmd,
int color_att,

View file

@ -6,6 +6,8 @@
#include "nvk_private.h"
#include "mme_sim.h"
static const nvk_mme_builder_func mme_builders[NVK_MME_COUNT] = {
[NVK_MME_SELECT_CB0] = nvk_mme_select_cb0,
[NVK_MME_BIND_CBUF_DESC] = nvk_mme_bind_cbuf_desc,
@ -28,6 +30,10 @@ static const nvk_mme_builder_func mme_builders[NVK_MME_COUNT] = {
[NVK_MME_SET_Z_CLAMP] = nvk_mme_set_z_clamp,
};
static const struct nvk_mme_test_case *mme_tests[NVK_MME_COUNT] = {
[NVK_MME_CLEAR] = nvk_mme_clear_tests,
};
uint32_t *
nvk_build_mme(const struct nv_device_info *devinfo,
enum nvk_mme mme, size_t *size_out)
@ -40,13 +46,93 @@ nvk_build_mme(const struct nv_device_info *devinfo,
return mme_builder_finish(&b, size_out);
}
struct nvk_mme_test_state {
const struct nvk_mme_test_case *test;
struct nvk_mme_mthd_data results[32];
uint32_t pi, ei;
};
static uint32_t
nvk_mme_test_state_load(void *_ts)
{
struct nvk_mme_test_state *ts = _ts;
return ts->test->params[ts->pi++];
}
static uint32_t
nvk_mme_test_state_state(void *_ts, uint16_t addr)
{
struct nvk_mme_test_state *ts = _ts;
/* First, look backwards through the expected data that we've already
* written. This ensures that mthd() impacts state().
*/
for (int32_t i = ts->ei - 1; i >= 0; i--) {
if (ts->test->expected[i].mthd == addr)
return ts->test->expected[i].data;
}
/* Now look at init. We assume the init data is unique */
assert(ts->test->init != NULL && "Read uninitialized state");
for (uint32_t i = 0;; i++) {
if (ts->test->init[i].mthd == 0)
unreachable("Read uninitialized state");
if (ts->test->init[i].mthd == addr)
return ts->test->init[i].data;
}
}
static void
nvk_mme_test_state_mthd(void *_ts, uint16_t addr, uint32_t data)
{
struct nvk_mme_test_state *ts = _ts;
assert(ts->ei < ARRAY_SIZE(ts->results));
ts->results[ts->ei] = (struct nvk_mme_mthd_data) {
.mthd = addr,
.data = data,
};
if (ts->test->expected != NULL) {
assert(ts->test->expected[ts->ei].mthd != 0);
assert(ts->test->expected[ts->ei].mthd == addr);
assert(ts->test->expected[ts->ei].data == data);
}
ts->ei++;
}
const struct mme_sim_state_ops nvk_mme_test_state_ops = {
.load = nvk_mme_test_state_load,
.state = nvk_mme_test_state_state,
.mthd = nvk_mme_test_state_mthd,
};
void
nvk_test_build_all_mmes(const struct nv_device_info *devinfo)
nvk_test_all_mmes(const struct nv_device_info *devinfo)
{
for (uint32_t mme = 0; mme < NVK_MME_COUNT; mme++) {
size_t size;
uint32_t *dw = nvk_build_mme(devinfo, mme, &size);
assert(dw != NULL);
if (mme_tests[mme] != NULL) {
for (uint32_t i = 0;; i++) {
if (mme_tests[mme][i].params == NULL)
break;
struct nvk_mme_test_state ts = {
.test = &mme_tests[mme][i],
};
mme_sim_core(devinfo, size, dw, &nvk_mme_test_state_ops, &ts);
if (ts.test->expected != NULL)
assert(ts.test->expected[ts.ei].mthd == 0);
if (ts.test->check != NULL)
ts.test->check(devinfo, ts.test, ts.results);
}
}
free(dw);
}
}

View file

@ -137,8 +137,6 @@ typedef void (*nvk_mme_builder_func)(struct mme_builder *b);
uint32_t *nvk_build_mme(const struct nv_device_info *devinfo,
enum nvk_mme mme, size_t *size_out);
void nvk_test_build_all_mmes(const struct nv_device_info *devinfo);
void nvk_mme_select_cb0(struct mme_builder *b);
void nvk_mme_bind_cbuf_desc(struct mme_builder *b);
void nvk_mme_clear(struct mme_builder *b);
@ -159,4 +157,24 @@ void nvk_mme_set_conservative_raster_state(struct mme_builder *b);
void nvk_mme_set_viewport_min_max_z(struct mme_builder *b);
void nvk_mme_set_z_clamp(struct mme_builder *b);
struct nvk_mme_mthd_data {
uint16_t mthd;
uint32_t data;
};
#define NVK_MME_MTHD_DATA_END ((struct nvk_mme_mthd_data) { 0, 0 })
struct nvk_mme_test_case {
const struct nvk_mme_mthd_data *init;
const uint32_t *params;
const struct nvk_mme_mthd_data *expected;
void (*check)(const struct nv_device_info *devinfo,
const struct nvk_mme_test_case *test,
const struct nvk_mme_mthd_data *results);
};
extern const struct nvk_mme_test_case nvk_mme_clear_tests[];
void nvk_test_all_mmes(const struct nv_device_info *devinfo);
#endif /* NVK_MME_H */

View file

@ -27,8 +27,8 @@ int main(int argc, char **argv)
};
// nvk_test_build_all_mmes(&kepler);
nvk_test_build_all_mmes(&volta);
nvk_test_build_all_mmes(&turing);
nvk_test_all_mmes(&volta);
nvk_test_all_mmes(&turing);
return 0;
}