This PR adds basic support for texture update, read back and clearing
for Vulkan. In Vulkan we need to convert each data type ourselves as
vulkan buffers are untyped. Therefore this change mostly is about data
conversions.
Considerations:
- Use a compute shader to do the conversions:
- Leads to performance regression as compute pipeline can stall
graphics pipeline
- Lead to additional memory usage as two staging buffers are needed
one to hold the CPU data, and one to hold the converted data.
- Do inline conversion when sending the data to Vulkan using `eGPUDataFormat`
- Additional CPU cycles required and not easy to optimize as it the
implementation requires many branches.
- Do inline conversion when sending the data to Vulkan (optimized for CPU)
For this solution it was chosen to implement the 3rd option as it is fast
and doesn't require additional memory what the other options do.
**Use Imath/half.h**
This patch uses `Imath/half.h` (dependency of OpenEXR) similar to
alembic. But this makes vulkan dependent of the availability of
OpenEXR. For now this isn't checked, but when we are closer to
a working Vulkan backend we have to make a decision how to cope with
this dependency.
**Missing Features**
*Framebuffer textures*
This doesn't include all possible data transformations. Some of those
transformation can only be tested after the VKFramebuffer has been
implemented. Some texture types are only available when created for a
framebuffer. These include the depth and stencil variations.
*Component format*
Is more relevant when implementing VKVertexBuffer.
*SRGB textures*
SRGB encoded textures aren't natively supported on all platforms, in
all usages and might require workarounds. This should be done in a
separate PR in a later stage when we are required to use SRGB textures.
**Test cases**
The added test cases gives an overview of the missing bits and pieces of
the patch. When the implementation/direction is accepted more test cases
can be enabled/implemented.
Some of these test cases will skip depending on the actual support of
platform the tests are running on. For example OpenGL/NVidia will skip
the next test as it doesn't support the texture format on OpenGL, although
it does support it on Vulkan.
```
[ RUN ] GPUOpenGLTest.texture_roundtrip__GPU_DATA_2_10_10_10_REV__GPU_RGB10_A2UI
[ SKIPPED ] GPUOpenGLTest.texture_roundtrip__GPU_DATA_2_10_10_10_REV__GPU_RGB10_A2UI [ RUN ] GPUVulkanTest.texture_roundtrip__GPU_DATA_2_10_10_10_REV__GPU_RGB10_A2UI
[ OK ] GPUVulkanTest.texture_roundtrip__GPU_DATA_2_10_10_10_REV__GPU_RGB10_A2UI
```
Pull Request: blender/blender#105762
In Vulkan multiple commands can be in flight simultaneously.
These commands can share resources like descriptor sets or push
constants. When between commands these resources are updated
a new version of the resources should be created.
When a resource is updated it should check the submission id of the
command buffer. If this is different than last known by the resources,
the previous resources should be freed.
If the submission id is the same than previously it has to create a
new version of the resource to not intervene with other commands that
uses the resource before the update.
When the resource wasn't updated between multiple usages in the same
submission id it could reuse the previous resource.
This PR introduces a `ResourceTracker` and a `SubmissionTracker`.
A submission tracker can check if the command buffer is submitted.
In this case all resources of the resource tracker should be freed.
Unmodified resources in the same submission can be shared.
A resource tracker will keep track of all resources that are in
flight. After the resources are used (submission + execution) have
finished the resources can be cleared.
Pull Request: blender/blender#105183
This PR uses renderdoc for frame capturing when enabled.
It enabled an easier workflow for frame capturing.
- Capture GPU API calls from test cases
- Capture GPU API calls from background threads
- Capture GPU API calls from background rendering.
Renderdoc is an important GPU debugger used by the Eevee/
Viewport module. Previously we needed to change code in
order to record background rendering, that could on its own
lead to other side-effects.
The integration with renderdoc can be enabled using
`WITH_RENDERDOC=On` compiler option. `GPU_debug_capture_begin`
and `GPU_debug_capture_end` can be added to the section
of the code you want to debug. When running Blender inside
renderdoc this part will automatically be captured.
All GPU test cases are now guarded by these calls. In order
to capture the test cases you need to start the test cases
from renderdoc and the captured GPU API calls will appear
where each capture is a single test case.
Pull Request: blender/blender#105921
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: blender/blender#104424
Implement GBuffer prepass and deferred lighting (lights only).
This decouple lighting from the material shaders making them lighter,
less expensive and faster to compile.
Trying to keep a nice data flow so we could potentially use the
subpass programable blending feature on tiled GPU arch.
Not everything is covered yet and #105880 is making the GBuffer layout
a bit awkward and not easily extendable.
Pull Request: blender/blender#105868
This PR adds support for `GPU_storagebuf_clear` and
`GPU_storagebuf_clear_zero` to the Vulkan backend. It also adds test
cases for all backends.
Pull Request: blender/blender#105487
Adds two modes of GPU frame capture support for
enhanced debugging. GPU frame capture begin/end
allow instantaneous frame capture of all GPU commands
within the capture boundary.
GPU frame capture scopes allow several user-defined capture
regions which can wrap key parts of code. These scopes are
exposed to connected GPU tools allowing the user to manually
trigger a capture of a known scope at the desired time.
This is currently integrated with the Metal backend for
support with Xcode.
Related to #105591
Pull Request: blender/blender#105717
Fix race condition if several competing threads are inserting Metal
buffers into the MTLSafeFreeList simultaneously while a new list
chunk is being created.
Also raise the limit for an MTLSafeFreeListChunk size to optimize
for interactivity when releasing lots of memory simultaneously.
Authored by Apple: Michael Parkin-White
Pull Request: blender/blender#105254
Optimized node graphs do not get cached and were
not correctly freed once their reference count reached
zero, due to being excluded from the GPUPass garbage
collection.
Also suppress Metal shader warnings, which are prevalent
during material optimization.
Authored by Apple: Michael Parkin-White
Pull Request: blender/blender#105795
Metal buffer binding validation would trigger an error
when a given shader had an empty PushConstantBlock.
This patch removes the default uniform code gen if
no uniforms are present, to avoid any possible issues
with buffers being bound to a shader where the destination
data block is size zero.
Authored by Apple: Michael Parkin-White
Pull Request: blender/blender#105796
Crash when selecting objects on AMD platforms running
Metal. This was caused by shader compilation warnings
being treated as errors in macOS 10.15. Wrapping
compilation failure with success check resolves error.
Authored by Apple: Michael Parkin-White
Pull Request: blender/blender#105739
immDrawPixels performs significantly slower in Metal
than OpenGL. This was caused by two main factors. Firstly,
the additional overhead of tiled texture update, where all
memory needed to be kept in flight for each update, but
caused update to take a slow path. Avoiding tile update
with Metal is more efficient for both memory pressure
and GPU pipelining.
Secondly, on AMD platforms, the staging buffer used
for temporary texture data was page-faulting when
several texture updates would occur within one frame.
This is due to limitations of allocating one large contiguous
memory chunk. Using the Metal buffer pool for staging
data is more efficient.
Authored by Apple: Michael Parkin-White
Pull Request: blender/blender#105794
Create GPUNodeLinks for tiled_image and tiled_image_mapping together, to ensure they are the same texture.
See blender/blender#105661 (comment) for context and a more in-depth explanation.
Pull Request: blender/blender#105772
Skip explicit binding location for samplers in OpenGL when not needed, since drivers can usually handle more sampler declarations this way (as long as they're not actually used by the shader).
Pull Request: blender/blender#105770
Skip explicit binding location for samplers in OpenGL when not needed, since drivers can usually handle more sampler declarations this way (as long as they're not actually used by the shader).
Pull Request: blender/blender#105770
Fix support for Wireframe and parametric nodes by resolving
compilation failures surrounding barycentric coordinates.
A final missing part of the Metal implementation for barycentric
coordinates was missing.
Feedback also addressed to move barycentric calculation out
of code-gen and into surface_lib.
Authored by Apple: Michael Parkin-White
This also resolves#103606.
Ref #96261
Pull Request: blender/blender#105740
VKPixelBuffer is used by external render engines to allocate buffers
using the same GPU backend that Blender runs in.
In a later stage we should test what exact binding flags are needed. I
expect that it should be able to use as a transfer buffer to copy the
pixels over to a texture using transfer commands.
Pull Request: blender/blender#105741
The _gpu_ prefix is redundant as they are inside a namespace
and run as part of a test suite that already contain the name
gpu. (GPUOpenGLTest)
This patch also moved the texture test cases to its own
compile module.
When a shader is bound it should outlife the pipeline. In one
test case where only the shader data was accessed it also bound
the shader. This isn't needed as the shader data should be
retrieved without binding the shader.
This change fixes the issue by not binding the GPU shader.
Refactoring mesh code, it has become clear that local cleanups and
simplifications are limited by the need to keep a C public API for
mesh functions. This change makes code more obvious and makes further
refactoring much easier.
- Add a new `BKE_mesh.hh` header for a C++ only mesh API
- Introduce a new `blender::bke::mesh` namespace, documented here:
https://wiki.blender.org/wiki/Source/Objects/Mesh#Namespaces
- Move some functions to the new namespace, cleaning up their arguments
- Move code to `Array` and `float3` where necessary to use the new API
- Define existing inline mesh data access functions to the new header
- Keep some C API functions where necessary because of RNA
- Move all C++ files to use the new header, which includes the old one
In the future it may make sense to split up `BKE_mesh.hh` more, but for
now keeping the same name as the existing header keeps things simple.
Pull Request: blender/blender#105416
The previous API for clearing storage buffers was following the OpenGL
api. OpenGL has many options to support for data conversions, striding
and sizzling. Metal and Vulkan don't have these features and we have to
deal it ourselves.
Blender internally only uses a tiny subset for what is possible in
OpenGL. Making the current API to difficult to implement on our future
platforms as we had to implement all cases, most even not used at all.
By changing the API we make future development easier as we only need
to implement what we are actually using.
**New API**
`GPU_storagebuf_clear(GPUStorageBuf* ssbo, uint32_t clear_value)`
Related issue: #105492
Pull Request: blender/blender#105521
Both the shader_builder and existing shader tests eventually
tested the same aspects. shader_builder is more modern and
handles more cases.
The old shader test requires a full backend in order to run
This commit replaces the old tests to just use the
shader builder for validation.
Shader builder can still be run at compile time, this is
just a convenience to have as a test case as well for CI/CD.
Ref: #105482
It is recommended to map buffers once and not each time the
mapped memory is needed. This patch will map the buffer when
created and unmap the buffer when the buffer is freed.
This patch will reduce the overhead where the Vulkan driver or
the virtual memory manager needs to be accessed.
Pull Request: blender/blender#105588
This patch implements the bicubic interpolation option in the transform
nodes. The path merely reuse the code in the shader image texture and
adds bicubic variants to the domain realization shader.
Pull Request: blender/blender#105533
MTLFramebuffer's viewport was not correctly updated when
updating attachments. Behaviour modified to be consistent
with OpenGL.
Authored by Apple: Michael Parkin-White
Ref #96261
Pull Request: blender/blender#105529
**What are push constants?**
Push constants is a way to quickly provide a small amount of uniform data to shaders.
It should be much quicker than UBOs but a huge limitation is the size of data - spec
requires 128 bytes to be available for a push constant range.
**What are the challenges with push constants?**
The challenge with push constants is that the limited available size. According to
the Vulkan spec each platform should at least have 128 bytes reserved for push
constants. Current Mesa/AMD drivers supports 256 bytes, but Mesa/Intel is only 128
bytes.
**What is our solution?**
Some shaders of Blender uses more than these boundaries. When more data is needed
push constants will not be used, but the shader will be patched to use an uniform
buffer instead. This mechanism will be part of the Vulkan backend and shader
developers should not see any difference on API level.
**Known limitations**
Current state of the vulkan backend does not track resources that are in the
command queue. This patch includes some test cases that identified this issue as
well. See #104771.
Pull Request #104880