Commit Graph

50 Commits

Author SHA1 Message Date
Clément Foucault
16aee8efff Fix: #138928: Metal: Custom pyGPU shader has a compilation error in 4.4
This was caused by the removal of some compatibility code
in the metal backend.

This patch reintroduce this compatibility code in a cleaner
way than before.

This should be followed up by a documentation commit that
explains what is supported and what is not.

Pull Request: https://projects.blender.org/blender/blender/pulls/139185
2025-05-22 10:36:04 +02:00
Clément Foucault
c7c3ed9fbf GPU: Shader Preprocess: Assert pragma once in lib
This avoid forgetting to add `pragma once` inside
shader library files and have different include
behavior between C++ and shader code.
2025-05-19 09:20:31 +02:00
Clément Foucault
e1ac6a75d5 GPU: Shader Preprocess: Escape more character in regex strings
This is trying to fix a reported issue on some compilern with
regex not matching the template definitions
2025-05-19 00:07:40 +02:00
Clément Foucault
84298a8fd8 GPU: Shader Preprocess: Add error check for conditional include
These are not supported, so make it an error to use them.
2025-05-19 00:02:28 +02:00
Clément Foucault
2ce71fca18 GPU: Shader Preprocess: Add support for template inside namespaces
And also support for template definition on single line.
2025-05-16 11:01:07 +02:00
Clément Foucault
83a40ceae2 GPU: Shader Preprocess: Add support for BLI C++ vector functional swizzle
This allow to share more code between C++ and the shader
code base.

Pull Request: https://projects.blender.org/blender/blender/pulls/138820
2025-05-13 16:28:55 +02:00
Campbell Barton
5e75a9c1e8 Cleanup: spelling in comments 2025-05-11 17:00:47 +10:00
Clément Foucault
5055770f5b GPU: Shader: Add support for basic namespace through preprocessor
Allows basic support for using `namespace X {}` and `X::symbol`
syntax.

Benefit:
- More sharing possible with host C++ code.
- Isolation of symbols when including shader files as C++.

Requirements:
- Nesting must be done using `namespace A::B{}` rather than
  `namespace A{ namespace B {}}`, which is unsupported.
- No support for `using namespace`.
- Support of `using X` and `using X = Y` inside of function scope.
- Support of `using X` and `using X = Y` inside of namespace scope.
  However, this is only to bring symbols from the same namespace
  declared in another block (potentially inside another file).
- Only support namespace elision for symbols defined and used
  inside of the same namespace scope.

Note that this is currently limited to blender GLSL files and
not for the shared headers. This is because we need to port a lot
of code to use namespaces before allowing this.

### Follow Up:
Nesting like `namespace A{ namespace B {}}` shouldn't be hard to
support and could be added if needed.

Rel #137446

Pull Request: https://projects.blender.org/blender/blender/pulls/137445
2025-05-07 10:41:47 +02:00
Clément Foucault
c2dc45ce5e GPU: Shader: Add support for function default arguments
This avoid manual code duplication and readability issues.

This is implemented as simple copy pasting of the function
with the different argument count, calling the overload with
the next argument count for each overload.

A `#line` directive is added to each line make sure errors
still make sense and refer to the original line.

Example:
```cpp
int func(int a, int b = 0, const int2 c = int2(1, 0))
{
  /* ... */
}
```
Gets expanded to:
```cpp
int func(int a, int b, const int c)
{
  /* ... */
}
int func(int a, int b)
{
  return func(a, b, int2(1, 0));
}
int func(int a)
{
  return func(a, 0);
}
```

Rel #137446

Pull Request: https://projects.blender.org/blender/blender/pulls/138254
2025-05-06 15:25:16 +02:00
Clément Foucault
9bef8741a9 Fix: GPU: Shader Preprocess: Undefined behavior in variable_reference_mutation
This is because the `match` can be referenced by the
`report_error` callback. If the string is reallocated,
the callback could read freed memory.
2025-05-06 15:02:45 +02:00
Clément Foucault
2513fbedca GPU: Shader: Add support for references
Implementation of #137341

This adds support for using references to any variable in a local scope
inside the shader codebase.

Example:
```cpp
int a = 0;
int &b = a;
b++; /* a == 1 */
```
Using `auto` is supported for reference definition as the type is not
preserved by the copy paste procedure. Type checking is done by the
C++ shader compilation or after the copy paste procedure during shader
compilation. `auto` is still unsupported for other variable declarations.

Reference to opaque types (`image`, `sampler`) are supported since
they are never really assigned to a temp variable.

This implements all safety feature related to the implementation being
copy pasting the definition string. That is:
- No `--`, `++` operators.
- No function calls.
- Array subscript index needs to be int constants or constant variable.

The copy pasting does not replace member access:
`auto &a = b; a.a = c;` becomes  `b.a = c;`
The copy pasting does not replace function calls:
`auto &a = b; a = a();` becomes  `b = a();`

While limited, this already allows for nicer syntax (aliasing) for
accessing SSBOs and the potential overhead of a copy semantic:
```cpp
ViewMatrices matrices  = drw_view_buf[0];
matrices.viewmat = float4x4(1);
drw_view_buf[0] = matrices;
```
Can now be written as;
```cpp
ViewMatrices &matrices  = drw_view_buf[0];
matrices.viewmat = float4x4(1);
```
Which expands to;
```cpp
drw_view_buf[0].viewmat = float4x4(1);
```

Note that the reference semantic is not carried through function call
because arguments are transformed to `inout` in GLSL. `inout` has
copy semantic but it is often implemented as reference by some
implementations.

Another important note is that this copy-pasting doesn't check if a
symbol is a variable. It can match a typename. But given that our
typenames have different capitalizations style this is unlikely to be
an issue. If that issue arise, we can add a check for it.

Rel #137446

Pull Request: https://projects.blender.org/blender/blender/pulls/138412
2025-05-06 13:36:59 +02:00
Clément Foucault
41ed07d55e GPU: Shader: Add support for basic template support through preprocessor
Allows basic usage of templated functions.
There is no support for templated struct.

Benefit:
- More readable than macros in shader sources.
- Compatible with C++ tools.
- More sharing possible with host C++ code.

Requirements/Limitations:
- No default arguments to template parameters.
- Must use explicit instantiation for all variant needed.
- Explicit instantiation needs to **not** use argument deduction.
- Calls to template needs to have all template argument explicit
  or all implicit.
- Template overload is not supported (redefining the same template
  with different template argument or function argument types).

Currently implemented as Macros inside the build-time pre-pocessor,
but that could change to copy-paste to allow better error reporting.
However, the Macros keep the shader code reduced in the final binary
and allow different file to declare different instantiation.

The implementation is done by declaring overloads for each explicit
instantiation.

If a template has arguments not present in function
arguments, then all arguments **values** are appended to the
function name. The explicit template callsite is then modified to use
`TEMPLATE_GLUE` which will call the correct function. This is
why template argument deduction is not supported in this case.

Rel #137446

Pull Request: https://projects.blender.org/blender/blender/pulls/137441
2025-05-06 10:41:25 +02:00
Campbell Barton
fd6ac498b0 Cleanup: spelling in comments, strings (make check_spelling_*)
Also replace some triple-quoted non-doc-string strings with commented
blocks in examples.
2025-05-06 00:18:39 +00:00
Clément Foucault
f844ed7869 GPU: Shader Preprocess: Processing time optimizations
Guarding expensive regex computation by much
cheaper checks to reduce compilation time.

Compiling `time ninja -j 1 bf_draw_shaders`

On MacOS M1 Max (debug build with glsl_preprocess optimization turned on):
Before 13.01 sec
After  9.08 sec

Pull Request: https://projects.blender.org/blender/blender/pulls/138336
2025-05-05 15:14:16 +02:00
Clément Foucault
7aef8c2917 GPU: Shader Preprocess: Add utility to search for references
This utility will only match `&` character inside a
reference declaration. This is needed for speeding up the
regex matches.
2025-05-05 13:42:42 +02:00
Clément Foucault
74e6d2c575 GPU: Shader: Add support for basic loop unrolling through preprocessor
This adds basic unrolling support for 2 syntax:
- `[[gpu::unroll]]` which does full loop unrolling
- `[[gpu::unroll(x)]]` which unrolls `x` iteration

Nesting is supported.

This change is motivated by the added cost in compilation
and execution time that some loops have even if they have
compile time defined iteration counts.

The syntax is inspired by `GL_EXT_control_flow_attributes`.
However, we might want to have our own prefix to show it is
a blender specific feature and that it differs from the standard.
I propose `[[gpu::unroll]]`.

In the future, we could extend this to support more directives that
can be expanded to backend specific extension / syntax. This would
avoid readability issue an error prone copy paste of large amount
of preprocessor directives.

Currently, given that GL's GLSL flavor doesn't support
any of these attributes, the preprocessor does some copy-pasting
that does the unrolling at the source level. Note that the added
`#line` allow for correct error logging.

For the `[[gpu::unroll]]` syntax, the `for` declaration
needs to follow a specific syntax to deduce the number
of loop iteration.
This variant removes the continue condition between iteration,
so all iterations are evaluated. This could be modified
using a special keyword.

For the `[[gpu::unroll(n)]]` syntax, the usercode needs
to make sure that `n` is large enough to cover all iterations
as the loop is completely removed.
We could add shader `assert` to make sure that there is
never a remaining iteration.
This behavior is usually different from what you see in other
implementation as we do not keep a loop at all. Usually, compilers
still keep the loop if it is not unrolled fully. But given we don't
have IR, this is the best we can do.

`break` and `continue` statement are forbidden at the unrolled loop
scope level. Nested loop and switch can contain these keywords.
This is accounted for by checks in the pre-processor.

Only `for` loops are supported for now. There are no real
incentive to add support for `while` given how rare it is
in the shader codebase.

Rel #137446

Pull Request: https://projects.blender.org/blender/blender/pulls/137444
2025-05-05 13:37:51 +02:00
Clément Foucault
a14fa6bfe5 GPU: Shader Preprocess: Add string utilities
Allow faster and more robust parsing / mutation.
2025-05-05 11:03:36 +02:00
Miguel Pozo
f24ad7a470 Build: Add WITH_OPTIMIZED_BUILD_TOOLS
Enable optimizations on Debug builds for executables used for the build
process (datatoc and glsl_preprocess) and enable unity builds for
shader preprocessing targets.

Debug: From 28.9s to 5.7s
Release: From 4.9s to 3.5s

Pull Request: https://projects.blender.org/blender/blender/pulls/138274
2025-05-02 18:33:44 +02:00
Clément Foucault
d24b0e4a4e GPU: Remove runtime parsing of GLSL source
See #129009 for context.

The preprocessor parses metadata and writes a header file containing
an inline function that inits the `GPUSource` with the metadata.

These header files are then included inside `gpu_shader_dependency.cc`.

This still keep the usage of the `metadata` enums and classes to avoid
pulling the whole blender module inside the preprocessor executable.

This speeds-up startup time in Debug build:
`gpu_shader_dependency_init`
- Before : 37ms
- After : 4ms

I didn't measure release, but it is unlikely to be noticeable (in the
order of 4ms > 1ms).

Pull Request: https://projects.blender.org/blender/blender/pulls/138070
2025-04-29 15:32:36 +02:00
Clément Foucault
0f71bb6c71 GPU: Rename shader_shared.h files to .hh
This makes more sense now that everything is C++.
2025-04-16 20:26:48 +02:00
Clément Foucault
a6fa1b5969 DRW: Rename common_*_lib.glsl to follow module prefix 2025-04-16 20:19:09 +02:00
Clément Foucault
6048a7a765 GPU: Preprocessor: Allow function argument to be references
Pull Request: https://projects.blender.org/blender/blender/pulls/137612
2025-04-16 19:42:27 +02:00
Clément Foucault
50dc6c0060 GPU: Preprocessor: Make source type extension convert to enum type
This allow to clearly define what type of preprocessing to
apply to which file type.
2025-04-16 19:41:51 +02:00
Clément Foucault
3b3a5731df GPU: Shader: Change vector and matrix type to use blender convention
This unify the C++ and GLSL codebase style.

The GLSL types are still in the backend compatibility
layers to support python shaders. However, the C++
shader compilation layer doesn't have them to enforce
correct type usage.

Note that this is going to break pretty much all PRs
in flight that targets shader code.

Rel #137261

Pull Request: https://projects.blender.org/blender/blender/pulls/137369
2025-04-14 13:46:41 +02:00
Campbell Barton
b85fc32cae Cleanup: spelling & repeated words in comments
Address warnings from check_spelling.py
2025-03-06 10:33:21 +11:00
Campbell Barton
600f803922 Cleanup: pass string as a const reference 2024-11-26 12:41:29 +11:00
Clément Foucault
29b3df7504 GPU: GLSL compilation as C++ for draw intern shaders
Allow compilation of shaders using C++ for linting and
IDE support.

Related #127983

Pull Request: https://projects.blender.org/blender/blender/pulls/130193
2024-11-13 12:32:39 +01:00
Clément Foucault
5c80fb17e0 GPU: Add support for shader assert
This allows to use `assert()` directly inside shader source.

The current implementation is just replacing it with a printf
that gives some information about the location of the assert.

It is not that much more helpful than a printf with a condition.
What is useful is that they are disabled by default. So they
can be sprinkle around and only turned on during debugging.

Adding shader name inside the assert report is not trivial and
could be added later (the shader name is only known at compile
time which is too late for string parsing).

Adding which drawcall produced the assert isn't trivial either.
It would require flushing the printf buffer for each drawcall
which might force synchronization and remove bugs.

Pull Request: https://projects.blender.org/blender/blender/pulls/129728
2024-11-06 20:29:01 +01:00
Clément Foucault
f38827802a Fix: GPU: Broken shader printf support
Was using wrong type of data offset and not removing
the quote when outputing the strings.
2024-10-16 17:01:17 +02:00
Campbell Barton
5a561c6aeb Cleanup: spelling in comments 2024-10-16 21:10:49 +11:00
Clément Foucault
c91baf1cdd GPU: GLSL Preprocess: Avoid parsing includes as string
Remove them before string parsing
2024-10-16 10:30:35 +02:00
Clément Foucault
4ba944b15a GPU: GLSL Preprocess: Always remove quotes
We cannot do this for the MSL files. Also
they are written in MSL which should not be
processed. So use datatoc for them.

Also add quote linting for GLSL files.
2024-10-16 09:08:51 +02:00
Clément Foucault
7110890b09 GPU: GLSL preprocessor: Only do function parsing on library files 2024-10-16 09:08:51 +02:00
Clément Foucault
fcae6f2fc4 Fix: GPU: GLSL preprocessor not using binary output stream
This was adding a lot of CLRF newlines on windows which
in turn caused the new runtime parsing to fail.
2024-10-15 22:56:32 +02:00
Clément Foucault
39d5013c6e GPU: Use filename hash for line directive instead of path
This ensures same values on all systems.
2024-10-15 22:26:08 +02:00
Clément Foucault
c1f4394b14 GPU: Use 32bit hash in static_strings_suffix
Also make sure to use stoul for parsing it.
2024-10-15 22:26:08 +02:00
Clément Foucault
c41326a296 Cleanup: GPU: GLSL Preprocessor: Use raw strings and remove template 2024-10-15 20:16:45 +02:00
Clément Foucault
cf9da6f642 GPU: Move global scope constant linting to preprocessor
# Conflicts:
#	source/blender/gpu/glsl_preprocess/glsl_preprocess.hh
2024-10-15 20:16:45 +02:00
Clément Foucault
62826931b0 GPU: Move more linting and processing of GLSL to compile time
The goal is to reduce the startup time cost of
all of these parsing and string replacement.

All comments are now stripped at compile time.
This comment check added noticeable slowdown at
startup in debug builds and during preprocessing.

Put all metadatas between start and end token.
Use very simple parsing using `StringRef` and
hash all identifiers.

Move all the complexity to the preprocessor that
massagess the metadata into a well expected input
to the runtime parser.

All identifiers are compile time hashed so that no string
comparison is made at runtime.

Speed up the source loading:
- from 10ms to 1.6ms (6.25x speedup) in release
- from 194ms to 6ms (32.3x speedup) in debug

Follow up #129009

Pull Request: https://projects.blender.org/blender/blender/pulls/128927
2024-10-15 19:47:30 +02:00
Campbell Barton
aa6742897e Cleanup: spelling in comments 2024-10-15 16:22:38 +11:00
Campbell Barton
bd299cad72 Cleanup: quiet unused argument warnings 2024-10-14 12:12:20 +11:00
Clément Foucault
191b347f58 Cleanup: GPU: Use function parameters instead of template 2024-10-12 14:21:51 +02:00
Clément Foucault
d9aad850b0 GPU: GLSL preprocess: Remove invalidly processed header
Add assert in the preprocessor that these file don't get
processed.
2024-10-12 14:21:51 +02:00
Clément Foucault
1c0247c871 Cleanup: GPU: Preprocessor: Use report callback on processing functions 2024-10-11 18:52:34 +02:00
Clément Foucault
300ea9f083 GPU: GLSL: Strip comment at compile time
This speeds up the preprocessor and
will allow for faster load time.

# Conflicts:
#	source/blender/gpu/glsl_preprocess/glsl_preprocess.cc
2024-10-11 11:15:52 +02:00
Campbell Barton
f3c2deac3e Cleanup: replace U+00A0 with space
Using ASCII space is sufficient in source.
2024-10-09 16:34:39 +11:00
Campbell Barton
2e881eacd1 Cleanup: spelling in comments 2024-10-08 09:54:29 +11:00
Clément Foucault
9c0321ae9b Metal: Simplify MSL translation
Move most of the string preprocessing used for MSL
compatibility to `glsl_preprocess`.

Enforce some changes like matrix constructor and
array constructor to the GLSL codebase. This is
for C++ compatibility.

Additionally reduce the amount of code duplication
inside the compatibility code.

Pull Request: https://projects.blender.org/blender/blender/pulls/128634
2024-10-07 12:54:10 +02:00
Clément Foucault
7e5bc58649 GPU: Change GLSL include directive
This changes the include directive to use the standard C preprocessor
`#include` directive.

The regex to applied to all glsl sources is:
`pragma BLENDER_REQUIRE\((\w+\.glsl)\)`
`include "$1"`

This allow C++ linter to parse the code and allow easier codebase
traversal.

However there is a small catch. While it does work like a standard
include directive when the code is treated as C++, it doesn't when
compiled by our shader backends. In this case, we still use our
dependency concatenation approach instead of file injection.

This means that included files will always be prepended when compiled
to GLSL and a file cannot be appended more than once.

This is why all GLSL lib file should have the `#pragma once` directive
and always be included at the start of the file.

These requirements are actually already enforced by our code-style
in practice.

On the implementation, the source needed to be mutated to comment
the `#pragma once` and `#include`. This is needed to avoid GLSL
compiler error out as this is an extension that not all vendor
supports.

Rel #127983
Pull Request: https://projects.blender.org/blender/blender/pulls/128076
2024-10-04 15:48:22 +02:00
Clément Foucault
0bfd5e3536 GPU: Add GLSL preprocessor
This splits the GLSL processing into its own file
as it will grow in complexity.

Removes the complexity from `datatoc` and chain them
during the build process.

Rel #128076

Pull Request: https://projects.blender.org/blender/blender/pulls/128261
2024-10-04 11:33:21 +02:00