#pragma once #include #include #include #include #include #include "vulkan/typed_buffer.h" namespace mirage::render::shaders { // ============ 缓冲区结构 ============ // 根据 SPIR-V 反射自动生成 // ============ Buffer Structures ============ // Auto-generated from SPIR-V reflection // 由 SPIR-V 反射生成 // 绑定:0,描述符集:0 // 类型:storage_buffer struct alignas(16) PositionBuffer { // 偏移量:0,大小:runtime,对齐方式:16 uint32_t positions_count; // 运行时数组元素计数 alignas(16) Eigen::Vector4f positions[]; // 运行时数组数据 // std::span 访问器(非 const 版本) std::span get_positions() { return std::span(positions, positions_count); } // std::span 访问器(const 版本) std::span get_positions() const { return std::span(positions, positions_count); } }; // 由 SPIR-V 反射生成 // 绑定:1,描述符集:0 // 类型:storage_buffer struct alignas(16) VelocityBuffer { // 偏移量:0,大小:runtime,对齐方式:16 uint32_t velocities_count; // 运行时数组元素计数 alignas(16) Eigen::Vector3f velocities[]; // 运行时数组数据 // std::span 访问器(非 const 版本) std::span get_velocities() { return std::span(velocities, velocities_count); } // std::span 访问器(const 版本) std::span get_velocities() const { return std::span(velocities, velocities_count); } }; // 由 SPIR-V 反射生成 // 绑定:2,描述符集:0 // 类型:uniform_buffer struct alignas(4) ControlParams { // 偏移量:0,大小:4,对齐方式:4 float deltaTime; // 偏移量:4,大小:4,对齐方式:4 uint32_t particleCount; // 偏移量:8,大小:4,对齐方式:4 float damping; }; // ============ 缓冲区辅助函数 ============ // 自动生成缓冲区数据管理的便利函数 // ============ 缓冲区辅助函数 ============ // 自动生成缓冲区数据管理的便利函数 // 为 buffer_0 创建缓冲区(绑定 0) inline auto create_buffer_0_buffer( mirage::render::vulkan::resource_manager& rm, size_t element_count ) -> mirage::render::vulkan::expected { return rm.create_buffer( element_count * sizeof(PositionBuffer), vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent ); } // 将数据上传到 buffer_0 缓冲区 inline void upload_buffer_0( vk::Device device, const mirage::render::vulkan::resource_manager::buffer_resource& buffer, std::span data ) { if (data.size_bytes() > buffer.size) { throw std::runtime_error("Data size exceeds buffer capacity"); } void* mapped = device.mapMemory(buffer.memory, 0, buffer.size); std::memcpy(mapped, data.data(), data.size_bytes()); device.unmapMemory(buffer.memory); } // 从 buffer_0 缓冲区下载数据 inline void download_buffer_0( vk::Device device, const mirage::render::vulkan::resource_manager::buffer_resource& buffer, std::span out_data ) { if (out_data.size_bytes() > buffer.size) { throw std::runtime_error("Output buffer size exceeds buffer capacity"); } void* mapped = device.mapMemory(buffer.memory, 0, buffer.size); std::memcpy(out_data.data(), mapped, out_data.size_bytes()); device.unmapMemory(buffer.memory); } // 为 buffer_1 创建缓冲区(绑定 1) inline auto create_buffer_1_buffer( mirage::render::vulkan::resource_manager& rm, size_t element_count ) -> mirage::render::vulkan::expected { return rm.create_buffer( element_count * sizeof(VelocityBuffer), vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent ); } // 将数据上传到 buffer_1 缓冲区 inline void upload_buffer_1( vk::Device device, const mirage::render::vulkan::resource_manager::buffer_resource& buffer, std::span data ) { if (data.size_bytes() > buffer.size) { throw std::runtime_error("Data size exceeds buffer capacity"); } void* mapped = device.mapMemory(buffer.memory, 0, buffer.size); std::memcpy(mapped, data.data(), data.size_bytes()); device.unmapMemory(buffer.memory); } // 从 buffer_1 缓冲区下载数据 inline void download_buffer_1( vk::Device device, const mirage::render::vulkan::resource_manager::buffer_resource& buffer, std::span out_data ) { if (out_data.size_bytes() > buffer.size) { throw std::runtime_error("Output buffer size exceeds buffer capacity"); } void* mapped = device.mapMemory(buffer.memory, 0, buffer.size); std::memcpy(out_data.data(), mapped, out_data.size_bytes()); device.unmapMemory(buffer.memory); } // 为 buffer_2 创建缓冲区(绑定 2) inline auto create_buffer_2_buffer( mirage::render::vulkan::resource_manager& rm, size_t element_count ) -> mirage::render::vulkan::expected { return rm.create_buffer( element_count * sizeof(ControlParams), vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent ); } // 将数据上传到 buffer_2 缓冲区 inline void upload_buffer_2( vk::Device device, const mirage::render::vulkan::resource_manager::buffer_resource& buffer, std::span data ) { if (data.size_bytes() > buffer.size) { throw std::runtime_error("Data size exceeds buffer capacity"); } void* mapped = device.mapMemory(buffer.memory, 0, buffer.size); std::memcpy(mapped, data.data(), data.size_bytes()); device.unmapMemory(buffer.memory); } // 从 buffer_2 缓冲区下载数据 inline void download_buffer_2( vk::Device device, const mirage::render::vulkan::resource_manager::buffer_resource& buffer, std::span out_data ) { if (out_data.size_bytes() > buffer.size) { throw std::runtime_error("Output buffer size exceeds buffer capacity"); } void* mapped = device.mapMemory(buffer.memory, 0, buffer.size); std::memcpy(out_data.data(), mapped, out_data.size_bytes()); device.unmapMemory(buffer.memory); } // ============ 类型化缓冲区别名 ============ // 类型安全缓冲区包装器的类型别名和工厂函数 // ============ Typed Buffer Aliases ============ // Type aliases and factory functions for type-safe buffer wrappers // buffer_0 类型缓冲区的类型别名 using buffer_0_buffer = mirage::render::vulkan::typed_buffer; // 为 buffer_0 创建类型化缓冲区(绑定 0) inline auto create_buffer_0_typed( vk::Device device, mirage::render::vulkan::resource_manager& rm, size_t count ) -> mirage::render::vulkan::expected { auto buffer_result = create_buffer_0_buffer(rm, count); if (!buffer_result) { return std::unexpected(buffer_result.error()); } return buffer_0_buffer(device, std::move(*buffer_result), count); } // buffer_1 类型缓冲区的类型别名 using buffer_1_buffer = mirage::render::vulkan::typed_buffer; // 为 buffer_1 创建类型化缓冲区(绑定 1) inline auto create_buffer_1_typed( vk::Device device, mirage::render::vulkan::resource_manager& rm, size_t count ) -> mirage::render::vulkan::expected { auto buffer_result = create_buffer_1_buffer(rm, count); if (!buffer_result) { return std::unexpected(buffer_result.error()); } return buffer_1_buffer(device, std::move(*buffer_result), count); } // buffer_2 类型缓冲区的类型别名 using buffer_2_buffer = mirage::render::vulkan::typed_buffer; // 为 buffer_2 创建类型化缓冲区(绑定 2) inline auto create_buffer_2_typed( vk::Device device, mirage::render::vulkan::resource_manager& rm, size_t count ) -> mirage::render::vulkan::expected { auto buffer_result = create_buffer_2_buffer(rm, count); if (!buffer_result) { return std::unexpected(buffer_result.error()); } return buffer_2_buffer(device, std::move(*buffer_result), count); } // ============ 缓冲区管理器类 ============ // 所有着色器缓冲区的自动生命周期管理 // ============ Buffer Manager Class ============ // Automatic lifecycle management for all shader buffers class runtime_array_test_buffer_manager { public: // 所有缓冲区的容器 struct buffers { buffer_0_buffer buffer_0; buffer_1_buffer buffer_1; buffer_2_buffer buffer_2; }; // 创建缓冲区管理器的工厂方法 static auto create( vk::Device device, mirage::render::vulkan::resource_manager& rm, size_t element_count ) -> mirage::render::vulkan::expected { auto buffer_0_result = create_buffer_0_typed(device, rm, element_count); if (!buffer_0_result) { return std::unexpected(buffer_0_result.error()); } auto buffer_1_result = create_buffer_1_typed(device, rm, element_count); if (!buffer_1_result) { return std::unexpected(buffer_1_result.error()); } auto buffer_2_result = create_buffer_2_typed(device, rm, element_count); if (!buffer_2_result) { return std::unexpected(buffer_2_result.error()); } return runtime_array_test_buffer_manager( device, std::move(*buffer_0_result), std::move(*buffer_1_result), std::move(*buffer_2_result) ); } // 用数据初始化所有缓冲区 void initialize( std::span buffer_0_data, std::span buffer_1_data, std::span buffer_2_data ) { buffers_.buffer_0.upload(buffer_0_data); buffers_.buffer_1.upload(buffer_1_data); buffers_.buffer_2.upload(buffer_2_data); } // 将所有缓冲区绑定到描述符集 void bind_to_descriptor_set( const mirage::render::vulkan::compute_pipeline& pipeline, vk::DescriptorSet descriptor_set ) const { pipeline.bind_buffer( descriptor_set, 0, buffers_.buffer_0.get_buffer(), vk::DescriptorType::eStorageBuffer ); pipeline.bind_buffer( descriptor_set, 1, buffers_.buffer_1.get_buffer(), vk::DescriptorType::eStorageBuffer ); pipeline.bind_buffer( descriptor_set, 2, buffers_.buffer_2.get_buffer(), vk::DescriptorType::eUniformBuffer ); } // 访问缓冲区 auto& get_buffers() { return buffers_; } const auto& get_buffers() const { return buffers_; } private: runtime_array_test_buffer_manager( vk::Device device, buffer_0_buffer buffer_0, buffer_1_buffer buffer_1, buffer_2_buffer buffer_2 ) : device_(device), buffers_{ .buffer_0 = std::move(buffer_0), .buffer_1 = std::move(buffer_1), .buffer_2 = std::move(buffer_2) } {} vk::Device device_; buffers buffers_; }; // COMP 着色器:runtime_array_test.comp.glsl // 编译为:glslc ... --target-env=vulkan1.2 static constexpr uint32_t runtime_array_test_comp_spirv[] = { 0x07230203, 0x00010500, 0x000d000b, 0x0000004b, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, 0x0009000f, 0x00000005, 0x00000004, 0x6e69616d, 0x00000000, 0x0000000b, 0x00000014, 0x00000023, 0x0000002a, 0x00060010, 0x00000004, 0x00000011, 0x00000100, 0x00000001, 0x00000001, 0x00030003, 0x00000002, 0x000001c2, 0x000a0004, 0x475f4c47, 0x4c474f4f, 0x70635f45, 0x74735f70, 0x5f656c79, 0x656e696c, 0x7269645f, 0x69746365, 0x00006576, 0x00080004, 0x475f4c47, 0x4c474f4f, 0x6e695f45, 0x64756c63, 0x69645f65, 0x74636572, 0x00657669, 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00030005, 0x00000008, 0x00786469, 0x00080005, 0x0000000b, 0x475f6c67, 0x61626f6c, 0x766e496c, 0x7461636f, 0x496e6f69, 0x00000044, 0x00060005, 0x00000012, 0x746e6f43, 0x506c6f72, 0x6d617261, 0x00000073, 0x00060006, 0x00000012, 0x00000000, 0x746c6564, 0x6d695461, 0x00000065, 0x00070006, 0x00000012, 0x00000001, 0x74726170, 0x656c6369, 0x6e756f43, 0x00000074, 0x00050006, 0x00000012, 0x00000002, 0x706d6164, 0x00676e69, 0x00030005, 0x00000014, 0x00000000, 0x00060005, 0x00000021, 0x69736f50, 0x6e6f6974, 0x66667542, 0x00007265, 0x00060006, 0x00000021, 0x00000000, 0x69736f70, 0x6e6f6974, 0x00000073, 0x00030005, 0x00000023, 0x00000000, 0x00060005, 0x00000028, 0x6f6c6556, 0x79746963, 0x66667542, 0x00007265, 0x00060006, 0x00000028, 0x00000000, 0x6f6c6576, 0x69746963, 0x00007365, 0x00030005, 0x0000002a, 0x00000000, 0x00040047, 0x0000000b, 0x0000000b, 0x0000001c, 0x00030047, 0x00000012, 0x00000002, 0x00050048, 0x00000012, 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x00000012, 0x00000001, 0x00000023, 0x00000004, 0x00050048, 0x00000012, 0x00000002, 0x00000023, 0x00000008, 0x00040047, 0x00000014, 0x00000021, 0x00000002, 0x00040047, 0x00000014, 0x00000022, 0x00000000, 0x00040047, 0x00000020, 0x00000006, 0x00000010, 0x00030047, 0x00000021, 0x00000002, 0x00050048, 0x00000021, 0x00000000, 0x00000023, 0x00000000, 0x00040047, 0x00000023, 0x00000021, 0x00000000, 0x00040047, 0x00000023, 0x00000022, 0x00000000, 0x00040047, 0x00000027, 0x00000006, 0x00000010, 0x00030047, 0x00000028, 0x00000002, 0x00050048, 0x00000028, 0x00000000, 0x00000023, 0x00000000, 0x00040047, 0x0000002a, 0x00000021, 0x00000001, 0x00040047, 0x0000002a, 0x00000022, 0x00000000, 0x00040047, 0x0000004a, 0x0000000b, 0x00000019, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00040015, 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, 0x00000007, 0x00000006, 0x00040017, 0x00000009, 0x00000006, 0x00000003, 0x00040020, 0x0000000a, 0x00000001, 0x00000009, 0x0004003b, 0x0000000a, 0x0000000b, 0x00000001, 0x0004002b, 0x00000006, 0x0000000c, 0x00000000, 0x00040020, 0x0000000d, 0x00000001, 0x00000006, 0x00030016, 0x00000011, 0x00000020, 0x0005001e, 0x00000012, 0x00000011, 0x00000006, 0x00000011, 0x00040020, 0x00000013, 0x00000002, 0x00000012, 0x0004003b, 0x00000013, 0x00000014, 0x00000002, 0x00040015, 0x00000015, 0x00000020, 0x00000001, 0x0004002b, 0x00000015, 0x00000016, 0x00000001, 0x00040020, 0x00000017, 0x00000002, 0x00000006, 0x00020014, 0x0000001a, 0x00040017, 0x0000001f, 0x00000011, 0x00000004, 0x0003001d, 0x00000020, 0x0000001f, 0x0003001e, 0x00000021, 0x00000020, 0x00040020, 0x00000022, 0x0000000c, 0x00000021, 0x0004003b, 0x00000022, 0x00000023, 0x0000000c, 0x0004002b, 0x00000015, 0x00000024, 0x00000000, 0x00040017, 0x00000026, 0x00000011, 0x00000003, 0x0003001d, 0x00000027, 0x00000026, 0x0003001e, 0x00000028, 0x00000027, 0x00040020, 0x00000029, 0x0000000c, 0x00000028, 0x0004003b, 0x00000029, 0x0000002a, 0x0000000c, 0x00040020, 0x0000002c, 0x0000000c, 0x00000026, 0x00040020, 0x0000002f, 0x00000002, 0x00000011, 0x00040020, 0x00000033, 0x0000000c, 0x0000001f, 0x00040020, 0x00000038, 0x0000000c, 0x00000011, 0x0004002b, 0x00000006, 0x0000003b, 0x00000001, 0x0004002b, 0x00000006, 0x0000003e, 0x00000002, 0x0004002b, 0x00000015, 0x00000042, 0x00000002, 0x0004002b, 0x00000006, 0x00000049, 0x00000100, 0x0006002c, 0x00000009, 0x0000004a, 0x00000049, 0x0000003b, 0x0000003b, 0x00050036, 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x00000007, 0x00000008, 0x00000007, 0x00050041, 0x0000000d, 0x0000000e, 0x0000000b, 0x0000000c, 0x0004003d, 0x00000006, 0x0000000f, 0x0000000e, 0x0003003e, 0x00000008, 0x0000000f, 0x0004003d, 0x00000006, 0x00000010, 0x00000008, 0x00050041, 0x00000017, 0x00000018, 0x00000014, 0x00000016, 0x0004003d, 0x00000006, 0x00000019, 0x00000018, 0x000500ae, 0x0000001a, 0x0000001b, 0x00000010, 0x00000019, 0x000300f7, 0x0000001d, 0x00000000, 0x000400fa, 0x0000001b, 0x0000001c, 0x0000001d, 0x000200f8, 0x0000001c, 0x000100fd, 0x000200f8, 0x0000001d, 0x0004003d, 0x00000006, 0x00000025, 0x00000008, 0x0004003d, 0x00000006, 0x0000002b, 0x00000008, 0x00060041, 0x0000002c, 0x0000002d, 0x0000002a, 0x00000024, 0x0000002b, 0x0004003d, 0x00000026, 0x0000002e, 0x0000002d, 0x00050041, 0x0000002f, 0x00000030, 0x00000014, 0x00000024, 0x0004003d, 0x00000011, 0x00000031, 0x00000030, 0x0005008e, 0x00000026, 0x00000032, 0x0000002e, 0x00000031, 0x00060041, 0x00000033, 0x00000034, 0x00000023, 0x00000024, 0x00000025, 0x0004003d, 0x0000001f, 0x00000035, 0x00000034, 0x0008004f, 0x00000026, 0x00000036, 0x00000035, 0x00000035, 0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x00000026, 0x00000037, 0x00000036, 0x00000032, 0x00070041, 0x00000038, 0x00000039, 0x00000023, 0x00000024, 0x00000025, 0x0000000c, 0x00050051, 0x00000011, 0x0000003a, 0x00000037, 0x00000000, 0x0003003e, 0x00000039, 0x0000003a, 0x00070041, 0x00000038, 0x0000003c, 0x00000023, 0x00000024, 0x00000025, 0x0000003b, 0x00050051, 0x00000011, 0x0000003d, 0x00000037, 0x00000001, 0x0003003e, 0x0000003c, 0x0000003d, 0x00070041, 0x00000038, 0x0000003f, 0x00000023, 0x00000024, 0x00000025, 0x0000003e, 0x00050051, 0x00000011, 0x00000040, 0x00000037, 0x00000002, 0x0003003e, 0x0000003f, 0x00000040, 0x0004003d, 0x00000006, 0x00000041, 0x00000008, 0x00050041, 0x0000002f, 0x00000043, 0x00000014, 0x00000042, 0x0004003d, 0x00000011, 0x00000044, 0x00000043, 0x00060041, 0x0000002c, 0x00000045, 0x0000002a, 0x00000024, 0x00000041, 0x0004003d, 0x00000026, 0x00000046, 0x00000045, 0x0005008e, 0x00000026, 0x00000047, 0x00000046, 0x00000044, 0x00060041, 0x0000002c, 0x00000048, 0x0000002a, 0x00000024, 0x00000041, 0x0003003e, 0x00000048, 0x00000047, 0x000100fd, 0x00010038 }; struct runtime_array_test_metadata { static constexpr std::string_view name = "runtime_array_test"; static constexpr std::string_view entry_point = "main"; }; inline constexpr std::array runtime_array_test_bindings = {{ mirage::render::vulkan::compute_pipeline::binding_info{ .binding = 0, .type = vk::DescriptorType::eStorageBuffer, .count = 1, .stage = vk::ShaderStageFlagBits::eCompute, }, mirage::render::vulkan::compute_pipeline::binding_info{ .binding = 1, .type = vk::DescriptorType::eStorageBuffer, .count = 1, .stage = vk::ShaderStageFlagBits::eCompute, }, mirage::render::vulkan::compute_pipeline::binding_info{ .binding = 2, .type = vk::DescriptorType::eUniformBuffer, .count = 1, .stage = vk::ShaderStageFlagBits::eCompute, }, }}; // ============ 工厂功能 ============ inline auto create_runtime_array_test_pipeline(const mirage::render::vulkan::logical_device& device) -> mirage::render::vulkan::expected { return mirage::render::vulkan::compute_pipeline::create_from_spv( device, std::span(runtime_array_test_comp_spirv), runtime_array_test_bindings ); } } // namespace mirage::render::shaders