Download tests/cpp/test_render_graph.cpp from kimjunhan/vkgs-sim: direct link, hf CLI and curl.
- Browser
- Download file 9.8 kB
-
https://huggingface.co/kimjunhan/vkgs-sim/resolve/main/tests/cpp/test_render_graph.cpp
- Command line
-
hf download hf://kimjunhan/vkgs-sim/tests/cpp/test_render_graph.cpp
-
curl -L -o test_render_graph.cpp https://huggingface.co/kimjunhan/vkgs-sim/resolve/main/tests/cpp/test_render_graph.cpp
9.8 kB
| // src/vkgs/src/render_graph.cpp ์ํ โ GPU ์์ด. vkCmdPipelineBarrier ๋ฅผ ๊ฐ์ง๋ก ์ ์ํด ๊ทธ๋ํ๊ฐ ๋ฃ๋ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๊ธฐ๋กํ๋ค. | |
| struct Rec { | |
| VkPipelineStageFlags src, dst; | |
| bool image; | |
| VkImageLayout old_layout, new_layout; | |
| }; | |
| static std::vector<Rec> g_barriers; | |
| extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier(VkCommandBuffer, VkPipelineStageFlags src, | |
| VkPipelineStageFlags dst, VkDependencyFlags, uint32_t, | |
| const VkMemoryBarrier*, uint32_t, const VkBufferMemoryBarrier*, | |
| uint32_t n_img, const VkImageMemoryBarrier* img) { | |
| g_barriers.push_back({src, dst, n_img > 0, n_img ? img->oldLayout : VK_IMAGE_LAYOUT_UNDEFINED, | |
| n_img ? img->newLayout : VK_IMAGE_LAYOUT_UNDEFINED}); | |
| } | |
| static int fails = 0; | |
| using nlohmann::json; | |
| static std::vector<std::string> order_names(vkgs::RenderGraph& g) { | |
| std::vector<std::string> o; | |
| for (int i : g.order()) o.push_back(g.passes()[i].name); | |
| return o; | |
| } | |
| int main(int argc, char** argv) { | |
| // 1) ์คํ ์์ = ์ ์ธ ์์ (๊ณ์ฝ โ render_graph.hpp). ์ ์ธ ์์๊ฐ ์ ๊ทผ ์์๋ฅผ ์ ์ํ๋ค | |
| json j = json::parse(R"({ | |
| "resources": {"a": {"type": "buffer"}, "img": {"type": "image"}}, | |
| "passes": [ | |
| {"name": "consume", "kind": "x", "uses": [["a", "storage_read"], ["img", "storage_write"]]}, | |
| {"name": "produce", "kind": "x", "uses": [["a", "storage_write"]]}, | |
| {"name": "present", "kind": "none", "uses": [["img", "transfer_src"]]} | |
| ]})"); | |
| vkgs::RenderGraph g; | |
| g.load(j); | |
| auto o = order_names(g); | |
| CHECK((o == std::vector<std::string>{"consume", "produce", "present"})); | |
| // 2) ๋ ๋ฆฝ ํจ์ค๊ฐ ์์ฌ ์์ด๋ ์ ์ธ ์์ | |
| json j2 = json::parse(R"({ | |
| "resources": {"a": {"type": "buffer"}, "b": {"type": "buffer"}}, | |
| "passes": [ | |
| {"name": "wa", "kind": "x", "uses": [["a", "storage_write"]]}, | |
| {"name": "wb", "kind": "x", "uses": [["b", "storage_write"]]}, | |
| {"name": "ra", "kind": "x", "uses": [["a", "storage_read"]]}, | |
| {"name": "rb", "kind": "x", "uses": [["b", "storage_read"]]} | |
| ]})"); | |
| g.load(j2); | |
| o = order_names(g); | |
| CHECK((o == std::vector<std::string>{"wa", "wb", "ra", "rb"})); | |
| // 3) ๋ชจ๋ฅด๋ ๋ฆฌ์์คยท์ฌ์ฉ ๋ฐฉ์์ ๋ก๋ ๋ ๊ฑฐ๋ถ | |
| bool threw = false; | |
| try { | |
| g.load(json::parse(R"({"resources": {}, "passes": [{"name": "p", "kind": "x", "uses": [["nope", "storage_read"]]}]})")); | |
| } catch (const std::exception&) { threw = true; } | |
| CHECK(threw); | |
| threw = false; | |
| try { | |
| g.load(json::parse(R"({"resources": {"a": {}}, "passes": [{"name": "p", "kind": "x", "uses": [["a", "sideways"]]}]})")); | |
| } catch (const std::exception&) { threw = true; } | |
| CHECK(threw); | |
| // 4) ๋ฐฐ๋ฆฌ์ด: ์ฐ๊ธฐ โ ๊ฐ์ ๋จ๊ณ ์ฝ๊ธฐ ํ ๋ฒ, ๋ ๋ฒ์งธ ์ฝ๊ธฐ๋ ๋ฐฐ๋ฆฌ์ด ์์, ์ด๋ฏธ์ง ๋ ์ด์์ ์ ํ | |
| g.load(j2); | |
| g.begin_frame(); | |
| g_barriers.clear(); | |
| g.traverse(VK_NULL_HANDLE, [](vkgs::RGPass&) {}); | |
| // wa, wb: ์ฒ์ ์ฐ๊ธฐ โ ์์ ์ ๊ทผ์ด ์์ด ๋ฐฐ๋ฆฌ์ด ์์. ra, rb: RAW ๊ฐ 1๊ฐ | |
| CHECK(g_barriers.size() == 2); | |
| for (const auto& b : g_barriers) CHECK(b.src == VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT && !b.image); | |
| json j3 = json::parse(R"({ | |
| "resources": {"img": {"type": "image"}}, | |
| "passes": [ | |
| {"name": "w", "kind": "x", "uses": [["img", "storage_write"]]}, | |
| {"name": "r1", "kind": "x", "uses": [["img", "storage_read"]]}, | |
| {"name": "r2", "kind": "x", "uses": [["img", "storage_read"]]}, | |
| {"name": "copy", "kind": "x", "uses": [["img", "transfer_src"]]} | |
| ]})"); | |
| g.load(j3); | |
| g.bind_image("img", reinterpret_cast<VkImage>(uintptr_t(1))); | |
| g.begin_frame(); | |
| g_barriers.clear(); | |
| g.traverse(VK_NULL_HANDLE, [](vkgs::RGPass&) {}); | |
| // w: UNDEFINED โ GENERAL, r1: RAW, r2: ์์ (์ด๋ฏธ ๋ณด์), copy: RAW + GENERAL โ TRANSFER_SRC | |
| CHECK(g_barriers.size() == 3); | |
| if (g_barriers.size() == 3) { | |
| CHECK(g_barriers[0].old_layout == VK_IMAGE_LAYOUT_UNDEFINED && g_barriers[0].new_layout == VK_IMAGE_LAYOUT_GENERAL); | |
| CHECK(g_barriers[1].src == VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); | |
| CHECK(g_barriers[2].dst == VK_PIPELINE_STAGE_TRANSFER_BIT && | |
| g_barriers[2].new_layout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); | |
| } | |
| // 4b) ๊ฐ์ ๋จ๊ณ์์ ์ด๋ฏธ ๋ณด์ด๋ ์ฐ๊ธฐ๋ผ๋ ๋ ์ด์์์ด ๋ฐ๋๋ฉด ๊ทธ ์ฐ๊ธฐ์ ๋๊ธฐํํ๋ค (์ ํ = ์ฐ๊ธฐ) | |
| json j4 = json::parse(R"({ | |
| "resources": {"img": {"type": "image"}}, | |
| "passes": [ | |
| {"name": "copy_in", "kind": "x", "uses": [["img", "transfer_dst"]]}, | |
| {"name": "copy_out", "kind": "x", "uses": [["img", "transfer_src"]]} | |
| ]})"); | |
| g.load(j4); | |
| g.bind_image("img", reinterpret_cast<VkImage>(uintptr_t(1))); | |
| g.begin_frame(); | |
| g_barriers.clear(); | |
| g.traverse(VK_NULL_HANDLE, [](vkgs::RGPass&) {}); | |
| CHECK(g_barriers.size() == 2); | |
| if (g_barriers.size() == 2) | |
| CHECK(g_barriers[1].src == VK_PIPELINE_STAGE_TRANSFER_BIT && | |
| g_barriers[1].new_layout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); | |
| // 4c) follows: ์ง ํจ์ค๊ฐ ๊บผ์ง๋ฉด ๊ฐ์ด ๊ฑด๋๋ด๋ค | |
| json j5 = json::parse(R"({ | |
| "resources": {"a": {"type": "buffer"}}, | |
| "passes": [ | |
| {"name": "lead", "kind": "x", "optional": true, "uses": [["a", "storage_write"]]}, | |
| {"name": "tail", "kind": "x", "follows": "lead", "uses": [["a", "storage_read"]]} | |
| ]})"); | |
| g.load(j5); | |
| g.find("lead")->enabled = false; | |
| g.begin_frame(); | |
| std::vector<std::string> ran5; | |
| g.traverse(VK_NULL_HANDLE, [&](vkgs::RGPass& p) { ran5.push_back(p.name); }); | |
| CHECK(ran5.empty()); | |
| // 5) ๊บผ์ง ํจ์ค๋ ๊ฑด๋๋ด๋ค | |
| g.load(j3); | |
| g.find("r1")->enabled = false; | |
| g.begin_frame(); | |
| std::vector<std::string> ran; | |
| g.traverse(VK_NULL_HANDLE, [&](vkgs::RGPass& p) { ran.push_back(p.name); }); | |
| CHECK((ran == std::vector<std::string>{"w", "r2", "copy"})); | |
| // 5b) follows: ์ง ํจ์ค๊ฐ ์ผ์ ธ ์์ผ๋ฉด ๊ฐ์ด ๋๋ค | |
| g.load(j5); | |
| g.begin_frame(); | |
| std::vector<std::string> ran5b; | |
| g.traverse(VK_NULL_HANDLE, [&](vkgs::RGPass& p) { ran5b.push_back(p.name); }); | |
| CHECK((ran5b == std::vector<std::string>{"lead", "tail"})); | |
| // 5c) ์ ์ฒจ๋ถ๋ก ์ด ์ด๋ฏธ์ง๋ฅผ ์ปดํจํธ๊ฐ ์ฝ๊ธฐ (RAW) โ ๋ ๋ ํจ์ค finalLayout(GENERAL) ๊ทธ๋๋ก, ์ ์ถ๋ ฅ ๋จ๊ณ์์ | |
| json j6 = json::parse(R"({ | |
| "resources": {"img": {"type": "image"}, "dep": {"type": "image"}}, | |
| "passes": [ | |
| {"name": "raster", "kind": "x", "uses": [["img", "color_attachment"], ["dep", "depth_attachment"]]}, | |
| {"name": "read", "kind": "x", "uses": [["img", "storage_read"], ["dep", "storage_read"]]} | |
| ]})"); | |
| g.load(j6); | |
| g.bind_image("img", reinterpret_cast<VkImage>(uintptr_t(1))); | |
| g.bind_image("dep", reinterpret_cast<VkImage>(uintptr_t(2)), VK_IMAGE_ASPECT_DEPTH_BIT); | |
| g.begin_frame(); | |
| g_barriers.clear(); | |
| g.traverse(VK_NULL_HANDLE, [](vkgs::RGPass&) {}); | |
| CHECK(g_barriers.size() == 2); // ์ฒจ๋ถ ์์ฒด์๋ ๋ฐฐ๋ฆฌ์ด ์์ (๋ ๋ ํจ์ค ๋ชซ), ์ฝ๊ธฐ์ ๊ฐ 1๊ฐ | |
| if (g_barriers.size() == 2) { | |
| CHECK(g_barriers[0].src == VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT && | |
| g_barriers[0].old_layout == VK_IMAGE_LAYOUT_GENERAL && g_barriers[0].new_layout == VK_IMAGE_LAYOUT_GENERAL); | |
| CHECK(g_barriers[1].src == VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT && | |
| g_barriers[1].old_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL && | |
| g_barriers[1].new_layout == VK_IMAGE_LAYOUT_GENERAL); | |
| } | |
| // 6) ์ ์ฅ์์ ์ค์ ๊ทธ๋ํ๊ฐ ๋ก๋ยท์ ๋ ฌ๋๊ณ DOT ๋ฅผ ๋ง๋ ๋ค | |
| if (argc > 1) { | |
| std::ifstream f(argv[1]); | |
| g.load(json::parse(f, nullptr, true, true)); | |
| o = order_names(g); | |
| CHECK(o.front() == "clear_draw_args" && o.back() == "to_present"); | |
| CHECK(g.to_dot().find("digraph") != std::string::npos); | |
| // ์ค์ ๊ทธ๋ํ ์ํ: ๊ฐ์ ๋ ์ด์ด(์ ์ฒจ๋ถ) โ ๋ ์จ(์ปดํจํธ ์ฝ๊ธฐ) ์ ์ ์ถ๋ ฅ โ ์ปดํจํธ ๋ฐฐ๋ฆฌ์ด๊ฐ ์์ด์ผ ํ๋ค | |
| int k = 1; | |
| for (const auto& [name, r] : g.resources()) | |
| if (r.type == "image") g.bind_image(name, reinterpret_cast<VkImage>(uintptr_t(k++))); | |
| for (auto& p : g.passes()) p.enabled = true; | |
| g.begin_frame(); | |
| g_barriers.clear(); | |
| std::vector<std::string> ran6; | |
| g.traverse(VK_NULL_HANDLE, [&](vkgs::RGPass& p) { ran6.push_back(p.name); }); | |
| bool color_to_compute = false; | |
| for (const auto& b : g_barriers) | |
| if (b.image && b.src == VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT && (b.dst & VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT)) | |
| color_to_compute = true; | |
| CHECK(color_to_compute); | |
| CHECK(std::find(ran6.begin(), ran6.end(), "precip") < std::find(ran6.begin(), ran6.end(), "weather")); | |
| } | |
| std::printf("%s\n", fails ? "์คํจ" : "ํต๊ณผ"); | |
| return fails ? 1 : 0; | |
| } | |