Release notes
On this page
Changelog
Version 1.50.0
Released 02 Feb 2024
API | Regenerated the license keys used for initialization of the library |
API | The window.load event no longer waits for images loaded through CSS |
API | Samples for Microsoft UWP and GDK platforms now use the Microsoft Visual Studio 2022 toolset |
API | Prebuilt Renoir rendering backends now use Microsoft Windows SDK 10 and the Microsoft Visual Studio 2022 toolset |
APIUnity | Deprecated View in favor of NativeView property of the CohtmlView component |
API | Removed the PreferCPUWorkload option from backend’s capabilities |
API | Removed the GLES2 support |
API | Removed the Shape Morphing support |
API | Changed rendering backend’s capabilities to fit for the new command batching flow. Read more in the migration guide. |
API | Changed shaders' vertex layout to fit for the new command batching flow. Read more in the migration guide. |
API | Added new commands in the rendering backend which need to be handled for the new command batching flow. Read more in the migration guide. |
API | Changed constant buffers in the rendering backends to fit for the new command batching flow. Read more in the migration guide. |
API | Removed support for Microsoft XDK (aka Durango) SDK for Microsoft Xbox One consoles |
Feature | Added support for Touch and TouchEvent constructors for all platforms except UWP arm |
Feature | Added support for capturing a screenshot in the inspector and through the dev tools protocol |
Feature | Enhanced batching of the rendering commands which combines the CPU and GPU workload and improves the efficiency. Check the migration guide. |
Feature | TouchEvent.touches now contains information about all touches |
Feature | The Player application can now receive touch events on Microsoft Windows |
Enhancement | Added resize logic for all samples using UI Composition, Surface Partitioning, and Backdrop Filter features |
Enhancement | Added support for backface-visibility CSS style |
Enhancement | Added support for GPOS kerning for fonts |
Enhancement | Added partial support for SVG transform, width, height, and viewbox JavaScript properties |
EnhancementUnreal Engine | Improved the sample hub UI |
Enhancement | Updated FreeType to version 2.13.2 |
Enhancement | Added GPU memory tracking to profiling output |
Enhancement | Optimized performance of border-image with SVG |
Enhancement | Added support for sending input events to composited surfaces |
Fix | Fixed a deadlock when scratch textures caches are being cleared |
Fix | Fixed incorrect marking of scratch textures as not usable |
Fix | Fixed a crash when try to read an invalid FreeType face |
Fix | Fixed incorrect SVG clipping with clip-path and mask elements when using them in user space |
Fix | Fixed positioning of nested elements when using cohinline |
Fix | Fixed mouse events not firing correctly for cohinline elements |
FixUnity | Fixed rendering problems with OpenGL and C# Backend in Unity |
Fix | Fixed leaking transformations when scaling SVGs to sizes smaller than 1 pixel |
Fix | Fixed a crash in the Player with HTTP requests on quit |
Fix | Fixed text nodes being 1 pixel larger then necessary that led to incorrect positioning when using right alignment |
Fix | Fixed missing texture when an image is used for only one frame |
FixUnity | Fixed the errors encountered when the Samples were removed from the package |
FixUnity | Fixed the backdrop filter texture format type in HDR mode |
Fix | Fixed requestAnimationFrame callbacks executing on the same frame |
FixUnity | Fixed the OnGUI events input regression caused by the latest input performance upgrades in Input Manager mode. |
Fix | Passing an empty string to textContent property won’t create empty text nodes |
Fix | Fixed cases where event listeners are not fired when other unrelated event listeners are removed |
Fix | Fixed excessive character vertical offset with certain fonts |
Fix | Fixed a crash caused by improper use of GIFs as background images |
Fix | Fixed a warning when setting the animation shorthand property to none |
FixUnreal Engine | Fixed safe zone and letter boxing on the Apple iPhone devices |
FixUnreal Engine | Removed forgotten experimental mentions from the documentation regarding Android and iOS platforms |
FixUnreal Engine | Address accumulation of frames for painting when UMG Widgets are hidden or minimized |
FixUnreal Engine | Fixed PlayerOverrides build issues |
FixUnreal Engine | Fixed UE package unzipping issue with the native Windows File Explorer manager |
Fix | Fixed composition with custom effects |
FixUnity | Fixed crashes when rapidly starting and stopping the Player in the Unity3D Editor |
FixUnity | Fixed order of touch events in Unity3D when Input Manager is used |
Fix | Removed forgotten experimental mentions from the documentation regarding inline layout, complex text, and SDF on GPU features |
FixUnity | Removed forgotten experimental mentions from the documentation regarding the C# backend feature |
Fix | Fixed a bug with upgrading cloned custom elements that prevented their lifetime callbacks to be invoked |
Fix | The inspector now shows the views for inspection only when they have a valid document loaded |
Fix | Fixed CSS calc functions failing when running with locale settings where the decimal symbol is not a dot |
Fix | Fixed a crash when clearing SVG surfaces caches |
Fix | Fixed 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
calledPreferCPUWorkload
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 stageData_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
andCOH_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 fromRGBA32_FLOAT
toRGB32_FLOAT
- Added new attribute
CBIndices
which isRGBA8_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 bufferMaxRegistersForPixelConstantBuffer
- The maximum count of float4 to be used in the constant buffer
Removed properties:
ConstantBufferBlocksCount
- Changed toPersistentConstantBuffersCount
- 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 unusedRequiresShaderTypeInShader
- 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 theStandardVertex
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 inGLES3
we useglVertexAttribIPointer
, however, it’s not supported onGLES2
, 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