Release notes

Changelog

Version 1.50.0


Released 02 Feb 2024
APIRegenerated the license keys used for initialization of the library
APIThe window.load event no longer waits for images loaded through CSS
APISamples for Microsoft UWP and GDK platforms now use the Microsoft Visual Studio 2022 toolset
APIPrebuilt Renoir rendering backends now use Microsoft Windows SDK 10 and the Microsoft Visual Studio 2022 toolset
APIUnityDeprecated View in favor of NativeView property of the CohtmlView component
APIRemoved the PreferCPUWorkload option from backend’s capabilities
APIRemoved the GLES2 support
APIRemoved the Shape Morphing support
APIChanged rendering backend’s capabilities to fit for the new command batching flow. Read more in the migration guide.
APIChanged shaders' vertex layout to fit for the new command batching flow. Read more in the migration guide.
APIAdded new commands in the rendering backend which need to be handled for the new command batching flow. Read more in the migration guide.
APIChanged constant buffers in the rendering backends to fit for the new command batching flow. Read more in the migration guide.
APIRemoved support for Microsoft XDK (aka Durango) SDK for Microsoft Xbox One consoles
FeatureAdded support for Touch and TouchEvent constructors for all platforms except UWP arm
FeatureAdded support for capturing a screenshot in the inspector and through the dev tools protocol
FeatureEnhanced batching of the rendering commands which combines the CPU and GPU workload and improves the efficiency. Check the migration guide.
FeatureTouchEvent.touches now contains information about all touches
FeatureThe Player application can now receive touch events on Microsoft Windows
EnhancementAdded resize logic for all samples using UI Composition, Surface Partitioning, and Backdrop Filter features
EnhancementAdded support for backface-visibility CSS style
EnhancementAdded support for GPOS kerning for fonts
EnhancementAdded partial support for SVG transform, width, height, and viewbox JavaScript properties
EnhancementUnreal EngineImproved the sample hub UI
EnhancementUpdated FreeType to version 2.13.2
EnhancementAdded GPU memory tracking to profiling output
EnhancementOptimized performance of border-image with SVG
EnhancementAdded support for sending input events to composited surfaces
FixFixed a deadlock when scratch textures caches are being cleared
FixFixed incorrect marking of scratch textures as not usable
FixFixed a crash when try to read an invalid FreeType face
FixFixed incorrect SVG clipping with clip-path and mask elements when using them in user space
FixFixed positioning of nested elements when using cohinline
FixFixed mouse events not firing correctly for cohinline elements
FixUnityFixed rendering problems with OpenGL and C# Backend in Unity
FixFixed leaking transformations when scaling SVGs to sizes smaller than 1 pixel
FixFixed a crash in the Player with HTTP requests on quit
FixFixed text nodes being 1 pixel larger then necessary that led to incorrect positioning when using right alignment
FixFixed missing texture when an image is used for only one frame
FixUnityFixed the errors encountered when the Samples were removed from the package
FixUnityFixed the backdrop filter texture format type in HDR mode
FixFixed requestAnimationFrame callbacks executing on the same frame
FixUnityFixed the OnGUI events input regression caused by the latest input performance upgrades in Input Manager mode.
FixPassing an empty string to textContent property won’t create empty text nodes
FixFixed cases where event listeners are not fired when other unrelated event listeners are removed
FixFixed excessive character vertical offset with certain fonts
FixFixed a crash caused by improper use of GIFs as background images
FixFixed a warning when setting the animation shorthand property to none
FixUnreal EngineFixed safe zone and letter boxing on the Apple iPhone devices
FixUnreal EngineRemoved forgotten experimental mentions from the documentation regarding Android and iOS platforms
FixUnreal EngineAddress accumulation of frames for painting when UMG Widgets are hidden or minimized
FixUnreal EngineFixed PlayerOverrides build issues
FixUnreal EngineFixed UE package unzipping issue with the native Windows File Explorer manager
FixFixed composition with custom effects
FixUnityFixed crashes when rapidly starting and stopping the Player in the Unity3D Editor
FixUnityFixed order of touch events in Unity3D when Input Manager is used
FixRemoved forgotten experimental mentions from the documentation regarding inline layout, complex text, and SDF on GPU features
FixUnityRemoved forgotten experimental mentions from the documentation regarding the C# backend feature
FixFixed a bug with upgrading cloned custom elements that prevented their lifetime callbacks to be invoked
FixThe inspector now shows the views for inspection only when they have a valid document loaded
FixFixed CSS calc functions failing when running with locale settings where the decimal symbol is not a dot
FixFixed a crash when clearing SVG surfaces caches
FixFixed invoking newly added event listeners during the dispatching of the event

What’s new

Rendering

Batching on Steroids

Overview

For the past months, we have been working on redesigning and improving the rendering flow in Renoir - the 2D library of Prysm. We’re excited to announce a significant enhancement of the batching system that will help you create a more stunning UI that runs faster than ever.

What are the benefits:

  • Up to 60% less rendering commands
  • Up to 30% faster on CPU
  • 33% less GPU memory for Vertex buffers
  • Up to 50% less GPU memory for Constant buffers

End of CPU workload support

Overview

With the introduction of the new rendering flow, we’ve decided to remove the CPU workload mode.

With that in mind, all resources and types connected to it are now removed. Such as:

  • All shaders that have *Batched* in their name
    • CohStandardBatchedVS.hlsl
    • CohStandardBatchedPS.hlsl
    • CohShadeGeometryBatched.ihlsl
  • All *Batched* shader types:
    • ST_StandardBatched
    • ST_StandardBatchedTexture
    • ST_BatchedText
    • ST_BatchedTextSDF
    • ST_BatchedTextSDFGPU
    • ST_BatchedTextMSDF
  • The member from the backend’s RendererCaps called PreferCPUWorkload is removed

Migration guide

Backend changed due to new rendering flow

Overview

One of the features we are excited to introduce is the new rendering flow, which allows us to batch the rendering commands more efficiently. Moreover, since we had 2 flows by now - GPU and CPU workloads, the new one will unify them by getting the good parts in both of them.

However, this feature required some modifications to the architecture of the rendering backends, which we will explain in this section.

Constant buffers
  • Removed all of the current constant buffers

  • Created 2 new ones instead:

    • Data_VS - an array of float4 used only in the Vertex stage
    • Data_PS - an array of float4 used only in the Pixel stage
  • Note: The size of the arrays might differ between rendering APIs. Check RenoirBackends/Common/ShaderConstants.inl - COH_VS_BUFFER_SIZE and COH_PS_BUFFER_SIZE.

Vertex Layouts

One of the objectives of the layout modifications is to minimize the amount of memory that each vertex consumes.

Previously, we have had 3 RGBA32_FLOAT attributes (Position, Color, Additional) for StandardVertex. Now it is:

  • The format of the Position is changed from RGBA32_FLOAT to RGB32_FLOAT
  • Added new attribute CBIndices which is RGBA8_UINT - here we’ll encode the offsets in constant buffers(Vertex & Pixel) for each geometry
  • Removed the attribute Color
Before (48 bytes):
const D3D11_INPUT_ELEMENT_DESC StandardVertexLayout[] =
{
  { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  { "TEXCOORD", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
New (32 bytes):
const D3D11_INPUT_ELEMENT_DESC StandardVertexLayout[] =
{
  { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },
  { "TEXCOORD", 0, DXGI_FORMAT_R8G8B8A8_UINT,      0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  { "TEXCOORD", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};

The vertex used for path rendering was only 1 RGBA32_FLOAT for Position but now, because of the constant buffers we need to pass additional data per instance which is in the CBIndices - a RGBA8_UINT attribute. There is no path vertex size change, however, now we create a new type of vertex buffer VT_SlimInstanceData for the instancing data and when we render paths we set 2 vertex buffer streams.

Old Path Vertex:

const D3D11_INPUT_ELEMENT_DESC SlimVertexLayout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, };

New Path Vertex:

const D3D11_INPUT_ELEMENT_DESC SlimVertexLayout[] =
{
  { "POSITION",               0, DXGI_FORMAT_R32G32B32A32_FLOAT,  0, 0, D3D11_INPUT_PER_VERTEX_DATA,   0 },
  { "VS_SEMANTIC_INSTANCED",  0, DXGI_FORMAT_R8G8B8A8_UINT,       1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 }, // the last param is the stream index
};

Due to the StandardVertex changes we need to introduce a new vertex used only for drawing SDF atlases called GlyphVertex:

const D3D11_INPUT_ELEMENT_DESC GlyphVertexLayout[] =
{
  { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },
  { "TEXCOORD", 0, DXGI_FORMAT_R8G8B8A8_UINT,      0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  { "TEXCOORD", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  { "TEXCOORD", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
Shaders
Decoding Constant buffer offsets

From the vertex layout explanation, we talked about the CBIndices attribute. To use it in the shaders we need to decode the information from it. Let’s see how we do that:

* The example for decoding in DX11. The code is taken from CohPlatform.ihlsl.

void decode(uint4 encoded, inout int vs_cb_offset, inout int ps_cb_offset, inout int ps_type) { // 0/x 1/y 2/z 3/w // [vs_cb] [vs_cb4|ps_cb4] [ps_cb] [ps_type]

vs_cb_offset = ((encoded[1] & 0xF) << 8) | encoded[0];
ps_cb_offset = (encoded[2] << 4) | ((encoded[1] & 0xF0) >> 4);
ps_type = encoded.w;

}

In each CBIndices attribute we have:

  • 12 bits for the offset in the vertex constant buffer
  • 12 bits for the offset in the pixel constant buffer
  • 8 bits for the pixel shader type by which we decide how exactly to shade the pixel
Backend commands

Two new backend commands are introduced which need to be handled:

  • BC_SetMultipleVertexBuffers
    • As we said earlier we set 2 buffers for the path rendering - 1 for the path data, 1 for the instancing
  • BC_DrawIndexedInstanced
    • To draw geometry using instancing - used for path rendering
Backend capabilities

With the new rendering pipeline, we made changes to the BackendCaps structure which fills the capabilities of the backend for specific graphics API.

  • Added properties:

    • PersistentConstantBuffersCount - This is the count of the constant buffer we’ll keep alive per Stage (Vertex and Pixel)
    • MaxRegistersForVertexConstantBuffer - The maximum count of float4 to be used in the constant buffer
    • MaxRegistersForPixelConstantBuffer - The maximum count of float4 to be used in the constant buffer
  • Removed properties:

    • ConstantBufferBlocksCount - Changed to PersistentConstantBuffersCount - The count of the constant buffers that will live through the whole lifetime of the library. If a scene uses more than that for a frame - they will be destroyed.
    • ConstantBufferBlockAlignment - The alignment now will be applied only when the buffer is being allocated, so we don’t need to pass it internally to Renoir.
    • SupportsSharedIndexBuffers - It was an optimization that reuses a sequence from the index buffer to more than 1 batch of rectangles. Now we can’t use it anymore because we batch more geometries that differ in their indices.
    • PreferCPUWorkload - The rendering flow that was designed mainly for mobile platforms, due to its more CPU and less GPU usage.
    • RequiresDrawFences - Hints that the API required explicit draw fences - it was unused
    • RequiresShaderTypeInShader - Tells if the user has set a shader mapping or not. Now it’s always true.
    • SupportsNPOTTextureOps - Tells if the backend supports linear sampling on NPOT texture - all supported graphics APIs are supporting that, so no there is no need to have it.

End of GLES2 support

Overview

We’ve decided to stop supporting GLES2 for a few reasons:

  • It is an old API and there are new which are more widespread and have better performance and support.
  • Its usage has declined. According to the Khronos Group, only 2% of mobile devices are shipped with GLES2 as a primary graphics API. This means that the vast majority of devices are with GLES or Vulkan.
  • Due to its limitations, we couldn’t implement some features or they were turning the complexity of the code into a burden.
  • The most known engines such as Unreal and Unity3D already dropped the support for them.
Limitations with Renoir
  • One of the vertex attributes (CBInides in the StandardVertex for example) is used for passing encoded values from the CPU to the GPU, so we need to transfer the same bytes to the GPU. When we bind the vertex attribute in GLES3 we use glVertexAttribIPointer, however, it’s not supported on GLES2, so we can’t pass the same bytes to the GPU which is breaking the decoding process.
  • For the path rendering we use instance drawing which is not supported on GLES2

End of Shape morphing support

Overview

This was a feature that the predecessor of the CSS SVG animations and it was in a custom format. Since now you can achieve the same with CSS we’ve decided to remove it.

The following shader types are removed:

  • ST_StencilAnimatedPathBezier
  • ST_StencilAnimatedPathTriangle