Migrate OpenGL Shaders to Vulkan. #89525
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
14 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#89525
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal of this task is to convert all OpenGL shaders to Vulkan shaders. When using an OpenGL backend the syntax will be parsed and converted back to an OpenGL shader.
Numbers
Blender has
NOTE: There might be some python shaders or internally shaders that we haven't counted here.
NOTE: Overlay, workbench engine show a worst case scenario where each shader config generates different shaders. In reality only a subset would only create a different shader.
NOTE: Eevee2 isn't taken into account as it is still in development, but is expected to land before Vulkan port. As we want to perform the shader migration in master we should not convert any eevee shaders yet.
NOTE: Eevee2 shader layout is already organized to migrate to uniform to buffers.
Approach
The idea is to do this migration in master this way any changes in the shaders should be done in the Vulkan syntax and reducing the risk of branches to get out of sync.
Changes
See https://github.com/KhronosGroup/GLSL/blob/master/extensions/khr/GL_KHR_vulkan_glsl.txt for an overview of the changes.
There is a relax version https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GL_EXT_vulkan_glsl_relaxed.txt that is added for better compatibility with OpenGL shaders. It does not match our approach where vulkan GLSL syntax is leading.
NOTE: This list isn't complete and the implications still needs to be discussed.
Builtin Uniforms
Blender auto binds common matrices to shaders. We should check how many different combinations are actually using
uniform mat4
. Create structs for the common combinations and lazy initialize these combinations.Draw manager already separates matrices into a viewBlock and a modelBlock. We could reuse a similar approach.
NOTE: See https://docs.google.com/spreadsheets/d/1JtE4lLJxg6faANZgz8PGFVQTm0a64wmrENiGxgNP0iI/edit?usp=sharing for some analysis on usage and grouping.
A common used configuration is
This could be converted to (is already done in draw manager but more complex as it supports instances)
Approach would be to extract the type info from the source
layout(binding = 1) uniform <structurename> {
Grouping of the uniforms into common structs:
NOTE:Grouping is based on actual usage after linking. It could be that a shader needs to support multiple groups when it is used in multiple configurations.
CPP
Vulkan GLSL
OpenGL GLSL
ID => Index
In Vulkan syntax the
gl_VertexID
has been renamed togl_VertexIndex
. These kind of changes will be send in for review one a by one basis for all shaders. These changes have low risk, are easy to do. See 44c875f59a as an example.Same should be done for
gl_InstanceID
Name Attachments
OpenGL queries binding location of shader elements based on its name. In vulkan this is done based
layout
keyword of the shader element see Description sets in the vulkan specification.Unclear how to handle these yet. One idea is to preprocess the shader source to extract the names binding map so we can still support name lookup.
Builtin uniforms
In vulkan uniforms cannot be addressed individually. They should become part of a buffer. Precise details how to organize these buffers isn't clear yet.
To keep the structures up to date we should be able to share the code between GLSL and C/CPP.
Changed status from 'Needs Triage' to: 'Confirmed'
Added subscriber: @Jeroen-Bakker
Added subscriber: @2046411367
Added subscriber: @RC12
Added subscriber: @fclem
Another thing to not forget is how does one updates a pyGPU shader to this version.
To me, one would not have to re-declare the builtin uniforms and just have to group uniforms into a uniform buffer.
I would prevent the use of push constant for now in order to avoid more complexity.
However, this means that UBO management from the pyGPU needs to be improved.
Added subscriber: @ckohl_art
Added subscriber: @GeorgiaPacific
Added subscriber: @Gilberto.R
Added subscriber: @Defka
Added subscriber: @newin
I just spend a bit of time trying to figure out different options to support both Vulkan and OpenGL in the layout binding issue (which is kind of mixed with https://developer.blender.org/T89684).
The probably most ubiquitous way of doing this would be to wrap uniform declarations into macros that can be both parsed to extract those names and expanded into different forms depending on the target version.
Even though I've seen this fairly often it very often it tend to produce code quite unpleasant to read very fast + add a parser that can be the source of bug and add maintenance work and all. It certainly an option but I'm not a fan of this direction.
The other well-known way to handle that would be to do exactly the opposite: generate uniforms on the fly just before the shader compilation. It may be a good idea from a software design perspective (everything is automatically consistent + no parsing involved) in reality this is relatively impractical to have piece of the code missing when working on shaders. (Unreal does that a lot and that's always very annoying). That being said I've only looked at static shaders and not materials, maybe materials already do that and it would be possible to use that to all shaders.
The last would be to have a very simple set of "compatibility layer" macros (probably just a few
#define
inglsl_patch_default_get()
) then use with the standard reflection features for opengl and add SPIRV-Reflect as a dependency for vulkan. The whole strategy would be to build a simple wrapper that would get/set those values in some generic way.For game development I wouldn't advise the last (because of performance and portability reasons) but for blender I think it's both elegant and simple and the perf impact should be a very big deal.
Problem is: it will add a dependency of something under Apache Version 2.0 Licence and I have no idea if I can (or even should) do that.
Should I go ahead and add the dependency ?
PS: There is probably another option based on explicit binding/layout locations but as it would require OpenGL 4+ I haven't spend much time on this front. I'm sure OpenGL 3.3 as minimal has been chosen for a good reason.
Added subscriber: @Emi_Martinez
Added subscriber: @dodo-2
Added subscriber: @Jarrett-Johnson
@newin Thank you for your feedback. I did not thought about generating the interface at runtime. In fact, this is what we now are considering to do. This has benefits even if it makes shader harder to read:
We are already fragmenting our shaders to share code (i.e: stage interfaces) so I don't see fragmentation as a big issue.
The ugly side of this is that we would have to create a pyGPU API for addons to create shaders this way.
One major drawback is that it needs manual effort to write down the interface. But for simple internal shaders, it could be automated.
I've push an experimental branch called
gpu-shader-descriptor
where there is a proof of concept implementation of what I had in mind. Also see D13360 for discussion about the implementation.Added subscriber: @Spundun-Bhatt
I was trying to figure out what's the work to be done for this task... I noticed that a lot of work has already gone into this with...
Is there anything else in scope for this task? I'm looking for starter projects that'd help me familiarize with the Vulkan API.
ps: Left some more details about my investigation of the work done here: #94975#1377420
@Spundun-Bhatt, yes we had to do the conversion already for the metal backend. Changes in eevee still needs to be done, but that will only be done for eevee-next. Will mark this task complete.
Hmmm... it can be a hard task to familiarize with Vulkan when introducing it in a project like Blender. The next step would be to implement the VKShader. That requires shaderc and other changes that are in the tmp-vulkan branch.
Note that the tmp-vulkan branch hasn't been updated for at least 6 months...
Changed status from 'Confirmed' to: 'Resolved'
Added subscriber: @bergjones
After merging a relatively recent blender (within the past month) and tmp-vulkan I cannot get the gpu_shader_create_info_compile_all to work when compiling to spv. For example, the "vertex_out_interfaces_" portion of vertex_interface_declare gives
when I need
A similar situation for the "Push Constants" which for example give
when I need
Maybe I may be missing something., but I cannot convert even simple shaders like 2d_flat_color. What I just did was in GPU_SHADER_CREATE_INFO added "vertex_out_VK" function and make it behave similar to vertex_in. I am working on making the push constants like MVP behave like UBO as well.