From fe26c1de17fae2706adb02d3336bcfb2b183db01 Mon Sep 17 00:00:00 2001 From: nmzik Date: Mon, 14 Sep 2026 16:04:51 +0400 Subject: [PATCH] Share SPIR-V module creation --- .../host_gpu/renderer/cache/faultManager.cpp | 7 +---- .../host_gpu/renderer/image/blitHelper.cpp | 17 ++---------- .../host_gpu/renderer/image/blitHelper.h | 3 +-- .../host_gpu/renderer/image/tiler.cpp | 22 +++------------- .../renderer/pipeline/pipelineCache.cpp | 7 +---- .../host_gpu/renderer/pipeline/shaders.cpp | 26 ++++++------------- src/graphics/host_gpu/vulkanCommon.cpp | 10 +++++++ src/graphics/host_gpu/vulkanCommon.h | 2 ++ 8 files changed, 29 insertions(+), 65 deletions(-) diff --git a/src/graphics/host_gpu/renderer/cache/faultManager.cpp b/src/graphics/host_gpu/renderer/cache/faultManager.cpp index c40b54e86..cc9172e41 100644 --- a/src/graphics/host_gpu/renderer/cache/faultManager.cpp +++ b/src/graphics/host_gpu/renderer/cache/faultManager.cpp @@ -44,12 +44,7 @@ FaultManager::FaultManager(GraphicContext& graphics, CommandScheduler& scheduler &m_fault_process_desc_layout), "create fault-buffer descriptor layout"); - vk::ShaderModuleCreateInfo module_info {}; - module_info.codeSize = std::size(FAULT_BUFFER_PROCESS_SPV) * sizeof(uint32_t); - module_info.pCode = FAULT_BUFFER_PROCESS_SPV; - vk::ShaderModule module = nullptr; - RequireVulkanSuccess(m_graphics.device.createShaderModule(&module_info, nullptr, &module), - "create fault-buffer shader module"); + const auto module = CompileSPV(FAULT_BUFFER_PROCESS_SPV, m_graphics.device); vk::PipelineLayoutCreateInfo pipeline_layout_info {}; pipeline_layout_info.setLayoutCount = 1; diff --git a/src/graphics/host_gpu/renderer/image/blitHelper.cpp b/src/graphics/host_gpu/renderer/image/blitHelper.cpp index d6a59fbb3..f5dbf2c7a 100644 --- a/src/graphics/host_gpu/renderer/image/blitHelper.cpp +++ b/src/graphics/host_gpu/renderer/image/blitHelper.cpp @@ -10,7 +10,6 @@ #include #include -#include namespace Libs::Graphics { @@ -37,9 +36,8 @@ BlitHelper::BlitHelper(GraphicContext& graphics, CommandScheduler& scheduler) m_graphics.device.createPipelineLayout(&layout_info, nullptr, &m_pipeline_layout), "create BlitHelper pipeline layout"); - m_vertex_shader = CreateShader(GPU_BLIT_FS_TRIANGLE_SPV, std::size(GPU_BLIT_FS_TRIANGLE_SPV)); - m_fragment_shader = - CreateShader(GPU_BLIT_COLOR_TO_MS_DEPTH_SPV, std::size(GPU_BLIT_COLOR_TO_MS_DEPTH_SPV)); + m_vertex_shader = CompileSPV(GPU_BLIT_FS_TRIANGLE_SPV, m_graphics.device); + m_fragment_shader = CompileSPV(GPU_BLIT_COLOR_TO_MS_DEPTH_SPV, m_graphics.device); } BlitHelper::~BlitHelper() { @@ -60,17 +58,6 @@ BlitHelper::~BlitHelper() { } } -vk::ShaderModule BlitHelper::CreateShader(const uint32_t* code, size_t words) const { - EXIT_IF(code == nullptr || words == 0); - vk::ShaderModuleCreateInfo create {}; - create.codeSize = words * sizeof(uint32_t); - create.pCode = code; - vk::ShaderModule module = nullptr; - RequireVulkanSuccess(m_graphics.device.createShaderModule(&create, nullptr, &module), - "create BlitHelper shader module"); - return module; -} - vk::Pipeline BlitHelper::GetPipeline(PipelineKey key) { const auto cached = std::ranges::find(m_pipelines, key, &Pipeline::key); if (cached != m_pipelines.end()) { diff --git a/src/graphics/host_gpu/renderer/image/blitHelper.h b/src/graphics/host_gpu/renderer/image/blitHelper.h index 1c23ef78c..c9476b105 100644 --- a/src/graphics/host_gpu/renderer/image/blitHelper.h +++ b/src/graphics/host_gpu/renderer/image/blitHelper.h @@ -37,8 +37,7 @@ private: vk::Pipeline handle = nullptr; }; - [[nodiscard]] vk::ShaderModule CreateShader(const uint32_t* code, size_t words) const; - [[nodiscard]] vk::Pipeline GetPipeline(PipelineKey key); + [[nodiscard]] vk::Pipeline GetPipeline(PipelineKey key); GraphicContext& m_graphics; CommandScheduler& m_scheduler; diff --git a/src/graphics/host_gpu/renderer/image/tiler.cpp b/src/graphics/host_gpu/renderer/image/tiler.cpp index 445f5ea96..06f20cf80 100644 --- a/src/graphics/host_gpu/renderer/image/tiler.cpp +++ b/src/graphics/host_gpu/renderer/image/tiler.cpp @@ -260,12 +260,8 @@ vk::Pipeline TileManager::GetPipeline(uint32_t slot) { const uint32_t values[] {1u << element_index, direction_index}; const vk::SpecializationMapEntry entries[] {{0, 0, 4}, {1, 4, 4}}; const vk::SpecializationInfo specialization {2, entries, sizeof(values), values}; - vk::ShaderModuleCreateInfo module_info {}; - module_info.codeSize = shaders[family_index].words * sizeof(uint32_t); - module_info.pCode = shaders[family_index].code; - vk::ShaderModule module = nullptr; - RequireVulkanSuccess(m_graphics.device.createShaderModule(&module_info, nullptr, &module), - "create TileManager shader module"); + const auto module = + CompileSPV({shaders[family_index].code, shaders[family_index].words}, m_graphics.device); vk::PipelineShaderStageCreateInfo stage {}; stage.stage = vk::ShaderStageFlagBits::eCompute; stage.module = module; @@ -472,12 +468,7 @@ void TileManager::ConvertD16(Result source, Result target, D16Direction directio code = GPU_TILER_DEMOTE_D16_SPV; words = std::size(GPU_TILER_DEMOTE_D16_SPV); } - vk::ShaderModuleCreateInfo module_info {}; - module_info.codeSize = words * sizeof(uint32_t); - module_info.pCode = code; - vk::ShaderModule module = nullptr; - RequireVulkanSuccess(m_graphics.device.createShaderModule(&module_info, nullptr, &module), - "create D16 conversion shader module"); + const auto module = CompileSPV({code, words}, m_graphics.device); vk::PipelineShaderStageCreateInfo stage {}; stage.stage = vk::ShaderStageFlagBits::eCompute; stage.module = module; @@ -611,12 +602,7 @@ void TileManager::ConvertD16(Result source, Result target, D16Direction directio void TileManager::SwapBgra16(Result input, Result output, uint32_t pixels) { if (m_swap_bgra16 == nullptr) { - vk::ShaderModuleCreateInfo module_info {}; - module_info.codeSize = std::size(GPU_TILER_SWAP_BGRA16_SPV) * sizeof(uint32_t); - module_info.pCode = GPU_TILER_SWAP_BGRA16_SPV; - vk::ShaderModule module = nullptr; - RequireVulkanSuccess(m_graphics.device.createShaderModule(&module_info, nullptr, &module), - "create BGRA16 swap shader module"); + const auto module = CompileSPV(GPU_TILER_SWAP_BGRA16_SPV, m_graphics.device); vk::PipelineShaderStageCreateInfo stage {}; stage.stage = vk::ShaderStageFlagBits::eCompute; stage.module = module; diff --git a/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp b/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp index 23502f401..0e9b01594 100644 --- a/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp +++ b/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp @@ -253,12 +253,7 @@ struct PipelineCache::ProgramCache { } DumpShaderSpirv(stage_name, options.shader_hash, result.spirv); - vk::ShaderModuleCreateInfo create_info {}; - create_info.codeSize = result.spirv.size() * sizeof(uint32_t); - create_info.pCode = result.spirv.data(); - vk::ShaderModule module = nullptr; - RequireVulkanSuccess(device.createShaderModule(&create_info, nullptr, &module), - "create recompiled shader module"); + const auto module = CompileSPV(result.spirv, device); EXIT_IF(module == nullptr); if (options.dump_ir) { LOGF("%s SPIR-V words=%" PRIu64 " wave_size=%u\n", options.dump_label, diff --git a/src/graphics/host_gpu/renderer/pipeline/shaders.cpp b/src/graphics/host_gpu/renderer/pipeline/shaders.cpp index dc7165ef9..f07ed0c25 100644 --- a/src/graphics/host_gpu/renderer/pipeline/shaders.cpp +++ b/src/graphics/host_gpu/renderer/pipeline/shaders.cpp @@ -231,30 +231,20 @@ void CreatePipelineInternal(GraphicContext& graphics, PipelineCache::Pipeline& p vk::ShaderModule tess_control_shader_module = nullptr; vk::ShaderModule tess_eval_shader_module = nullptr; - vk::ShaderModuleCreateInfo create_info {}; - vk::Result result {}; if (rect_list) { const auto shaders = BuildRectListShaders(vs_input_info, ps_active ? ps_input_info : nullptr); - create_info.codeSize = shaders.control.size() * 4; - create_info.pCode = shaders.control.data(); - result = - graphics.device.createShaderModule(&create_info, nullptr, &tess_control_shader_module); + tess_control_shader_module = CompileSPV(shaders.control, graphics.device); if (graphics_debug_dump_enabled()) { - LOGF("PipelineTrace: vkCreateShaderModule RectList TCS done result=%s module=%p\n", - vk::to_string(result).c_str(), static_cast(tess_control_shader_module)); + LOGF("PipelineTrace: vkCreateShaderModule RectList TCS done module=%p\n", + static_cast(tess_control_shader_module)); } - EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess); - create_info.codeSize = shaders.evaluation.size() * 4; - create_info.pCode = shaders.evaluation.data(); - result = - graphics.device.createShaderModule(&create_info, nullptr, &tess_eval_shader_module); + tess_eval_shader_module = CompileSPV(shaders.evaluation, graphics.device); if (graphics_debug_dump_enabled()) { - LOGF("PipelineTrace: vkCreateShaderModule RectList TES done result=%s module=%p\n", - vk::to_string(result).c_str(), static_cast(tess_eval_shader_module)); + LOGF("PipelineTrace: vkCreateShaderModule RectList TES done module=%p\n", + static_cast(tess_eval_shader_module)); } - EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess); } EXIT_NOT_IMPLEMENTED( @@ -470,8 +460,8 @@ void CreatePipelineInternal(GraphicContext& graphics, PipelineCache::Pipeline& p " set_layouts=1 push_constants=%" PRIu32 "\n", vertex_program.id, ps_active ? pixel_program.id : 0, 1u); } - result = graphics.device.createPipelineLayout(&pipeline_layout_info, nullptr, - &pipeline.pipeline_layout); + auto result = graphics.device.createPipelineLayout(&pipeline_layout_info, nullptr, + &pipeline.pipeline_layout); if (graphics_debug_dump_enabled()) { LOGF("PipelineTrace: vkCreatePipelineLayout done result=%s layout=%p\n", vk::to_string(result).c_str(), static_cast(pipeline.pipeline_layout)); diff --git a/src/graphics/host_gpu/vulkanCommon.cpp b/src/graphics/host_gpu/vulkanCommon.cpp index 2c8af0865..e39dfb7eb 100644 --- a/src/graphics/host_gpu/vulkanCommon.cpp +++ b/src/graphics/host_gpu/vulkanCommon.cpp @@ -123,4 +123,14 @@ void RequireVulkanSuccess(vk::Result result, const char* operation) { } } +vk::ShaderModule CompileSPV(std::span code, vk::Device device) { + vk::ShaderModuleCreateInfo create_info {}; + create_info.codeSize = code.size_bytes(); + create_info.pCode = code.data(); + vk::ShaderModule module = nullptr; + RequireVulkanSuccess(device.createShaderModule(&create_info, nullptr, &module), + "create SPIR-V shader module"); + return module; +} + } // namespace Libs::Graphics diff --git a/src/graphics/host_gpu/vulkanCommon.h b/src/graphics/host_gpu/vulkanCommon.h index 4f520e6ba..bcf978832 100644 --- a/src/graphics/host_gpu/vulkanCommon.h +++ b/src/graphics/host_gpu/vulkanCommon.h @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,7 @@ using VulkanMemoryBarrier = vk::MemoryBarrier; vk::Format VulkanFormat(Prospero::BufferFormat guest_format); void RequireVulkanSuccess(vk::Result result, const char* operation); +vk::ShaderModule CompileSPV(std::span code, vk::Device device); template void SetVulkanObjectNameF(vk::Device device, Handle handle, fmt::format_string format,