Progress Update: June 2019


#1

Hello everyone, June has passed and it’s time for another progress update!

This month was primarily focused on finishing up the development of MoltenVK integration, which took up most of my time. I’m happy to say this has been pretty much wrapped up and both the framework and the editor will now run using Vulkan backend on macOS!

Secondary focus was bug fixing in order to get editor into stable state. Over 35 various bugs were resolved, including a multiple serious bugs regarding async scene import and async scene loading. Editor has also been enhanced with a few Material-related improvements to the inspector, and Decal support is now also fully integrated and working.

Aside from that I did an overhaul of the framework’s logging system, added a bunch of enhancements to the shading language and improved framework’s entry point handling.

Read below for more details.

Highlights

MoltenVK support

Last month we’ve started work on adding support for Vulkan on macOS, in order to resolve some issues with OpenGL, and also get rid of the limitations of the old OpenGL 4.1 version used by the OS.

I’m happy to announce that this work is now pretty much done! All the bsf examples now run on Vulkan, as well as the editor itself. I’m certain there are still minor issues to resolve but those will be handled on a per-issue basis, and shouldn’t be taking any major amounts of my time.

Aside from letting us use the full power of the renderer on macOS, and saving time when implementing new rendering effects, this also makes the framework one big step closer to supporting iOS devices!

New logging system

The logging system received a complete overhaul, replacing current LOGWRN, LOGERR, etc. messages with a single unified BS_LOG macro. A new logging call might look like this:

BS_LOG(Error, RenderBackend, "Cannot set parameter block buffer with the name '{0}'.", lockInfo.name);

The advantages of the new system are:

  • More verbosity options. While previously you could only choose between Debug, Warning and Error, you now have 7 different options provided by the LogVerbosity enum, which can be easily extended with more. This means we can add more error logging messages at higher verbosity, without having to worry about spamming the console/terminal, ultimately helping with tracking down issues.
  • Compile-time verbosity. By setting BS_LOG_VERBOSITY macro you can compile the framework with only certain level of verbosity, completely eliminating logging calls of higher verbosity, ensuring no performance impact due to extra logging calls in debug mode.
  • Categories! Each logging call can now have a category, which in most cases specifies from which system it came from. This allows you to selectively filter what kind of logging messages are you interested in, as well as to add your own categories for organizing user-made logging messages. I’ve went through all the existing logging calls and categorized them already!
  • Built-in support for string formatting. The macro now supports string format {0} parameters by default, which means a much less verbose syntax when adding such parameters as there’s no need to explicitly convert them to strings, as well as more readable code.

BSL enhancements

BSL received a number of enhancements, both in functionality and usability.

[name] attribute
Shader parameters can now be given a pretty name. This name will be used for display in the inspector, rather than using the variable name, resulting in a prettier display in the inspector.

// Texture will be displayed as just "Opacity" in editor inspector
[name("Opacity")]
Texture2D gOpacityTex = white;

[hideInInspector] attribute
So far shader parameters could be marked as [internal] which would hide them from user-space completely. However sometimes it is useful to hide the parameter from the inspector, but still allow it to be set from code. This can now be done by using the [hideInInspector] attribute.

cbuffer Params
{
	// Allow the user to customize this parameter, but don't show in inspector
	// as it might be confusing to set for non-coders
	[hideInInspector]
	float gInvDepthRange = 1.0f;
};

Named variations
Variations and their values can now be given names using the new [name] attribute. These names will be reported by the new variation reflection system described below.

[name("Blend mode")]
BLEND_MODE = 
{ 
	[name("Transparent")] 0, 
	[name("Stain")] 1, 
	[name("Normals")] 2, 
	[name("Emissive")] 3 
};

Variation reflection
Shader API has been extended with Shader::getVariationParams() method, which returns an array of ShaderVariationParamInfo objects. These objects can be used for determining all variation parameters that a shader supports, their names and their possible values. This functionality is used by the variation inspector feature below.

Variation inspector
Editor’s Material inspector will now display user-space shader variations, allowing you to change which shader variation to use directly from the editor GUI. This is currently used for the Decal shader, which supports a variety of blend modes such as stain or normal-only.

Ultimately this can be used by users to create uber-shaders while ensuring shader properties can be toggled purely from the inspector.

Variations
Auto-generated variation paramater picker in the inspector

To make the variation display in the inspector, use the new [show] attribute. Without this attribute the variation is assumed to be internal and used by the renderer (which is the case for most variations).

[name("Blend mode"),show]
BLEND_MODE = 
{ 
	[name("Transparent")] 0, 
	[name("Stain")] 1, 
	[name("Normals")] 2, 
	[name("Emissive")] 3 
};

Per-warp memory barriers
If you’ve worked with compute shaders you might be familiar with memory and execution barriers within a single compute group. More recently we’ve also seen shading languages introduce support for memory barriers specific to a single warp (or as they’re also known: wavefront, subgroup or SIMD-group depending on the vendor/backend).

These are now supported by BSL! They are faster to execute than normal group barriers if you know that your code will only be sharing data within a single warp.

This is done through new commands:

  • WarpGroupMemoryBarrier
  • WarpDeviceMemoryBarrier
  • WarpAllMemoryBarrier
  • WarpGroupMemoryBarrierWithWarpSync
  • WarpDeviceMemoryBarrierWithWarpSync
  • WarpAllMemoryBarrierWithWarpSync

They are similar to Group operations provided by HLSL, but apply only to a warp subset of the group. Internally these are implemented as subgroup memory barriers in GLSL and SPIR-V, and SIMD-group memory barriers on MSL.

New entry point

From now on all the framework code should be executed from the bs_main entry point. This entry point is defined in BsEntry.h which you should include in your application and use as a replacement for main and WinMain. bsfExamples on the develop branch have been updated to use the entry point, and introductory manuals have been updated as well.

This entry point has a couple of advantages:

  • It requires no preprocessor per-platform macros. So far all the examples had to have #if checking for WinMain on Windows or main on Linux/macOS. New entry point completely hides this.
  • Running the framework on a custom thread. If we need to, the framework can be started on a worker thread, without the user ever knowing about it. This is useful for macOS which can sometimes require rendering to happen on the main thread. For example the new BS_CORE_THREAD_IS_MAIN can be used to perform rendering on the main thread, while your code runs on a secondary thread.

For now you can still use the old approach as well, but it is suggested to upgrade because if we ever enable feature such as BS_CORE_THREAD_IS_MAIN your code will break.

Minor features

Framework

  • Material variations can now be set from C#
  • Added a RTTIPlainType specializaton for SmallVector
  • Custom search paths can now be added for shader includes
  • Exposed SceneObject.hasFlag method to C# - by @jayrulez
  • Shader reflection now reports underlying buffer/texture per-pixel formats
  • Updated to Vulkan 1.1 API
  • Blit shader can now be used for downsizing, instead of just copying and resolving samples
  • PixelData now stores row & slice pitch in bytes, rather than pixels, ensuring it can be easily used for various compressed formats
  • OpenGL backend now supports setting blend & color mask options on a per-target basis

Editor

  • Material variations can now be changed from the inspector
  • Added Decal scene gizmo
  • Decal blending type can now be toggled from its Material inspector
  • Decals are now fully functional in the editor

Decals
Decals being set up in the editor

Bugfixes

Framework

  • Use of multiple descriptor sets now works properly in Vulkan
  • Reduced threadgroup size for indirect specular tiled deferred shader, as it was too large for macOS
  • Cross-compiler updated so it emits less pessimistic memory barriers, significantly increasing performance on certain hardware under OpenGL/Vulkan
  • Fixed memory corruption due to invalid handling of arrays of structs in material params
  • Fixed a nasty threading issue that made command queue block operation not to block when requested
  • Fixed animation curve splitting not working properly with a single-keyframe curves, causing invalid animations
  • Fix script binding generation for struct interop objects containing arrays of other struct interop objects
  • Independant blend for multiple render targets is now parsed properly in BSL
  • gMaskTex parameter in Decal shader is now correctly marked as internal, hiding it from user-space
  • Decal shader blend modes are now properly applied
  • Fixed a crash when changing Decal material
  • Fixed a crash when attempting to use a non-decal material with the Decal component
  • Flipped decal Y axis so it matches the texture along its local XY axes
  • GPU sort unit test now runs properly on Vulkan
  • Updated Decal shader so it doesn’t exibit artifacts on Metal due to use of discard
  • Fixed BSL compiler not reporting an error if an include file cannot be found
  • Binding null (dummy) textures & buffers in Vulkan will now correctly register them with the command buffer and therefore issue layout transitions and relevant memory barriers
  • Fixed resource listener callbacks triggering on non-main thread, causing potential race conditions
  • Fixed resource dependency queries not being thread safe
  • Asset import tool can now properly process built-in assets for the editor
  • Fixed a deadlock when many resources are being loaded and all end up waiting for other resources, using up all scheduler threads
  • Mesh and texture core thread readbacks should not trigger submits for other threads
  • Decal size no longer returns size * scale instead of just local size
  • Fixed a crash when attempting to use a non-native texture format on Vulkan
  • Fixed sprite texture not being properly initialized, causing animated GUI textures to render incorrectly
  • Single-threaded rendering path can now be compiled once again
  • Fixed a threading issue that was causing secondary windows to render as blank on macOS
  • Fixed memory corruption on GUIElement destruction, due to incorrectly set update parents
  • Fixed helper GPU frames not freeing GPU profiler samples
  • When reading texture data on DirectX backend, respect the returned row and slice pitch
  • Fixed read-back from render textures on Vulkan failing due to invalid layout
  • Fixed a crash when creating a 0-sized texture on OpenGL
  • Fixed NDC->Screen space conversion working incorrectly when running with Vulkan

Editor

  • Fixed a crash when scene picking an object with a not-yet-loaded material
  • Deleting last entry in a GUI int or float field will no longer immediately insert a 0 instead of keeping the field empty
  • Improved texture preview functionality that now works with compressed texture formats
  • Fixed a variety of threading issues causing hangs and crashes during scene loading and/or resource import

What’s next?

Feature-wise I’ve started work on new rendering effects. I mentioned last month we’re changing the roadmap a bit, so that v1.2 will include rendering effects as well as a networking system. These effects will include all kinds of modern rendering enhancements including stuff like temporal AA, bokeh depth of field, subsurface scattering and a lot more. You should be seeing the first of these rendering effects in July.

I’m also continuing work on editor bugs. This month was a big one in terms of high priority bugs solved, and there are just a few major ones remaining. On top of that MoltenVK supports means editor macOS support is also sorted. As we move onto lower priority bugs those should also be easier and faster to solve, so they might get wrapped up quickly. Although I’m sure users will find new major issues for me to fix!

I’ll continue work on networking once I wrap up the next editor update, which won’t be in July, but it’s getting a lot closer. It’s been moved a bit off track due to some new projects we’ve been involved in, and a new focus on framework’s features, rather than on editor bugs.

That’s it for now, stay tuned! And a special thanks for all the patrons on Patreon!


How to Use Editor?