From 7d6cc15ab81178be7660a27b26626734773c267f Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Fri, 16 Aug 2024 17:07:57 -0500 Subject: [PATCH] nvk/mme: Add a unit test framework for driver macros Also add tests for NVK_MME_CLEAR to demonstrate the framework. Part-of: --- src/nouveau/vulkan/nvk_cmd_clear.c | 28 ++++++++++ src/nouveau/vulkan/nvk_mme.c | 88 +++++++++++++++++++++++++++++- src/nouveau/vulkan/nvk_mme.h | 22 +++++++- src/nouveau/vulkan/test_nvk_mme.c | 4 +- 4 files changed, 137 insertions(+), 5 deletions(-) diff --git a/src/nouveau/vulkan/nvk_cmd_clear.c b/src/nouveau/vulkan/nvk_cmd_clear.c index 185de4ebead..110c8bdd194 100644 --- a/src/nouveau/vulkan/nvk_cmd_clear.c +++ b/src/nouveau/vulkan/nvk_cmd_clear.c @@ -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, diff --git a/src/nouveau/vulkan/nvk_mme.c b/src/nouveau/vulkan/nvk_mme.c index 79fb80477a3..7f0d4625ad9 100644 --- a/src/nouveau/vulkan/nvk_mme.c +++ b/src/nouveau/vulkan/nvk_mme.c @@ -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); } } diff --git a/src/nouveau/vulkan/nvk_mme.h b/src/nouveau/vulkan/nvk_mme.h index 7db94418255..0012d9ef052 100644 --- a/src/nouveau/vulkan/nvk_mme.h +++ b/src/nouveau/vulkan/nvk_mme.h @@ -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 */ diff --git a/src/nouveau/vulkan/test_nvk_mme.c b/src/nouveau/vulkan/test_nvk_mme.c index e67df066612..e0395c772ef 100644 --- a/src/nouveau/vulkan/test_nvk_mme.c +++ b/src/nouveau/vulkan/test_nvk_mme.c @@ -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; }