From a9f5bcddeaee75b07297ef4807a9978daea56573 Mon Sep 17 00:00:00 2001 From: futz12 <1391525377@qq.com> Date: Sat, 12 Jul 2025 15:40:09 +0800 Subject: [PATCH 1/4] feat: shader compress --- CMakeLists.txt | 4 ++ cmake/ncnn_add_shader.cmake | 2 +- cmake/ncnn_generate_shader_comp_header.cmake | 51 +++++++++++++- src/CMakeLists.txt | 24 +++++++ src/gpu.cpp | 60 ++++++++++++++++- .../vulkan/shader/shader_compress_dict.in | 66 +++++++++++++++++++ src/platform.h.in | 1 + 7 files changed, 203 insertions(+), 5 deletions(-) create mode 100644 src/layer/vulkan/shader/shader_compress_dict.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 800bf47ca..ca7397bae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,10 @@ else() option(NCNN_BUILD_EXAMPLES "build examples" ON) endif() +if(NCNN_VULKAN) + option(NCNN_SHADER_COMPRESS "compress shader" OFF) +endif() + if(NCNN_SHARED_LIB) if(NCNN_ENABLE_LTO) # enable global link time optimization diff --git a/cmake/ncnn_add_shader.cmake b/cmake/ncnn_add_shader.cmake index 76680f4ca..0390bf32a 100644 --- a/cmake/ncnn_add_shader.cmake +++ b/cmake/ncnn_add_shader.cmake @@ -5,7 +5,7 @@ macro(ncnn_add_shader NCNN_SHADER_SRC) add_custom_command( OUTPUT ${NCNN_SHADER_COMP_HEADER} - COMMAND ${CMAKE_COMMAND} -DSHADER_SRC=${NCNN_SHADER_SRC} -DSHADER_COMP_HEADER=${NCNN_SHADER_COMP_HEADER} -P "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ncnn_generate_shader_comp_header.cmake" + COMMAND ${CMAKE_COMMAND} -DSHADER_SRC=${NCNN_SHADER_SRC} -DSHADER_COMP_HEADER=${NCNN_SHADER_COMP_HEADER} -DNCNN_SHADER_COMPRESS=${NCNN_SHADER_COMPRESS}- -P "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ncnn_generate_shader_comp_header.cmake" DEPENDS ${NCNN_SHADER_SRC} COMMENT "Preprocessing shader source ${NCNN_SHADER_SRC_NAME_WE}.comp" VERBATIM diff --git a/cmake/ncnn_generate_shader_comp_header.cmake b/cmake/ncnn_generate_shader_comp_header.cmake index 79f7c1eff..5604a1339 100644 --- a/cmake/ncnn_generate_shader_comp_header.cmake +++ b/cmake/ncnn_generate_shader_comp_header.cmake @@ -1,14 +1,57 @@ - # must define SHADER_COMP_HEADER SHADER_SRC file(READ ${SHADER_SRC} comp_data) +if(NCNN_SHADER_COMPRESS) + set(WORDLIST_FILE "${CMAKE_SOURCE_DIR}/../../src/layer/vulkan/shader/shader_compress_dict.in") + if(EXISTS ${WORDLIST_FILE}) + file(STRINGS ${WORDLIST_FILE} RAW_LIST) + + # 处理转义序列并创建新列表 + set(PROCESSED_LIST) + foreach(line IN LISTS RAW_LIST) + string(REPLACE "\\n" "\n" processed_line "${line}") + list(APPEND PROCESSED_LIST "${processed_line}") + endforeach() + + # 按长度降序排序 (优先匹配长字符串) + list(SORT PROCESSED_LIST COMPARE STRING ORDER DESCENDING) + set(WORD_LIST ${PROCESSED_LIST}) + else() + message(FATAL_ERROR "shader_compress_dict is missing: ${WORDLIST_FILE}") + endif() +endif() + # skip leading comment string(FIND "${comp_data}" "#version" version_start) if(NOT ${version_start} EQUAL -1) string(SUBSTRING "${comp_data}" ${version_start} -1 comp_data) endif() +if(NCNN_SHADER_COMPRESS) + # use + list(LENGTH WORD_LIST word_count) + if(word_count GREATER 128) + message(WARNING "词表过大(超过128词),将截断") + math(EXPR word_count "128") + endif() + + set(idx 0) + foreach(word IN LISTS WORD_LIST) + if(idx LESS 128) # 确保不超过128个词 + # 生成替换字符(128 + idx) + math(EXPR char_code "128 + ${idx}") + string(ASCII ${char_code} replace_char) + + # 执行全局替换 + string(REPLACE "${word}" "${replace_char}" comp_data "${comp_data}") + + # 索引递增 + math(EXPR idx "${idx} + 1") + endif() + endforeach() +endif () + # remove whitespace string(REGEX REPLACE "\n +" "\n" comp_data "${comp_data}") @@ -24,4 +67,8 @@ string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," comp_data_hex ${comp_data_hex string(FIND "${comp_data_hex}" "," tail_comma REVERSE) string(SUBSTRING "${comp_data_hex}" 0 ${tail_comma} comp_data_hex) -file(WRITE ${SHADER_COMP_HEADER} "static const char ${SHADER_SRC_NAME_WE}_comp_data[] = {${comp_data_hex}};\n") +if(NCNN_SHADER_COMPRESS) + file(WRITE ${SHADER_COMP_HEADER} "static const unsigned char ${SHADER_SRC_NAME_WE}_comp_data[] = {${comp_data_hex}};\n") +else () + file(WRITE ${SHADER_COMP_HEADER} "static const char ${SHADER_SRC_NAME_WE}_comp_data[] = {${comp_data_hex}};\n") +endif () \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cb7570a02..0eaa4c381 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -174,6 +174,30 @@ ncnn_add_layer(InverseSpectrogram) if(NCNN_VULKAN) ncnn_add_shader(${CMAKE_CURRENT_SOURCE_DIR}/convert_ycbcr.comp) ncnn_add_shader(${CMAKE_CURRENT_SOURCE_DIR}/layer/vulkan/shader/vulkan_activation.comp) + if(NCNN_SHADER_COMPRESS) + set(WORDLIST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/layer/vulkan/shader/shader_compress_dict.in") + if(EXISTS ${WORDLIST_FILE}) + file(STRINGS ${WORDLIST_FILE} RAW_LIST) + set(PROCESSED_LIST) + foreach(line IN LISTS RAW_LIST) + string(REPLACE "\\n" "\n" processed_line "${line}") + list(APPEND PROCESSED_LIST "${processed_line}") + endforeach() + list(SORT PROCESSED_LIST COMPARE STRING ORDER DESCENDING) + set(WORD_LIST ${PROCESSED_LIST}) + + # 导出 WORD_LIST 到文件 + set(OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/shader_compress_dict.in") + file(WRITE "${OUTPUT_FILE}" "") + foreach(line IN LISTS WORD_LIST) + string(REPLACE "\\" "\\\\" escaped_line "${line}") + string(REPLACE "\"" "\\\"" escaped_line "${escaped_line}") + file(APPEND "${OUTPUT_FILE}" "\"${escaped_line}\",\n") + endforeach() + else() + message(FATAL_ERROR "shader_compress_dict is missing: ${WORDLIST_FILE}") + endif() + endif() endif() add_custom_target(ncnn-generate-spirv DEPENDS ${NCNN_SHADER_SPV_HEX_FILES}) diff --git a/src/gpu.cpp b/src/gpu.cpp index c359a890d..14e84709d 100644 --- a/src/gpu.cpp +++ b/src/gpu.cpp @@ -87,11 +87,46 @@ static GpuInfo* g_gpu_infos[NCNN_MAX_GPU_COUNT] = {0}; static Mutex g_default_vkdev_lock; static VulkanDevice* g_default_vkdev[NCNN_MAX_GPU_COUNT] = {0}; +#ifdef NCNN_SHADER_COMPRESS +struct layer_shader_registry_entry +{ + const unsigned char* comp_data; + int comp_data_size; +}; + +void decompress_layer_shader(const unsigned char* comp_data, const int comp_data_size, char* &decompressed_data, int &decompressed_data_size) +{ + static const char* dict[] = { +#include "shader_compress_dict.in" + }; + + std::vector buffer; + for (int i = 0; i < comp_data_size; i++) + { + if (comp_data[i] < 0x80) + { + buffer.push_back(comp_data[i]); + } + else + { + for (char* c = (char*)dict[comp_data[i] - 0x80]; *c; c++) + { + buffer.push_back(*c); + } + } + } + decompressed_data_size = (int)buffer.size(); + decompressed_data = new char[decompressed_data_size]; + memcpy(decompressed_data, buffer.data(), decompressed_data_size); +} + +#else struct layer_shader_registry_entry { const char* comp_data; int comp_data_size; }; +#endif #include "layer_shader_spv_data.h" @@ -4409,9 +4444,19 @@ public: { if (strcmp(headerName, "vulkan_activation.comp") == 0) { +#ifdef NCNN_SHADER_COMPRESS + char* headerData; + int headerLength; + + decompress_layer_shader(vulkan_activation_comp_data,sizeof(vulkan_activation_comp_data), headerData, headerLength); +#else const char* const headerData = vulkan_activation_comp_data; const size_t headerLength = sizeof(vulkan_activation_comp_data); +#endif + glslang::TShader::Includer::IncludeResult* r = new glslang::TShader::Includer::IncludeResult(headerName, headerData, headerLength, 0); + + delete [] headerData; return r; } @@ -5536,11 +5581,22 @@ int compile_spirv_module(int shader_type_index, const Option& opt, std::vector= psc(w) || gy >= psc(h) || gz >= psc(c)) +int gx = int(gl_GlobalInvocationID.x); +int gy = int(gl_GlobalInvocationID.y); +int gz = int(gl_GlobalInvocationID.z); +const int gi = gz * psc(cstep) + gy * psc(w) + gx; +gl_GlobalInvocationID +afp v = buffer_ld1(bottom_top_blob_data, gi); +buffer_st1(bottom_top_blob_data, gi, v); +afpvec4 v = buffer_ld4(bottom_top_blob_data, gi); +buffer_st4(bottom_top_blob_data, gi, v); +bottom_top_blob_data +bottom_top_blob +top_blob_data +dims +cstep +out +scale +axis +buffer_ld8( +buffer_ld4( +buffer_ld1( +buffer +const +int +uint +afpvec4 +sfpvec8 +sfpvec4 +sfp +afp +readonly +writeonly +sum +bias +offset +psc +if +else +for +extension +return +#version 450 +matrix +fcoopmatNV +vec4 +coop +fp16 +order +type +blob +data +v_offset +gl_ScopeSubgroup +activation_type +CooperativeMatrix +max +min +abs +slope \ No newline at end of file diff --git a/src/platform.h.in b/src/platform.h.in index 8b7357eec..8dfc78d9e 100644 --- a/src/platform.h.in +++ b/src/platform.h.in @@ -57,6 +57,7 @@ #cmakedefine01 NCNN_INT8 #cmakedefine01 NCNN_BF16 #cmakedefine01 NCNN_FORCE_INLINE +#cmakedefine01 NCNN_SHADER_COMPRESS #cmakedefine NCNN_VERSION_STRING "@NCNN_VERSION_STRING@" From 381178d843f007b7820947d942eef9065b3a77f9 Mon Sep 17 00:00:00 2001 From: futz12 <56149058+futz12@users.noreply.github.com> Date: Sat, 12 Jul 2025 07:42:03 +0000 Subject: [PATCH 2/4] apply code-format changes --- src/gpu.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gpu.cpp b/src/gpu.cpp index 14e84709d..8123d7dff 100644 --- a/src/gpu.cpp +++ b/src/gpu.cpp @@ -94,7 +94,7 @@ struct layer_shader_registry_entry int comp_data_size; }; -void decompress_layer_shader(const unsigned char* comp_data, const int comp_data_size, char* &decompressed_data, int &decompressed_data_size) +void decompress_layer_shader(const unsigned char* comp_data, const int comp_data_size, char*& decompressed_data, int& decompressed_data_size) { static const char* dict[] = { #include "shader_compress_dict.in" @@ -4448,7 +4448,7 @@ public: char* headerData; int headerLength; - decompress_layer_shader(vulkan_activation_comp_data,sizeof(vulkan_activation_comp_data), headerData, headerLength); + decompress_layer_shader(vulkan_activation_comp_data, sizeof(vulkan_activation_comp_data), headerData, headerLength); #else const char* const headerData = vulkan_activation_comp_data; const size_t headerLength = sizeof(vulkan_activation_comp_data); @@ -4456,7 +4456,7 @@ public: glslang::TShader::Includer::IncludeResult* r = new glslang::TShader::Includer::IncludeResult(headerName, headerData, headerLength, 0); - delete [] headerData; + delete[] headerData; return r; } @@ -5584,7 +5584,7 @@ int compile_spirv_module(int shader_type_index, const Option& opt, std::vector Date: Mon, 14 Jul 2025 05:29:05 +0800 Subject: [PATCH 3/4] fix: error cpp marco and bad cmakelists --- CMakeLists.txt | 2 +- cmake/ncnn_add_shader.cmake | 25 ++++++++++++++++++------- src/gpu.cpp | 8 ++++---- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca7397bae..b64c20670 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,7 +107,7 @@ else() endif() if(NCNN_VULKAN) - option(NCNN_SHADER_COMPRESS "compress shader" OFF) + option(NCNN_SHADER_COMPRESS "compress shader" ON) endif() if(NCNN_SHARED_LIB) diff --git a/cmake/ncnn_add_shader.cmake b/cmake/ncnn_add_shader.cmake index 0390bf32a..afcea4c7e 100644 --- a/cmake/ncnn_add_shader.cmake +++ b/cmake/ncnn_add_shader.cmake @@ -3,13 +3,24 @@ macro(ncnn_add_shader NCNN_SHADER_SRC) get_filename_component(NCNN_SHADER_SRC_NAME_WE ${NCNN_SHADER_SRC} NAME_WE) set(NCNN_SHADER_COMP_HEADER ${CMAKE_CURRENT_BINARY_DIR}/layer/vulkan/shader/${NCNN_SHADER_SRC_NAME_WE}.comp.hex.h) - add_custom_command( - OUTPUT ${NCNN_SHADER_COMP_HEADER} - COMMAND ${CMAKE_COMMAND} -DSHADER_SRC=${NCNN_SHADER_SRC} -DSHADER_COMP_HEADER=${NCNN_SHADER_COMP_HEADER} -DNCNN_SHADER_COMPRESS=${NCNN_SHADER_COMPRESS}- -P "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ncnn_generate_shader_comp_header.cmake" - DEPENDS ${NCNN_SHADER_SRC} - COMMENT "Preprocessing shader source ${NCNN_SHADER_SRC_NAME_WE}.comp" - VERBATIM - ) + if(NCNN_SHADER_COMPRESS) + add_custom_command( + OUTPUT ${NCNN_SHADER_COMP_HEADER} + COMMAND ${CMAKE_COMMAND} -DSHADER_SRC=${NCNN_SHADER_SRC} -DSHADER_COMP_HEADER=${NCNN_SHADER_COMP_HEADER} -DNCNN_SHADER_COMPRESS=ON -P "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ncnn_generate_shader_comp_header.cmake" + DEPENDS ${NCNN_SHADER_SRC} + COMMENT "Preprocessing shader source ${NCNN_SHADER_SRC_NAME_WE}.comp" + VERBATIM + ) + else() + add_custom_command( + OUTPUT ${NCNN_SHADER_COMP_HEADER} + COMMAND ${CMAKE_COMMAND} -DSHADER_SRC=${NCNN_SHADER_SRC} -DSHADER_COMP_HEADER=${NCNN_SHADER_COMP_HEADER} -P "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ncnn_generate_shader_comp_header.cmake" + DEPENDS ${NCNN_SHADER_SRC} + COMMENT "Preprocessing shader source ${NCNN_SHADER_SRC_NAME_WE}.comp" + VERBATIM + ) + endif() + set_source_files_properties(${NCNN_SHADER_COMP_HEADER} PROPERTIES GENERATED TRUE) get_filename_component(NCNN_SHADER_COMP_HEADER_NAME ${NCNN_SHADER_COMP_HEADER} NAME) diff --git a/src/gpu.cpp b/src/gpu.cpp index 8123d7dff..70cbd5aff 100644 --- a/src/gpu.cpp +++ b/src/gpu.cpp @@ -87,7 +87,7 @@ static GpuInfo* g_gpu_infos[NCNN_MAX_GPU_COUNT] = {0}; static Mutex g_default_vkdev_lock; static VulkanDevice* g_default_vkdev[NCNN_MAX_GPU_COUNT] = {0}; -#ifdef NCNN_SHADER_COMPRESS +#if NCNN_SHADER_COMPRESS struct layer_shader_registry_entry { const unsigned char* comp_data; @@ -4444,7 +4444,7 @@ public: { if (strcmp(headerName, "vulkan_activation.comp") == 0) { -#ifdef NCNN_SHADER_COMPRESS +#if NCNN_SHADER_COMPRESS char* headerData; int headerLength; @@ -5581,7 +5581,7 @@ int compile_spirv_module(int shader_type_index, const Option& opt, std::vector Date: Mon, 14 Jul 2025 06:48:29 +0800 Subject: [PATCH 4/4] fix: remove cmake warning --- cmake/ncnn_generate_shader_comp_header.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/ncnn_generate_shader_comp_header.cmake b/cmake/ncnn_generate_shader_comp_header.cmake index 5604a1339..4ca4de197 100644 --- a/cmake/ncnn_generate_shader_comp_header.cmake +++ b/cmake/ncnn_generate_shader_comp_header.cmake @@ -1,4 +1,5 @@ # must define SHADER_COMP_HEADER SHADER_SRC +cmake_policy(SET CMP0007 OLD) file(READ ${SHADER_SRC} comp_data)