Skip to content

Commit 84970ee

Browse files
authored
vulkan validation layer enables NCNN_LOGE in shader source (#5963)
* NCNN_LOGE in glsl * Update glsl-extension.md
1 parent 23cdc81 commit 84970ee

File tree

2 files changed

+133
-17
lines changed

2 files changed

+133
-17
lines changed

docs/developer-guide/glsl-extension.md

+92-10
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,6 @@ You can write shader code with ncnn glsl extension, compiled to spir-v using ncn
7676
static const char my_glsl_data[] = R"(
7777
#version 450
7878
79-
#if NCNN_fp16_storage
80-
#extension GL_EXT_shader_16bit_storage: require
81-
#endif
82-
#if NCNN_fp16_arithmetic
83-
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
84-
#endif
85-
8679
layout (binding = 0) readonly buffer a_blob { sfpvec4 a_blob_data[]; };
8780
layout (binding = 1) writeonly buffer b_blob { sfpvec4 b_blob_data[]; };
8881
@@ -336,17 +329,106 @@ judge if the current platform is moltenvk, for enabling some platform-specific w
336329
#endif
337330
```
338331

339-
# option macros
332+
ncnn additionally defines most of the vulkan device-related features as macros, which we can use to distinguish different platforms, device extensions, features, and properties
333+
334+
### extension macros
335+
336+
When the device supports an extension, `ncnn_<extension_name>` is defined as the extension version
337+
338+
```c
339+
void main()
340+
{
341+
#if ncnn_VK_KHR_16bit_storage
342+
// here is the code for any device that supports VK_KHR_16bit_storage
343+
#endif
344+
345+
#if ncnn_VK_KHR_sampler_ycbcr_conversion >= 10
346+
// here is the code for any device that supports VK_KHR_sampler_ycbcr_conversion and version >= 10
347+
#endif
348+
}
349+
```
350+
351+
### device feature and property macros
352+
353+
ncnn will query device features and properties and then define them as macros.
354+
355+
The macro name is `ncnn_<feature_name>` or `ncnn_<property_name>`
356+
357+
The `GL_EXT_shader_explicit_arithmetic_types_int64` extension will be automatically enabled without explicit code indication when the device supports `shaderInt64`
358+
359+
```c
360+
void main()
361+
{
362+
#if ncnn_robustBufferAccess
363+
// here is the code for any device that supports robustBufferAccess feature
364+
#endif
365+
366+
#if ncnn_vendorID == 4318
367+
// here is the vendor specific code, 4318 is nvidia graphics
368+
#endif
369+
370+
#if ncnn_subgroupSize == 32
371+
// here is the code path optimized for subgroup_size == 32
372+
#endif
373+
374+
// use macro definitions
375+
uint size; // dynamic value from some previous routines
376+
if (size < ncnn_subgroupSize)
377+
{
378+
#if ncnn_supportedOperations & 4
379+
// subgroup support arithmetic
380+
#endif
381+
382+
#if ncnn_subgroup_arithmetic
383+
// shorthand style for checking subgroup arithmetic :P
384+
#endif
385+
}
386+
}
387+
```
388+
389+
### validation layer macros
390+
391+
ncnn will define some additional convenient macros when the vulkan validation layer enabled
392+
393+
* `ncnn_enable_validataion_layer`
394+
* `NCNN_LOGE`
395+
396+
currently, you have to modify the `ENABLE_VALIDATION_LAYER` definition at the beginning of `src/gpu.cpp` to `1` to enable these macros.
397+
398+
The `GL_EXT_debug_printf` extension will be enabled automatically without explicitly specifying it in your code.
399+
400+
```c
401+
void main()
402+
{
403+
int gx = int(gl_GlobalInvocationID.x);
404+
405+
#if ncnn_enable_validataion_layer
406+
NCNN_LOGE("gx = %d\n", gx);
407+
#endif
408+
}
409+
```
410+
411+
At runtime, `NCNN_LOGE` will print out the value of `gx`
412+
413+
### option macros
340414

341415
enable glsl extension only if user enable some options
342416

417+
The `GL_EXT_shader_16bit_storage` extension will be automatically enabled without explicit code indication when the device supports 16-bit storage and the user turns on `opt.use_fp16_storage`
418+
419+
The `GL_EXT_shader_explicit_arithmetic_types_float16` extension will be automatically enabled without explicit code indication when the device supports 16-bit arithmetic and the user turns on `opt.use_fp16_arithmetic`
420+
343421
```c
422+
void main()
423+
{
344424
#if NCNN_fp16_storage
345-
#extension GL_EXT_shader_16bit_storage: require
425+
// the user enable fp16 storage option and the device has fp16 storage support
346426
#endif
427+
347428
#if NCNN_fp16_arithmetic
348-
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
429+
// the user enable fp16 arithmetic option and the device has fp16 arithmetic support
349430
#endif
431+
}
350432
```
351433

352434
declare descriptor binding for image or buffer

src/gpu.cpp

+41-7
Original file line numberDiff line numberDiff line change
@@ -4925,6 +4925,14 @@ int compile_spirv_module(const char* comp_data, int comp_data_size, const Option
49254925
DD_APPEND_PROPERTY(requiredSubgroupSizeStages)
49264926
}
49274927

4928+
#if ENABLE_VALIDATION_LAYER
4929+
if (info.support_VK_KHR_shader_non_semantic_info())
4930+
{
4931+
device_defines.append("enable_validataion_layer", VK_TRUE);
4932+
custom_defines.append("NCNN_LOGE", "debugPrintfEXT");
4933+
}
4934+
#endif
4935+
49284936
#undef DD_APPEND_PROPERTY
49294937
}
49304938
else
@@ -5038,6 +5046,11 @@ int compile_spirv_module(const char* comp_data, int comp_data_size, const Option
50385046
{
50395047
custom_exts += "#extension GL_EXT_shader_explicit_arithmetic_types_float16: require\n";
50405048
}
5049+
#if ENABLE_VALIDATION_LAYER
5050+
{
5051+
custom_exts += "#extension GL_EXT_debug_printf : require\n";
5052+
}
5053+
#endif
50415054

50425055
// debug
50435056
// NCNN_LOGE("%s", define_macro_data.c_str());
@@ -5048,16 +5061,37 @@ int compile_spirv_module(const char* comp_data, int comp_data_size, const Option
50485061
glslang::TShader s(EShLangCompute);
50495062

50505063
// split shader source by token "#version 450\n"
5051-
int nversion = 0;
5052-
sscanf(comp_data, "#version %*d\n%n", &nversion);
5053-
if (nversion == 0)
5064+
int version_end_pos = -1;
50545065
{
5055-
NCNN_LOGE("shader source has no #version token");
5056-
return -1;
5066+
for (int i = 0; i < comp_data_size - 8; i++)
5067+
{
5068+
if (strncmp(comp_data + i, "#version", 8) != 0)
5069+
continue;
5070+
5071+
// #version shall be the very beginning or after newline
5072+
if (i != 0 && comp_data[i - 1] != '\n')
5073+
continue;
5074+
5075+
int nversion = 0;
5076+
sscanf(comp_data + i, "#version %*d\n%n", &nversion);
5077+
if (nversion == 0)
5078+
continue;
5079+
5080+
version_end_pos = i + nversion;
5081+
break;
5082+
}
5083+
5084+
if (version_end_pos == -1)
5085+
{
5086+
NCNN_LOGE("shader source has no #version token");
5087+
return -1;
5088+
}
5089+
5090+
// NCNN_LOGE("version_end_pos = %d", version_end_pos);
50575091
}
50585092

5059-
const char* comp_data_2 = comp_data + nversion;
5060-
int comp_data_size_1 = nversion;
5093+
const char* comp_data_2 = comp_data + version_end_pos;
5094+
int comp_data_size_1 = version_end_pos;
50615095
int comp_data_size_2 = comp_data_size - comp_data_size_1;
50625096

50635097
const char* comp_datas[4] = {comp_data, custom_exts.c_str(), define_macro_data.c_str(), comp_data_2};

0 commit comments

Comments
 (0)