mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 21:21:17 +01:00
refactor: Start splitting shaders into separate files (#10698) b73733a052
* refactor: Start splitting shaders into separate files The draw shaders are getting unruly with #defines all over the place. Before we can add more, we need to clean these up a little. This PR splits out the fragment portions of raster ordered and msaa shaders into separate files. This also required teaching minify.py to handle .vert and .frag files. * apply_frag_coverage * fixwebgpu * unreal * fixmetalagain * formats * oops * rm draw_image_mesh.glsl Co-authored-by: Chris Dalton <99840794+csmartdalton@users.noreply.github.com>
This commit is contained in:
@@ -1 +1 @@
|
||||
986c92af9ab29f5c68bb3a6a39c1f05924683028
|
||||
b73733a0525518a76e8a6b32a2529a2dea319ace
|
||||
|
||||
@@ -277,9 +277,9 @@ private:
|
||||
glutils::Texture m_atlasTexture = glutils::Texture::Zero();
|
||||
glutils::Framebuffer m_atlasFBO;
|
||||
|
||||
// Wraps a compiled GL shader of draw_path.glsl or draw_image_mesh.glsl,
|
||||
// either vertex or fragment, with a specific set of features enabled via
|
||||
// #define. The set of features to enable is dictated by ShaderFeatures.
|
||||
// Wraps a compiled GL "draw" shader, either vertex or fragment, with a
|
||||
// specific set of features enabled via #define. The set of features to
|
||||
// enable is dictated by ShaderFeatures.
|
||||
class DrawShader
|
||||
{
|
||||
public:
|
||||
@@ -304,9 +304,9 @@ private:
|
||||
GLuint m_id = 0;
|
||||
};
|
||||
|
||||
// Wraps a compiled and linked GL program of draw_path.glsl or
|
||||
// draw_image_mesh.glsl, with a specific set of features enabled via
|
||||
// #define. The set of features to enable is dictated by ShaderFeatures.
|
||||
// Wraps a compiled and linked GL "draw" program, with a specific set of
|
||||
// features enabled via #define. The set of features to enable is dictated
|
||||
// by ShaderFeatures.
|
||||
class DrawProgram
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -10,16 +10,14 @@
|
||||
|
||||
#include "generated/shaders/advanced_blend.glsl.hpp"
|
||||
#include "generated/shaders/atomic_draw.glsl.hpp"
|
||||
#include "generated/shaders/color_ramp.glsl.hpp"
|
||||
#include "generated/shaders/constants.glsl.hpp"
|
||||
#include "generated/shaders/common.glsl.hpp"
|
||||
#include "generated/shaders/draw_image_mesh.glsl.hpp"
|
||||
#include "generated/shaders/draw_image_mesh.vert.hpp"
|
||||
#include "generated/shaders/draw_raster_order_image_mesh.frag.hpp"
|
||||
#include "generated/shaders/draw_path_common.glsl.hpp"
|
||||
#include "generated/shaders/draw_path.glsl.hpp"
|
||||
#include "generated/shaders/draw_path.vert.hpp"
|
||||
#include "generated/shaders/draw_raster_order_path.frag.hpp"
|
||||
#include "generated/shaders/hlsl.glsl.hpp"
|
||||
#include "generated/shaders/bezier_utils.glsl.hpp"
|
||||
#include "generated/shaders/render_atlas.glsl.hpp"
|
||||
#include "generated/shaders/tessellate.glsl.hpp"
|
||||
|
||||
namespace rive::gpu::d3d_utils
|
||||
{
|
||||
@@ -125,18 +123,30 @@ static std::string build_shader(DrawType drawType,
|
||||
case DrawType::midpointFanCenterAAPatches:
|
||||
case DrawType::outerCurvePatches:
|
||||
s << glsl::draw_path_common << '\n';
|
||||
s << (interlockMode == InterlockMode::rasterOrdering
|
||||
? glsl::draw_path
|
||||
: glsl::atomic_draw)
|
||||
<< '\n';
|
||||
if (interlockMode == gpu::InterlockMode::rasterOrdering)
|
||||
{
|
||||
s << glsl::draw_path_vert << '\n';
|
||||
s << glsl::draw_raster_order_path_frag << '\n';
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(interlockMode == gpu::InterlockMode::atomics);
|
||||
s << glsl::atomic_draw << '\n';
|
||||
}
|
||||
break;
|
||||
case DrawType::interiorTriangulation:
|
||||
case DrawType::atlasBlit:
|
||||
s << glsl::draw_path_common << '\n';
|
||||
s << (interlockMode == InterlockMode::rasterOrdering
|
||||
? glsl::draw_path
|
||||
: glsl::atomic_draw)
|
||||
<< '\n';
|
||||
if (interlockMode == gpu::InterlockMode::rasterOrdering)
|
||||
{
|
||||
s << glsl::draw_path_vert << '\n';
|
||||
s << glsl::draw_raster_order_path_frag << '\n';
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(interlockMode == gpu::InterlockMode::atomics);
|
||||
s << glsl::atomic_draw << '\n';
|
||||
}
|
||||
break;
|
||||
case DrawType::imageRect:
|
||||
assert(interlockMode == InterlockMode::atomics);
|
||||
@@ -146,7 +156,8 @@ static std::string build_shader(DrawType drawType,
|
||||
case DrawType::imageMesh:
|
||||
if (interlockMode == InterlockMode::rasterOrdering)
|
||||
{
|
||||
s << glsl::draw_image_mesh << '\n';
|
||||
s << glsl::draw_image_mesh_vert << '\n';
|
||||
s << glsl::draw_raster_order_image_mesh_frag << '\n';
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -9,20 +9,8 @@
|
||||
#include "rive/renderer/texture.hpp"
|
||||
|
||||
#include <D3DCompiler.h>
|
||||
#include <sstream>
|
||||
|
||||
#include "generated/shaders/advanced_blend.glsl.hpp"
|
||||
#include "generated/shaders/atomic_draw.glsl.hpp"
|
||||
#include "generated/shaders/color_ramp.glsl.hpp"
|
||||
#include "generated/shaders/constants.glsl.hpp"
|
||||
#include "generated/shaders/common.glsl.hpp"
|
||||
#include "generated/shaders/draw_image_mesh.glsl.hpp"
|
||||
#include "generated/shaders/draw_path_common.glsl.hpp"
|
||||
#include "generated/shaders/draw_path.glsl.hpp"
|
||||
#include "generated/shaders/hlsl.glsl.hpp"
|
||||
#include "generated/shaders/bezier_utils.glsl.hpp"
|
||||
#include "generated/shaders/render_atlas.glsl.hpp"
|
||||
#include "generated/shaders/tessellate.glsl.hpp"
|
||||
#include "generated/shaders/tessellate.glsl.exports.h"
|
||||
|
||||
// offline shaders
|
||||
namespace shader
|
||||
|
||||
@@ -4,18 +4,7 @@
|
||||
#include "rive/renderer/d3d12/d3d12_pipeline_manager.hpp"
|
||||
#include "rive/renderer/d3d/d3d_constants.hpp"
|
||||
|
||||
#include "generated/shaders/advanced_blend.glsl.hpp"
|
||||
#include "generated/shaders/atomic_draw.glsl.hpp"
|
||||
#include "generated/shaders/color_ramp.glsl.hpp"
|
||||
#include "generated/shaders/constants.glsl.hpp"
|
||||
#include "generated/shaders/common.glsl.hpp"
|
||||
#include "generated/shaders/draw_image_mesh.glsl.hpp"
|
||||
#include "generated/shaders/draw_path_common.glsl.hpp"
|
||||
#include "generated/shaders/draw_path.glsl.hpp"
|
||||
#include "generated/shaders/hlsl.glsl.hpp"
|
||||
#include "generated/shaders/bezier_utils.glsl.hpp"
|
||||
#include "generated/shaders/render_atlas.glsl.hpp"
|
||||
#include "generated/shaders/tessellate.glsl.hpp"
|
||||
#include "generated/shaders/tessellate.glsl.exports.h"
|
||||
|
||||
// offline shaders
|
||||
namespace shader
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "shaders/constants.glsl"
|
||||
#include <sstream>
|
||||
|
||||
#include "generated/shaders/pls_load_store_ext.exports.h"
|
||||
#include "generated/shaders/pls_load_store_ext.glsl.exports.h"
|
||||
|
||||
namespace rive::gpu
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "shaders/constants.glsl"
|
||||
#include "rive/renderer/gl/gl_utils.hpp"
|
||||
|
||||
#include "generated/shaders/glsl.exports.h"
|
||||
#include "generated/shaders/glsl.glsl.exports.h"
|
||||
|
||||
namespace rive::gpu
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "rive/renderer/gl/render_target_gl.hpp"
|
||||
#include "shaders/constants.glsl"
|
||||
|
||||
#include "generated/shaders/glsl.exports.h"
|
||||
#include "generated/shaders/glsl.glsl.exports.h"
|
||||
|
||||
#ifdef RIVE_WEBGL
|
||||
#include <emscripten/emscripten.h>
|
||||
|
||||
@@ -18,8 +18,12 @@
|
||||
#include "generated/shaders/constants.glsl.hpp"
|
||||
#include "generated/shaders/common.glsl.hpp"
|
||||
#include "generated/shaders/draw_path_common.glsl.hpp"
|
||||
#include "generated/shaders/draw_path.glsl.hpp"
|
||||
#include "generated/shaders/draw_image_mesh.glsl.hpp"
|
||||
#include "generated/shaders/draw_path.vert.hpp"
|
||||
#include "generated/shaders/draw_raster_order_path.frag.hpp"
|
||||
#include "generated/shaders/draw_msaa_path.frag.hpp"
|
||||
#include "generated/shaders/draw_image_mesh.vert.hpp"
|
||||
#include "generated/shaders/draw_raster_order_image_mesh.frag.hpp"
|
||||
#include "generated/shaders/draw_msaa_image_mesh.frag.hpp"
|
||||
#include "generated/shaders/bezier_utils.glsl.hpp"
|
||||
#include "generated/shaders/tessellate.glsl.hpp"
|
||||
#include "generated/shaders/render_atlas.glsl.hpp"
|
||||
@@ -1098,9 +1102,18 @@ RenderContextGLImpl::DrawShader::DrawShader(
|
||||
}
|
||||
defines.push_back(GLSL_DRAW_PATH);
|
||||
sources.push_back(gpu::glsl::draw_path_common);
|
||||
sources.push_back(interlockMode == gpu::InterlockMode::atomics
|
||||
? gpu::glsl::atomic_draw
|
||||
: gpu::glsl::draw_path);
|
||||
if (interlockMode == gpu::InterlockMode::atomics)
|
||||
{
|
||||
sources.push_back(gpu::glsl::atomic_draw);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
sources.push_back(gpu::glsl::draw_path_vert);
|
||||
sources.push_back(interlockMode == gpu::InterlockMode::msaa
|
||||
? gpu::glsl::draw_msaa_path_frag
|
||||
: gpu::glsl::draw_raster_order_path_frag);
|
||||
}
|
||||
break;
|
||||
case gpu::DrawType::msaaStencilClipReset:
|
||||
assert(interlockMode == gpu::InterlockMode::msaa);
|
||||
@@ -1128,9 +1141,18 @@ RenderContextGLImpl::DrawShader::DrawShader(
|
||||
case gpu::DrawType::interiorTriangulation:
|
||||
defines.push_back(GLSL_DRAW_INTERIOR_TRIANGLES);
|
||||
sources.push_back(gpu::glsl::draw_path_common);
|
||||
sources.push_back(interlockMode == gpu::InterlockMode::atomics
|
||||
? gpu::glsl::atomic_draw
|
||||
: gpu::glsl::draw_path);
|
||||
if (interlockMode == gpu::InterlockMode::atomics)
|
||||
{
|
||||
sources.push_back(gpu::glsl::atomic_draw);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
sources.push_back(gpu::glsl::draw_path_vert);
|
||||
sources.push_back(interlockMode == gpu::InterlockMode::msaa
|
||||
? gpu::glsl::draw_msaa_path_frag
|
||||
: gpu::glsl::draw_raster_order_path_frag);
|
||||
}
|
||||
break;
|
||||
case gpu::DrawType::imageRect:
|
||||
assert(interlockMode == gpu::InterlockMode::atomics);
|
||||
@@ -1149,7 +1171,11 @@ RenderContextGLImpl::DrawShader::DrawShader(
|
||||
}
|
||||
else
|
||||
{
|
||||
sources.push_back(gpu::glsl::draw_image_mesh);
|
||||
sources.push_back(gpu::glsl::draw_image_mesh_vert);
|
||||
sources.push_back(
|
||||
interlockMode == gpu::InterlockMode::msaa
|
||||
? gpu::glsl::draw_msaa_image_mesh_frag
|
||||
: gpu::glsl::draw_raster_order_image_mesh_frag);
|
||||
}
|
||||
break;
|
||||
case gpu::DrawType::renderPassResolve:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "rive_render_paint.hpp"
|
||||
#include "gradient.hpp"
|
||||
|
||||
#include "generated/shaders/draw_path.exports.h"
|
||||
#include "generated/shaders/draw_path.vert.exports.h"
|
||||
|
||||
namespace rive::gpu
|
||||
{
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
namespace rive::gpu
|
||||
{
|
||||
// Defines a job to compile a "draw" shader -- either draw_path.glsl or
|
||||
// draw_image_mesh.glsl, with a specific set of features enabled.
|
||||
// Defines a job to compile a "draw" shader, with a specific set of features
|
||||
// enabled.
|
||||
struct BackgroundCompileJob
|
||||
{
|
||||
gpu::DrawType drawType;
|
||||
@@ -29,9 +29,8 @@ struct BackgroundCompileJob
|
||||
#endif
|
||||
};
|
||||
|
||||
// Compiles "draw" shaders in a background thread. A "draw" shaders is either
|
||||
// draw_path.glsl or draw_image_mesh.glsl, with a specific set of features
|
||||
// enabled.
|
||||
// Compiles "draw" shaders in a background thread, with a specific set of
|
||||
// features enabled.
|
||||
class BackgroundShaderCompiler
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
#include "generated/shaders/common.glsl.hpp"
|
||||
#include "generated/shaders/advanced_blend.glsl.hpp"
|
||||
#include "generated/shaders/draw_path_common.glsl.hpp"
|
||||
#include "generated/shaders/draw_path.glsl.hpp"
|
||||
#include "generated/shaders/draw_image_mesh.glsl.hpp"
|
||||
#include "generated/shaders/draw_path.vert.hpp"
|
||||
#include "generated/shaders/draw_raster_order_path.frag.hpp"
|
||||
#include "generated/shaders/draw_image_mesh.vert.hpp"
|
||||
#include "generated/shaders/draw_raster_order_image_mesh.frag.hpp"
|
||||
|
||||
#ifndef RIVE_IOS
|
||||
// iOS doesn't need the atomic shaders; every non-simulated iOS device supports
|
||||
@@ -144,15 +146,20 @@ void BackgroundShaderCompiler::threadMain()
|
||||
defines[@GLSL_ENABLE_INSTANCE_INDEX] = @"";
|
||||
defines[@GLSL_DRAW_PATH] = @"";
|
||||
[source appendFormat:@"%s\n", gpu::glsl::draw_path_common];
|
||||
#ifdef RIVE_IOS
|
||||
[source appendFormat:@"%s\n", gpu::glsl::draw_path];
|
||||
#else
|
||||
[source appendFormat:@"%s\n",
|
||||
interlockMode ==
|
||||
gpu::InterlockMode::rasterOrdering
|
||||
? gpu::glsl::draw_path
|
||||
: gpu::glsl::atomic_draw];
|
||||
#ifndef RIVE_IOS
|
||||
if (interlockMode == gpu::InterlockMode::atomics)
|
||||
{
|
||||
[source appendFormat:@"%s\n", gpu::glsl::atomic_draw];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
assert(interlockMode == gpu::InterlockMode::rasterOrdering);
|
||||
[source appendFormat:@"%s\n", gpu::glsl::draw_path_vert];
|
||||
[source
|
||||
appendFormat:@"%s\n",
|
||||
gpu::glsl::draw_raster_order_path_frag];
|
||||
}
|
||||
break;
|
||||
case DrawType::atlasBlit:
|
||||
defines[@GLSL_ATLAS_BLIT] = @"1";
|
||||
@@ -160,15 +167,20 @@ void BackgroundShaderCompiler::threadMain()
|
||||
case DrawType::interiorTriangulation:
|
||||
defines[@GLSL_DRAW_INTERIOR_TRIANGLES] = @"";
|
||||
[source appendFormat:@"%s\n", gpu::glsl::draw_path_common];
|
||||
#ifdef RIVE_IOS
|
||||
[source appendFormat:@"%s\n", gpu::glsl::draw_path];
|
||||
#else
|
||||
[source appendFormat:@"%s\n",
|
||||
interlockMode ==
|
||||
gpu::InterlockMode::rasterOrdering
|
||||
? gpu::glsl::draw_path
|
||||
: gpu::glsl::atomic_draw];
|
||||
#ifndef RIVE_IOS
|
||||
if (interlockMode == gpu::InterlockMode::atomics)
|
||||
{
|
||||
[source appendFormat:@"%s\n", gpu::glsl::atomic_draw];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
assert(interlockMode == gpu::InterlockMode::rasterOrdering);
|
||||
[source appendFormat:@"%s\n", gpu::glsl::draw_path_vert];
|
||||
[source
|
||||
appendFormat:@"%s\n",
|
||||
gpu::glsl::draw_raster_order_path_frag];
|
||||
}
|
||||
break;
|
||||
case DrawType::imageRect:
|
||||
#ifdef RIVE_IOS
|
||||
@@ -184,19 +196,22 @@ void BackgroundShaderCompiler::threadMain()
|
||||
case DrawType::imageMesh:
|
||||
defines[@GLSL_DRAW_IMAGE] = @"";
|
||||
defines[@GLSL_DRAW_IMAGE_MESH] = @"";
|
||||
#ifdef RIVE_IOS
|
||||
[source appendFormat:@"%s\n", gpu::glsl::draw_image_mesh];
|
||||
#else
|
||||
if (interlockMode == gpu::InterlockMode::rasterOrdering)
|
||||
{
|
||||
[source appendFormat:@"%s\n", gpu::glsl::draw_image_mesh];
|
||||
}
|
||||
else
|
||||
#ifndef RIVE_IOS
|
||||
if (interlockMode == gpu::InterlockMode::atomics)
|
||||
{
|
||||
[source appendFormat:@"%s\n", gpu::glsl::draw_path_common];
|
||||
[source appendFormat:@"%s\n", gpu::glsl::atomic_draw];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
assert(interlockMode == gpu::InterlockMode::rasterOrdering);
|
||||
[source
|
||||
appendFormat:@"%s\n", gpu::glsl::draw_image_mesh_vert];
|
||||
[source appendFormat:@"%s\n",
|
||||
gpu::glsl::
|
||||
draw_raster_order_image_mesh_frag];
|
||||
}
|
||||
break;
|
||||
case DrawType::renderPassInitialize:
|
||||
#ifdef RIVE_IOS
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#include "shaders/constants.glsl"
|
||||
#include <sstream>
|
||||
|
||||
#include "generated/shaders/color_ramp.exports.h"
|
||||
#include "generated/shaders/tessellate.exports.h"
|
||||
#include "generated/shaders/color_ramp.glsl.exports.h"
|
||||
#include "generated/shaders/tessellate.glsl.exports.h"
|
||||
|
||||
#if defined(RIVE_IOS_SIMULATOR)
|
||||
#import <mach-o/arch.h>
|
||||
|
||||
@@ -7,7 +7,7 @@ OUT := out/generated
|
||||
FLAGS :=
|
||||
|
||||
## Shader minification.
|
||||
MINIFY_INPUTS := $(wildcard *.glsl)
|
||||
MINIFY_INPUTS := $(wildcard *.glsl) $(wildcard *.vert) $(wildcard *.frag)
|
||||
MINIFY_EXPORT_OUTPUTS := $(addprefix $(OUT)/, $(patsubst %.glsl, %.exports.h, $(MINIFY_INPUTS)))
|
||||
MINIFY_GLSL_OUTPUTS := $(addprefix $(OUT)/, $(patsubst %.glsl, %.minified.glsl, $(MINIFY_INPUTS)))
|
||||
MINIFY_HPP_OUTPUTS := $(addprefix $(OUT)/, $(patsubst %.glsl, %.glsl.hpp, $(MINIFY_INPUTS)))
|
||||
|
||||
@@ -23,6 +23,8 @@ layout(input_attachment_index = 0,
|
||||
binding = MSAA_COLOR_SEED_IDX,
|
||||
set = PLS_TEXTURE_BINDINGS_SET) uniform lowp subpassInput
|
||||
inputAttachment;
|
||||
|
||||
layout(location = 0) out half4 outputColor;
|
||||
|
||||
void main() { outputColor = subpassLoad(inputAttachment); }
|
||||
#endif
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 Rive
|
||||
*/
|
||||
|
||||
#ifdef @VERTEX
|
||||
ATTR_BLOCK_BEGIN(PositionAttr)
|
||||
ATTR(0, float2, @a_position);
|
||||
ATTR_BLOCK_END
|
||||
|
||||
ATTR_BLOCK_BEGIN(UVAttr)
|
||||
ATTR(1, float2, @a_texCoord);
|
||||
ATTR_BLOCK_END
|
||||
#endif
|
||||
|
||||
VARYING_BLOCK_BEGIN
|
||||
NO_PERSPECTIVE VARYING(0, float2, v_texCoord);
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
@OPTIONALLY_FLAT VARYING(1, half, v_clipID);
|
||||
#endif
|
||||
#if defined(@ENABLE_CLIP_RECT) && !defined(@RENDER_MODE_MSAA)
|
||||
NO_PERSPECTIVE VARYING(2, float4, v_clipRect);
|
||||
#endif
|
||||
VARYING_BLOCK_END
|
||||
|
||||
#ifdef @VERTEX
|
||||
VERTEX_TEXTURE_BLOCK_BEGIN
|
||||
VERTEX_TEXTURE_BLOCK_END
|
||||
|
||||
IMAGE_MESH_VERTEX_MAIN(@drawVertexMain,
|
||||
PositionAttr,
|
||||
position,
|
||||
UVAttr,
|
||||
uv,
|
||||
_vertexID)
|
||||
{
|
||||
ATTR_UNPACK(_vertexID, position, @a_position, float2);
|
||||
ATTR_UNPACK(_vertexID, uv, @a_texCoord, float2);
|
||||
|
||||
VARYING_INIT(v_texCoord, float2);
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
VARYING_INIT(v_clipID, half);
|
||||
#endif
|
||||
#if defined(@ENABLE_CLIP_RECT) && !defined(@RENDER_MODE_MSAA)
|
||||
VARYING_INIT(v_clipRect, float4);
|
||||
#endif
|
||||
|
||||
float2 vertexPosition =
|
||||
MUL(make_float2x2(imageDrawUniforms.viewMatrix), @a_position) +
|
||||
imageDrawUniforms.translate;
|
||||
v_texCoord = @a_texCoord;
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
if (@ENABLE_CLIPPING)
|
||||
{
|
||||
v_clipID = id_bits_to_f16(imageDrawUniforms.clipID,
|
||||
uniforms.pathIDGranularity);
|
||||
}
|
||||
#endif
|
||||
#ifdef @ENABLE_CLIP_RECT
|
||||
if (@ENABLE_CLIP_RECT)
|
||||
{
|
||||
#ifndef @RENDER_MODE_MSAA
|
||||
v_clipRect = find_clip_rect_coverage_distances(
|
||||
make_float2x2(imageDrawUniforms.clipRectInverseMatrix),
|
||||
imageDrawUniforms.clipRectInverseTranslate,
|
||||
vertexPosition);
|
||||
#else
|
||||
set_clip_rect_plane_distances(
|
||||
make_float2x2(imageDrawUniforms.clipRectInverseMatrix),
|
||||
imageDrawUniforms.clipRectInverseTranslate,
|
||||
vertexPosition);
|
||||
#endif
|
||||
}
|
||||
#endif // ENABLE_CLIP_RECT
|
||||
float4 pos = RENDER_TARGET_COORD_TO_CLIP_COORD(vertexPosition);
|
||||
#ifdef @POST_INVERT_Y
|
||||
pos.y = -pos.y;
|
||||
#endif
|
||||
#ifdef @RENDER_MODE_MSAA
|
||||
pos.z = normalize_z_index(imageDrawUniforms.zIndex);
|
||||
#endif
|
||||
|
||||
VARYING_PACK(v_texCoord);
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
VARYING_PACK(v_clipID);
|
||||
#endif
|
||||
#ifdef @ENABLE_CLIP_RECT
|
||||
VARYING_PACK(v_clipRect);
|
||||
#endif
|
||||
EMIT_VERTEX(pos);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef @FRAGMENT
|
||||
FRAG_TEXTURE_BLOCK_BEGIN
|
||||
TEXTURE_RGBA8(PER_DRAW_BINDINGS_SET, IMAGE_TEXTURE_IDX, @imageTexture);
|
||||
#if defined(@RENDER_MODE_MSAA) && defined(@ENABLE_ADVANCED_BLEND)
|
||||
DST_COLOR_TEXTURE(@dstColorTexture);
|
||||
#endif
|
||||
FRAG_TEXTURE_BLOCK_END
|
||||
|
||||
DYNAMIC_SAMPLER_BLOCK_BEGIN
|
||||
SAMPLER_DYNAMIC(PER_DRAW_BINDINGS_SET, IMAGE_SAMPLER_IDX, imageSampler)
|
||||
DYNAMIC_SAMPLER_BLOCK_END
|
||||
|
||||
FRAG_STORAGE_BUFFER_BLOCK_BEGIN
|
||||
FRAG_STORAGE_BUFFER_BLOCK_END
|
||||
|
||||
#ifndef @RENDER_MODE_MSAA
|
||||
|
||||
PLS_BLOCK_BEGIN
|
||||
PLS_DECL4F(COLOR_PLANE_IDX, colorBuffer);
|
||||
PLS_DECLUI(CLIP_PLANE_IDX, clipBuffer);
|
||||
PLS_DECL4F(SCRATCH_COLOR_PLANE_IDX, scratchColorBuffer);
|
||||
PLS_DECLUI(COVERAGE_PLANE_IDX, coverageCountBuffer);
|
||||
PLS_BLOCK_END
|
||||
|
||||
PLS_MAIN_WITH_IMAGE_UNIFORMS(@drawFragmentMain)
|
||||
{
|
||||
VARYING_UNPACK(v_texCoord, float2);
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
VARYING_UNPACK(v_clipID, half);
|
||||
#endif
|
||||
#ifdef @ENABLE_CLIP_RECT
|
||||
VARYING_UNPACK(v_clipRect, float4);
|
||||
#endif
|
||||
|
||||
half4 color = TEXTURE_SAMPLE_DYNAMIC_LODBIAS(@imageTexture,
|
||||
imageSampler,
|
||||
v_texCoord,
|
||||
uniforms.mipMapLODBias);
|
||||
|
||||
half coverage = 1.;
|
||||
|
||||
#ifdef @ENABLE_CLIP_RECT
|
||||
if (@ENABLE_CLIP_RECT)
|
||||
{
|
||||
half clipRectCoverage = min_value(cast_float4_to_half4(v_clipRect));
|
||||
coverage = clamp(clipRectCoverage, make_half(.0), coverage);
|
||||
}
|
||||
#endif
|
||||
|
||||
PLS_INTERLOCK_BEGIN;
|
||||
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
if (@ENABLE_CLIPPING && v_clipID != .0)
|
||||
{
|
||||
half2 clipData = unpackHalf2x16(PLS_LOADUI(clipBuffer));
|
||||
half clipContentID = clipData.g;
|
||||
half clipCoverage =
|
||||
clipContentID == v_clipID ? clipData.r : make_half(.0);
|
||||
coverage = min(coverage, clipCoverage);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Blend with the framebuffer color.
|
||||
half4 dstColorPremul = PLS_LOAD4F(colorBuffer);
|
||||
#ifdef @ENABLE_ADVANCED_BLEND
|
||||
if (@ENABLE_ADVANCED_BLEND && imageDrawUniforms.blendMode != BLEND_SRC_OVER)
|
||||
{
|
||||
color.rgb = advanced_color_blend(
|
||||
unmultiply_rgb(color),
|
||||
dstColorPremul,
|
||||
cast_uint_to_ushort(imageDrawUniforms.blendMode)) *
|
||||
color.a;
|
||||
}
|
||||
#endif
|
||||
color *= imageDrawUniforms.opacity * coverage;
|
||||
color += dstColorPremul * (1. - color.a);
|
||||
|
||||
PLS_STORE4F(colorBuffer, color);
|
||||
PLS_PRESERVE_UI(clipBuffer);
|
||||
PLS_PRESERVE_UI(coverageCountBuffer);
|
||||
|
||||
PLS_INTERLOCK_END;
|
||||
|
||||
EMIT_PLS;
|
||||
}
|
||||
|
||||
#else // !@RENDER_MODE_MSAA => @RENDER_MODE_MSAA
|
||||
|
||||
FRAG_DATA_MAIN(half4, @drawFragmentMain)
|
||||
{
|
||||
VARYING_UNPACK(v_texCoord, float2);
|
||||
|
||||
half4 color = TEXTURE_SAMPLE_DYNAMIC_LODBIAS(@imageTexture,
|
||||
imageSampler,
|
||||
v_texCoord,
|
||||
uniforms.mipMapLODBias) *
|
||||
imageDrawUniforms.opacity;
|
||||
|
||||
#if defined(@ENABLE_ADVANCED_BLEND) && !defined(@FIXED_FUNCTION_COLOR_OUTPUT)
|
||||
if (@ENABLE_ADVANCED_BLEND)
|
||||
{
|
||||
// Do the color portion of the blend mode in the shader.
|
||||
half4 dstColorPremul = DST_COLOR_FETCH(@dstColorTexture);
|
||||
color.rgb = advanced_color_blend(unmultiply_rgb(color),
|
||||
dstColorPremul,
|
||||
imageDrawUniforms.blendMode);
|
||||
// Src-over blending is enabled, so just premultiply and let the HW
|
||||
// finish the the the alpha portion of the blend mode.
|
||||
color.rgb *= color.a;
|
||||
}
|
||||
#endif // @ENABLE_ADVANCED_BLEND && !@FIXED_FUNCTION_COLOR_OUTPUT
|
||||
|
||||
EMIT_FRAG_DATA(color);
|
||||
}
|
||||
|
||||
#endif // @RENDER_MODE_MSAA
|
||||
#endif // FRAGMENT
|
||||
91
renderer/src/shaders/draw_image_mesh.vert
Normal file
91
renderer/src/shaders/draw_image_mesh.vert
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2023 Rive
|
||||
*/
|
||||
|
||||
#ifdef @VERTEX
|
||||
ATTR_BLOCK_BEGIN(PositionAttr)
|
||||
ATTR(0, float2, @a_position);
|
||||
ATTR_BLOCK_END
|
||||
|
||||
ATTR_BLOCK_BEGIN(UVAttr)
|
||||
ATTR(1, float2, @a_texCoord);
|
||||
ATTR_BLOCK_END
|
||||
#endif
|
||||
|
||||
VARYING_BLOCK_BEGIN
|
||||
NO_PERSPECTIVE VARYING(0, float2, v_texCoord);
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
@OPTIONALLY_FLAT VARYING(1, half, v_clipID);
|
||||
#endif
|
||||
#if defined(@ENABLE_CLIP_RECT) && !defined(@RENDER_MODE_MSAA)
|
||||
NO_PERSPECTIVE VARYING(2, float4, v_clipRect);
|
||||
#endif
|
||||
VARYING_BLOCK_END
|
||||
|
||||
#ifdef @VERTEX
|
||||
VERTEX_TEXTURE_BLOCK_BEGIN
|
||||
VERTEX_TEXTURE_BLOCK_END
|
||||
|
||||
IMAGE_MESH_VERTEX_MAIN(@drawVertexMain,
|
||||
PositionAttr,
|
||||
position,
|
||||
UVAttr,
|
||||
uv,
|
||||
_vertexID)
|
||||
{
|
||||
ATTR_UNPACK(_vertexID, position, @a_position, float2);
|
||||
ATTR_UNPACK(_vertexID, uv, @a_texCoord, float2);
|
||||
|
||||
VARYING_INIT(v_texCoord, float2);
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
VARYING_INIT(v_clipID, half);
|
||||
#endif
|
||||
#if defined(@ENABLE_CLIP_RECT) && !defined(@RENDER_MODE_MSAA)
|
||||
VARYING_INIT(v_clipRect, float4);
|
||||
#endif
|
||||
|
||||
float2 vertexPosition =
|
||||
MUL(make_float2x2(imageDrawUniforms.viewMatrix), @a_position) +
|
||||
imageDrawUniforms.translate;
|
||||
v_texCoord = @a_texCoord;
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
if (@ENABLE_CLIPPING)
|
||||
{
|
||||
v_clipID = id_bits_to_f16(imageDrawUniforms.clipID,
|
||||
uniforms.pathIDGranularity);
|
||||
}
|
||||
#endif
|
||||
#ifdef @ENABLE_CLIP_RECT
|
||||
if (@ENABLE_CLIP_RECT)
|
||||
{
|
||||
#ifndef @RENDER_MODE_MSAA
|
||||
v_clipRect = find_clip_rect_coverage_distances(
|
||||
make_float2x2(imageDrawUniforms.clipRectInverseMatrix),
|
||||
imageDrawUniforms.clipRectInverseTranslate,
|
||||
vertexPosition);
|
||||
#else
|
||||
set_clip_rect_plane_distances(
|
||||
make_float2x2(imageDrawUniforms.clipRectInverseMatrix),
|
||||
imageDrawUniforms.clipRectInverseTranslate,
|
||||
vertexPosition);
|
||||
#endif
|
||||
}
|
||||
#endif // ENABLE_CLIP_RECT
|
||||
float4 pos = RENDER_TARGET_COORD_TO_CLIP_COORD(vertexPosition);
|
||||
#ifdef @POST_INVERT_Y
|
||||
pos.y = -pos.y;
|
||||
#endif
|
||||
#ifdef @RENDER_MODE_MSAA
|
||||
pos.z = normalize_z_index(imageDrawUniforms.zIndex);
|
||||
#endif
|
||||
|
||||
VARYING_PACK(v_texCoord);
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
VARYING_PACK(v_clipID);
|
||||
#endif
|
||||
#ifdef @ENABLE_CLIP_RECT
|
||||
VARYING_PACK(v_clipRect);
|
||||
#endif
|
||||
EMIT_VERTEX(pos);
|
||||
}
|
||||
#endif
|
||||
48
renderer/src/shaders/draw_msaa_image_mesh.frag
Normal file
48
renderer/src/shaders/draw_msaa_image_mesh.frag
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2023 Rive
|
||||
*/
|
||||
|
||||
#ifdef @FRAGMENT
|
||||
|
||||
FRAG_TEXTURE_BLOCK_BEGIN
|
||||
TEXTURE_RGBA8(PER_DRAW_BINDINGS_SET, IMAGE_TEXTURE_IDX, @imageTexture);
|
||||
#ifdef @ENABLE_ADVANCED_BLEND
|
||||
DST_COLOR_TEXTURE(@dstColorTexture);
|
||||
#endif
|
||||
FRAG_TEXTURE_BLOCK_END
|
||||
|
||||
DYNAMIC_SAMPLER_BLOCK_BEGIN
|
||||
SAMPLER_DYNAMIC(PER_DRAW_BINDINGS_SET, IMAGE_SAMPLER_IDX, imageSampler)
|
||||
DYNAMIC_SAMPLER_BLOCK_END
|
||||
|
||||
FRAG_STORAGE_BUFFER_BLOCK_BEGIN
|
||||
FRAG_STORAGE_BUFFER_BLOCK_END
|
||||
|
||||
FRAG_DATA_MAIN(half4, @drawFragmentMain)
|
||||
{
|
||||
VARYING_UNPACK(v_texCoord, float2);
|
||||
|
||||
half4 color = TEXTURE_SAMPLE_DYNAMIC_LODBIAS(@imageTexture,
|
||||
imageSampler,
|
||||
v_texCoord,
|
||||
uniforms.mipMapLODBias) *
|
||||
imageDrawUniforms.opacity;
|
||||
|
||||
#if defined(@ENABLE_ADVANCED_BLEND) && !defined(@FIXED_FUNCTION_COLOR_OUTPUT)
|
||||
if (@ENABLE_ADVANCED_BLEND)
|
||||
{
|
||||
// Do the color portion of the blend mode in the shader.
|
||||
half4 dstColorPremul = DST_COLOR_FETCH(@dstColorTexture);
|
||||
color.rgb = advanced_color_blend(unmultiply_rgb(color),
|
||||
dstColorPremul,
|
||||
imageDrawUniforms.blendMode);
|
||||
// Src-over blending is enabled, so just premultiply and let the HW
|
||||
// finish the the the alpha portion of the blend mode.
|
||||
color.rgb *= color.a;
|
||||
}
|
||||
#endif // @ENABLE_ADVANCED_BLEND && !@FIXED_FUNCTION_COLOR_OUTPUT
|
||||
|
||||
EMIT_FRAG_DATA(color);
|
||||
}
|
||||
|
||||
#endif // @FRAGMENT
|
||||
59
renderer/src/shaders/draw_msaa_path.frag
Normal file
59
renderer/src/shaders/draw_msaa_path.frag
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2022 Rive
|
||||
*/
|
||||
|
||||
#ifdef @FRAGMENT
|
||||
|
||||
FRAG_DATA_MAIN(half4, @drawFragmentMain)
|
||||
{
|
||||
VARYING_UNPACK(v_paint, float4);
|
||||
#ifdef @ATLAS_BLIT
|
||||
VARYING_UNPACK(v_atlasCoord, float2);
|
||||
#endif
|
||||
#ifdef @ENABLE_ADVANCED_BLEND
|
||||
VARYING_UNPACK(v_blendMode, half);
|
||||
#endif
|
||||
|
||||
half coverage =
|
||||
#ifdef @ATLAS_BLIT
|
||||
filter_feather_atlas(
|
||||
v_atlasCoord,
|
||||
uniforms.atlasTextureInverseSize TEXTURE_CONTEXT_FORWARD);
|
||||
#else
|
||||
1.;
|
||||
#endif
|
||||
half4 color = find_paint_color(v_paint, coverage FRAGMENT_CONTEXT_UNPACK);
|
||||
|
||||
#if defined(@ENABLE_ADVANCED_BLEND) && !defined(@FIXED_FUNCTION_COLOR_OUTPUT)
|
||||
if (@ENABLE_ADVANCED_BLEND)
|
||||
{
|
||||
// Do the color portion of the blend mode in the shader.
|
||||
//
|
||||
// NOTE: "color" is already unmultiplied because
|
||||
// GENERATE_PREMULTIPLIED_PAINT_COLORS is false when using advanced
|
||||
// blend.
|
||||
half4 dstColorPremul = DST_COLOR_FETCH(@dstColorTexture);
|
||||
color.rgb = advanced_color_blend(color.rgb,
|
||||
dstColorPremul,
|
||||
cast_half_to_ushort(v_blendMode));
|
||||
// Src-over blending is enabled, so just premultiply and let the HW
|
||||
// finish the the the alpha portion of the blend mode.
|
||||
color.rgb *= color.a;
|
||||
}
|
||||
#endif // @ENABLE_ADVANCED_BLEND && !@FIXED_FUNCTION_COLOR_OUTPUT
|
||||
|
||||
// Certain platforms give us less control of the format of what we are
|
||||
// rendering too. Specifically, we are auto converted from linear -> sRGB on
|
||||
// render target writes in unreal. In those cases we made need to end up in
|
||||
// linear color space
|
||||
#ifdef @NEEDS_GAMMA_CORRECTION
|
||||
if (@NEEDS_GAMMA_CORRECTION)
|
||||
{
|
||||
color = gamma_to_linear(color);
|
||||
}
|
||||
#endif
|
||||
|
||||
EMIT_FRAG_DATA(color);
|
||||
}
|
||||
|
||||
#endif // FRAGMENT
|
||||
@@ -2,6 +2,9 @@
|
||||
* Copyright 2022 Rive
|
||||
*/
|
||||
|
||||
// undef GENERATE_PREMULTIPLIED_PAINT_COLORS first because this file gets
|
||||
// included multiple times with different defines in the Metal library.
|
||||
#undef GENERATE_PREMULTIPLIED_PAINT_COLORS
|
||||
#ifdef @ENABLE_ADVANCED_BLEND
|
||||
// If advanced blend is enabled, we generate unmultiplied paint colors in the
|
||||
// shader. Otherwise we would have to just turn around and unmultiply them in
|
||||
@@ -13,6 +16,15 @@
|
||||
#define GENERATE_PREMULTIPLIED_PAINT_COLORS true
|
||||
#endif
|
||||
|
||||
// undef COVERAGE_TYPE first because this file gets included multiple times with
|
||||
// different defines in the Metal library.
|
||||
#undef COVERAGE_TYPE
|
||||
#ifdef @ENABLE_FEATHER
|
||||
#define COVERAGE_TYPE float4
|
||||
#else
|
||||
#define COVERAGE_TYPE half2
|
||||
#endif
|
||||
|
||||
#ifdef @VERTEX
|
||||
ATTR_BLOCK_BEGIN(Attrs)
|
||||
#ifdef @DRAW_INTERIOR_TRIANGLES
|
||||
@@ -34,10 +46,8 @@ NO_PERSPECTIVE VARYING(1, float2, v_atlasCoord);
|
||||
#elif !defined(@RENDER_MODE_MSAA)
|
||||
#ifdef @DRAW_INTERIOR_TRIANGLES
|
||||
@OPTIONALLY_FLAT VARYING(1, half, v_windingWeight);
|
||||
#elif defined(@ENABLE_FEATHER)
|
||||
NO_PERSPECTIVE VARYING(2, float4, v_coverages);
|
||||
#else
|
||||
NO_PERSPECTIVE VARYING(2, half2, v_coverages);
|
||||
NO_PERSPECTIVE VARYING(2, COVERAGE_TYPE, v_coverages);
|
||||
#endif //@DRAW_INTERIOR_TRIANGLES
|
||||
@OPTIONALLY_FLAT VARYING(3, half, v_pathID);
|
||||
#endif // !@RENDER_MODE_MSAA
|
||||
@@ -70,10 +80,8 @@ VERTEX_MAIN(@drawVertexMain, Attrs, attrs, _vertexID, _instanceID)
|
||||
#elif !defined(@RENDER_MODE_MSAA)
|
||||
#ifdef @DRAW_INTERIOR_TRIANGLES
|
||||
VARYING_INIT(v_windingWeight, half);
|
||||
#elif defined(@ENABLE_FEATHER)
|
||||
VARYING_INIT(v_coverages, float4);
|
||||
#else
|
||||
VARYING_INIT(v_coverages, half2);
|
||||
VARYING_INIT(v_coverages, COVERAGE_TYPE);
|
||||
#endif //@DRAW_INTERIOR_TRIANGLES
|
||||
VARYING_INIT(v_pathID, half);
|
||||
#endif // !@RENDER_MODE_MSAA
|
||||
@@ -304,8 +312,6 @@ VERTEX_MAIN(@drawVertexMain, Attrs, attrs, _vertexID, _instanceID)
|
||||
#elif !defined(@RENDER_MODE_MSAA)
|
||||
#ifdef @DRAW_INTERIOR_TRIANGLES
|
||||
VARYING_PACK(v_windingWeight);
|
||||
#elif defined(@ENABLE_FEATHER)
|
||||
VARYING_PACK(v_coverages);
|
||||
#else
|
||||
VARYING_PACK(v_coverages);
|
||||
#endif //@DRAW_INTERIOR_TRIANGLES
|
||||
@@ -326,9 +332,12 @@ VERTEX_MAIN(@drawVertexMain, Attrs, attrs, _vertexID, _instanceID)
|
||||
#endif
|
||||
|
||||
#ifdef @FRAGMENT
|
||||
|
||||
FRAG_STORAGE_BUFFER_BLOCK_BEGIN
|
||||
FRAG_STORAGE_BUFFER_BLOCK_END
|
||||
|
||||
// Add a function here for fragments to unpack the paint since we're the ones
|
||||
// who packed it in the vertex shader.
|
||||
INLINE half4 find_paint_color(float4 paint,
|
||||
float coverage FRAGMENT_CONTEXT_DECL)
|
||||
{
|
||||
@@ -382,339 +391,55 @@ INLINE half4 find_paint_color(float4 paint,
|
||||
return color;
|
||||
}
|
||||
|
||||
#ifndef @RENDER_MODE_MSAA
|
||||
#ifndef @DRAW_INTERIOR_TRIANGLES
|
||||
|
||||
PLS_BLOCK_BEGIN
|
||||
PLS_DECL4F(COLOR_PLANE_IDX, colorBuffer);
|
||||
PLS_DECLUI(CLIP_PLANE_IDX, clipBuffer);
|
||||
PLS_DECL4F(SCRATCH_COLOR_PLANE_IDX, scratchColorBuffer);
|
||||
PLS_DECLUI(COVERAGE_PLANE_IDX, coverageCountBuffer);
|
||||
PLS_BLOCK_END
|
||||
|
||||
PLS_MAIN(@drawFragmentMain)
|
||||
// Add functions here for fragments to unpack and evaluate coverage since we're
|
||||
// the ones who packed the coverage components in the vertex shader.
|
||||
INLINE half find_stroke_coverage(COVERAGE_TYPE coverages TEXTURE_CONTEXT_DECL)
|
||||
{
|
||||
VARYING_UNPACK(v_paint, float4);
|
||||
|
||||
#ifdef @ATLAS_BLIT
|
||||
VARYING_UNPACK(v_atlasCoord, float2);
|
||||
#elif !defined(@RENDER_MODE_MSAA)
|
||||
#ifdef @DRAW_INTERIOR_TRIANGLES
|
||||
VARYING_UNPACK(v_windingWeight, half);
|
||||
#elif defined(@ENABLE_FEATHER)
|
||||
VARYING_UNPACK(v_coverages, float4);
|
||||
#else
|
||||
VARYING_UNPACK(v_coverages, half2);
|
||||
#endif //@DRAW_INTERIOR_TRIANGLES
|
||||
VARYING_UNPACK(v_pathID, half);
|
||||
#endif // !@RENDER_MODE_MSAA
|
||||
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
VARYING_UNPACK(v_clipIDs, half2);
|
||||
#endif
|
||||
#ifdef @ENABLE_CLIP_RECT
|
||||
VARYING_UNPACK(v_clipRect, float4);
|
||||
#endif
|
||||
#ifdef @ENABLE_ADVANCED_BLEND
|
||||
VARYING_UNPACK(v_blendMode, half);
|
||||
#endif
|
||||
|
||||
#if !defined(@DRAW_INTERIOR_TRIANGLES) || defined(@ATLAS_BLIT)
|
||||
// Interior triangles don't overlap, so don't need raster ordering.
|
||||
PLS_INTERLOCK_BEGIN;
|
||||
#endif
|
||||
|
||||
half coverage;
|
||||
#ifdef @ATLAS_BLIT
|
||||
coverage = filter_feather_atlas(
|
||||
v_atlasCoord,
|
||||
uniforms.atlasTextureInverseSize TEXTURE_CONTEXT_FORWARD);
|
||||
#else
|
||||
half2 coverageData = unpackHalf2x16(PLS_LOADUI(coverageCountBuffer));
|
||||
half coverageBufferID = coverageData.g;
|
||||
half coverageCount =
|
||||
coverageBufferID == v_pathID ? coverageData.r : make_half(.0);
|
||||
|
||||
#ifdef @DRAW_INTERIOR_TRIANGLES
|
||||
coverageCount += v_windingWeight;
|
||||
PLS_PRESERVE_UI(coverageCountBuffer);
|
||||
#else
|
||||
if (is_stroke(v_coverages))
|
||||
{
|
||||
half fragCoverage;
|
||||
#ifdef @ENABLE_FEATHER
|
||||
if (@ENABLE_FEATHER && is_feathered_stroke(v_coverages))
|
||||
{
|
||||
fragCoverage =
|
||||
eval_feathered_stroke(v_coverages TEXTURE_CONTEXT_FORWARD);
|
||||
}
|
||||
else
|
||||
if (@ENABLE_FEATHER && is_feathered_stroke(coverages))
|
||||
return eval_feathered_stroke(coverages TEXTURE_CONTEXT_FORWARD);
|
||||
else
|
||||
#endif // @ENABLE_FEATHER
|
||||
{
|
||||
fragCoverage = min(v_coverages.x, v_coverages.y);
|
||||
}
|
||||
coverageCount = max(fragCoverage, coverageCount);
|
||||
}
|
||||
else // Fill. (Back-face culling handles the sign of v_coverages.x.)
|
||||
{
|
||||
half fragCoverage;
|
||||
#if defined(@ENABLE_FEATHER)
|
||||
if (@ENABLE_FEATHER && is_feathered_fill(v_coverages))
|
||||
{
|
||||
fragCoverage =
|
||||
eval_feathered_fill(v_coverages TEXTURE_CONTEXT_FORWARD);
|
||||
}
|
||||
else
|
||||
#endif // @CLOCKWISE_FILL && @ENABLE_FEATHER
|
||||
{
|
||||
fragCoverage = v_coverages.x;
|
||||
}
|
||||
coverageCount += fragCoverage;
|
||||
}
|
||||
return min(coverages.x, coverages.y);
|
||||
}
|
||||
|
||||
INLINE half find_fill_coverage(COVERAGE_TYPE coverages TEXTURE_CONTEXT_DECL)
|
||||
{
|
||||
#if defined(@ENABLE_FEATHER)
|
||||
if (@ENABLE_FEATHER && is_feathered_fill(coverages))
|
||||
return eval_feathered_fill(coverages TEXTURE_CONTEXT_FORWARD);
|
||||
else
|
||||
#endif // @ENABLE_FEATHER
|
||||
return coverages.x;
|
||||
}
|
||||
|
||||
INLINE half find_frag_coverage(COVERAGE_TYPE coverages TEXTURE_CONTEXT_DECL)
|
||||
{
|
||||
if (is_stroke(coverages))
|
||||
return find_stroke_coverage(coverages TEXTURE_CONTEXT_FORWARD);
|
||||
else // Fill. (Back-face culling handles the sign of coverages.x.)
|
||||
return find_fill_coverage(coverages TEXTURE_CONTEXT_FORWARD);
|
||||
}
|
||||
|
||||
INLINE half apply_frag_coverage(half initialCoverage,
|
||||
COVERAGE_TYPE coverages TEXTURE_CONTEXT_DECL)
|
||||
{
|
||||
if (is_stroke(coverages))
|
||||
{
|
||||
half fragCoverage =
|
||||
find_stroke_coverage(coverages TEXTURE_CONTEXT_FORWARD);
|
||||
return max(fragCoverage, initialCoverage);
|
||||
}
|
||||
else // Fill. (Back-face culling handles the sign of coverages.x.)
|
||||
{
|
||||
half fragCoverage =
|
||||
find_fill_coverage(coverages TEXTURE_CONTEXT_FORWARD);
|
||||
return initialCoverage + fragCoverage;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the updated coverage.
|
||||
PLS_STOREUI(coverageCountBuffer,
|
||||
packHalf2x16(make_half2(coverageCount, v_pathID)));
|
||||
#endif // !@DRAW_INTERIOR_TRIANGLES
|
||||
|
||||
// Convert coverageCount to coverage.
|
||||
#ifdef @CLOCKWISE_FILL
|
||||
if (@CLOCKWISE_FILL)
|
||||
{
|
||||
#ifdef @VULKAN_VENDOR_ID
|
||||
if (@VULKAN_VENDOR_ID == VULKAN_VENDOR_ARM)
|
||||
{
|
||||
// ARM hits a bug if we use clamp() here.
|
||||
if (coverageCount < .0)
|
||||
coverage = .0;
|
||||
else if (coverageCount <= 1.)
|
||||
coverage = coverageCount;
|
||||
else
|
||||
coverage = 1.;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
coverage = clamp(coverageCount, make_half(.0), make_half(1.));
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // CLOCKWISE_FILL
|
||||
{
|
||||
coverage = abs(coverageCount);
|
||||
#ifdef @ENABLE_EVEN_ODD
|
||||
if (@ENABLE_EVEN_ODD && v_pathID < .0 /*even-odd*/)
|
||||
{
|
||||
coverage = 1. - make_half(abs(fract(coverage * .5) * 2. + -1.));
|
||||
}
|
||||
#endif
|
||||
// This also caps stroke coverage, which can be >1.
|
||||
coverage = min(coverage, make_half(1.));
|
||||
}
|
||||
#endif // !@ATLAS_BLIT
|
||||
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
if (@ENABLE_CLIPPING && v_clipIDs.x < .0) // Update the clip buffer.
|
||||
{
|
||||
half clipID = -v_clipIDs.x;
|
||||
#ifdef @ENABLE_NESTED_CLIPPING
|
||||
if (@ENABLE_NESTED_CLIPPING)
|
||||
{
|
||||
half outerClipID = v_clipIDs.y;
|
||||
if (outerClipID != .0)
|
||||
{
|
||||
// This is a nested clip. Intersect coverage with the enclosing
|
||||
// clip (outerClipID).
|
||||
half2 clipData = unpackHalf2x16(PLS_LOADUI(clipBuffer));
|
||||
half clipContentID = clipData.g;
|
||||
half outerClipCoverage;
|
||||
if (clipContentID != clipID)
|
||||
{
|
||||
// First hit: either clipBuffer contains outerClipCoverage,
|
||||
// or this pixel is not inside the outer clip and
|
||||
// outerClipCoverage is zero.
|
||||
outerClipCoverage =
|
||||
clipContentID == outerClipID ? clipData.r : .0;
|
||||
#ifndef @DRAW_INTERIOR_TRIANGLES
|
||||
// Stash outerClipCoverage before overwriting clipBuffer, in
|
||||
// case we hit this pixel again and need it. (Not necessary
|
||||
// when drawing interior triangles because they always go
|
||||
// last and don't overlap.)
|
||||
PLS_STORE4F(scratchColorBuffer,
|
||||
make_half4(outerClipCoverage, .0, .0, .0));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Subsequent hit: outerClipCoverage is stashed in
|
||||
// scratchColorBuffer.
|
||||
outerClipCoverage = PLS_LOAD4F(scratchColorBuffer).r;
|
||||
#ifndef @DRAW_INTERIOR_TRIANGLES
|
||||
// Since interior triangles are always last, there's no need
|
||||
// to preserve this value.
|
||||
PLS_PRESERVE_4F(scratchColorBuffer);
|
||||
#endif
|
||||
}
|
||||
coverage = min(coverage, outerClipCoverage);
|
||||
}
|
||||
}
|
||||
#endif // @ENABLE_NESTED_CLIPPING
|
||||
PLS_STOREUI(clipBuffer, packHalf2x16(make_half2(coverage, clipID)));
|
||||
PLS_PRESERVE_4F(colorBuffer);
|
||||
}
|
||||
else // Render to the main framebuffer.
|
||||
#endif // @ENABLE_CLIPPING
|
||||
{
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
if (@ENABLE_CLIPPING)
|
||||
{
|
||||
// Apply the clip.
|
||||
half clipID = v_clipIDs.x;
|
||||
if (clipID != .0)
|
||||
{
|
||||
// Clip IDs are not necessarily drawn in monotonically
|
||||
// increasing order, so always check exact equality of the
|
||||
// clipID.
|
||||
half2 clipData = unpackHalf2x16(PLS_LOADUI(clipBuffer));
|
||||
half clipContentID = clipData.g;
|
||||
coverage = (clipContentID == clipID) ? min(clipData.r, coverage)
|
||||
: make_half(.0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef @ENABLE_CLIP_RECT
|
||||
if (@ENABLE_CLIP_RECT)
|
||||
{
|
||||
half clipRectCoverage = min_value(cast_float4_to_half4(v_clipRect));
|
||||
coverage = clamp(clipRectCoverage, make_half(.0), coverage);
|
||||
}
|
||||
#endif // ENABLE_CLIP_RECT
|
||||
|
||||
half4 color =
|
||||
find_paint_color(v_paint, coverage FRAGMENT_CONTEXT_UNPACK);
|
||||
|
||||
half4 dstColorPremul;
|
||||
#ifdef @ATLAS_BLIT
|
||||
dstColorPremul = PLS_LOAD4F(colorBuffer);
|
||||
#else
|
||||
if (coverageBufferID != v_pathID)
|
||||
{
|
||||
// This is the first fragment from pathID to touch this pixel.
|
||||
dstColorPremul = PLS_LOAD4F(colorBuffer);
|
||||
#ifndef @DRAW_INTERIOR_TRIANGLES
|
||||
// We don't need to store coverage when drawing interior triangles
|
||||
// because they always go last and don't overlap, so every fragment
|
||||
// is the final one in the path.
|
||||
PLS_STORE4F(scratchColorBuffer, dstColorPremul);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
dstColorPremul = PLS_LOAD4F(scratchColorBuffer);
|
||||
#ifndef @DRAW_INTERIOR_TRIANGLES
|
||||
// Since interior triangles are always last, there's no need to
|
||||
// preserve this value.
|
||||
PLS_PRESERVE_4F(scratchColorBuffer);
|
||||
#endif
|
||||
}
|
||||
#endif // @ATLAS_BLIT
|
||||
|
||||
// Blend with the framebuffer color.
|
||||
#ifdef @ENABLE_ADVANCED_BLEND
|
||||
if (@ENABLE_ADVANCED_BLEND)
|
||||
{
|
||||
// GENERATE_PREMULTIPLIED_PAINT_COLORS is false in this case because
|
||||
// advanced blend needs unmultiplied colors.
|
||||
if (v_blendMode != cast_uint_to_half(BLEND_SRC_OVER))
|
||||
{
|
||||
color.rgb =
|
||||
advanced_color_blend(color.rgb,
|
||||
dstColorPremul,
|
||||
cast_half_to_ushort(v_blendMode));
|
||||
}
|
||||
// Premultiply alpha now.
|
||||
color.rgb *= color.a;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Certain platforms give us less control of the format of what we are
|
||||
// rendering too. Specifically, we are auto converted from linear ->
|
||||
// sRGB on render target writes in unreal. In those cases we made need
|
||||
// to end up in linear color space
|
||||
#ifdef @NEEDS_GAMMA_CORRECTION
|
||||
if (@NEEDS_GAMMA_CORRECTION)
|
||||
{
|
||||
color = gamma_to_linear(color);
|
||||
}
|
||||
#endif
|
||||
|
||||
color += dstColorPremul * (1. - color.a);
|
||||
|
||||
PLS_STORE4F(colorBuffer, color);
|
||||
PLS_PRESERVE_UI(clipBuffer);
|
||||
}
|
||||
|
||||
#if !defined(@DRAW_INTERIOR_TRIANGLES) || defined(@ATLAS_BLIT)
|
||||
// Interior triangles don't overlap, so don't need raster ordering.
|
||||
PLS_INTERLOCK_END;
|
||||
#endif
|
||||
|
||||
EMIT_PLS;
|
||||
}
|
||||
|
||||
#else // !@RENDER_MODE_MSAA => @RENDER_MODE_MSAA
|
||||
|
||||
FRAG_DATA_MAIN(half4, @drawFragmentMain)
|
||||
{
|
||||
VARYING_UNPACK(v_paint, float4);
|
||||
#ifdef @ATLAS_BLIT
|
||||
VARYING_UNPACK(v_atlasCoord, float2);
|
||||
#endif
|
||||
#ifdef @ENABLE_ADVANCED_BLEND
|
||||
VARYING_UNPACK(v_blendMode, half);
|
||||
#endif
|
||||
|
||||
half coverage =
|
||||
#ifdef @ATLAS_BLIT
|
||||
filter_feather_atlas(
|
||||
v_atlasCoord,
|
||||
uniforms.atlasTextureInverseSize TEXTURE_CONTEXT_FORWARD);
|
||||
#else
|
||||
1.;
|
||||
#endif
|
||||
half4 color = find_paint_color(v_paint, coverage FRAGMENT_CONTEXT_UNPACK);
|
||||
|
||||
#if defined(@ENABLE_ADVANCED_BLEND) && !defined(@FIXED_FUNCTION_COLOR_OUTPUT)
|
||||
if (@ENABLE_ADVANCED_BLEND)
|
||||
{
|
||||
// Do the color portion of the blend mode in the shader.
|
||||
//
|
||||
// NOTE: "color" is already unmultiplied because
|
||||
// GENERATE_PREMULTIPLIED_PAINT_COLORS is false when using advanced
|
||||
// blend.
|
||||
half4 dstColorPremul = DST_COLOR_FETCH(@dstColorTexture);
|
||||
color.rgb = advanced_color_blend(color.rgb,
|
||||
dstColorPremul,
|
||||
cast_half_to_ushort(v_blendMode));
|
||||
// Src-over blending is enabled, so just premultiply and let the HW
|
||||
// finish the the the alpha portion of the blend mode.
|
||||
color.rgb *= color.a;
|
||||
}
|
||||
#endif // @ENABLE_ADVANCED_BLEND && !@FIXED_FUNCTION_COLOR_OUTPUT
|
||||
|
||||
// Certain platforms give us less control of the format of what we are
|
||||
// rendering too. Specifically, we are auto converted from linear -> sRGB on
|
||||
// render target writes in unreal. In those cases we made need to end up in
|
||||
// linear color space
|
||||
#ifdef @NEEDS_GAMMA_CORRECTION
|
||||
if (@NEEDS_GAMMA_CORRECTION)
|
||||
{
|
||||
color = gamma_to_linear(color);
|
||||
}
|
||||
#endif
|
||||
|
||||
EMIT_FRAG_DATA(color);
|
||||
}
|
||||
|
||||
#endif // @RENDER_MODE_MSAA
|
||||
|
||||
#endif // FRAGMENT
|
||||
#endif // @FRAGMENT
|
||||
87
renderer/src/shaders/draw_raster_order_image_mesh.frag
Normal file
87
renderer/src/shaders/draw_raster_order_image_mesh.frag
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2023 Rive
|
||||
*/
|
||||
|
||||
#ifdef @FRAGMENT
|
||||
|
||||
PLS_BLOCK_BEGIN
|
||||
PLS_DECL4F(COLOR_PLANE_IDX, colorBuffer);
|
||||
PLS_DECLUI(CLIP_PLANE_IDX, clipBuffer);
|
||||
PLS_DECL4F(SCRATCH_COLOR_PLANE_IDX, scratchColorBuffer);
|
||||
PLS_DECLUI(COVERAGE_PLANE_IDX, coverageCountBuffer);
|
||||
PLS_BLOCK_END
|
||||
|
||||
FRAG_TEXTURE_BLOCK_BEGIN
|
||||
TEXTURE_RGBA8(PER_DRAW_BINDINGS_SET, IMAGE_TEXTURE_IDX, @imageTexture);
|
||||
FRAG_TEXTURE_BLOCK_END
|
||||
|
||||
DYNAMIC_SAMPLER_BLOCK_BEGIN
|
||||
SAMPLER_DYNAMIC(PER_DRAW_BINDINGS_SET, IMAGE_SAMPLER_IDX, imageSampler)
|
||||
DYNAMIC_SAMPLER_BLOCK_END
|
||||
|
||||
FRAG_STORAGE_BUFFER_BLOCK_BEGIN
|
||||
FRAG_STORAGE_BUFFER_BLOCK_END
|
||||
|
||||
PLS_MAIN_WITH_IMAGE_UNIFORMS(@drawFragmentMain)
|
||||
{
|
||||
VARYING_UNPACK(v_texCoord, float2);
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
VARYING_UNPACK(v_clipID, half);
|
||||
#endif
|
||||
#ifdef @ENABLE_CLIP_RECT
|
||||
VARYING_UNPACK(v_clipRect, float4);
|
||||
#endif
|
||||
|
||||
half4 color = TEXTURE_SAMPLE_DYNAMIC_LODBIAS(@imageTexture,
|
||||
imageSampler,
|
||||
v_texCoord,
|
||||
uniforms.mipMapLODBias);
|
||||
|
||||
half coverage = 1.;
|
||||
|
||||
#ifdef @ENABLE_CLIP_RECT
|
||||
if (@ENABLE_CLIP_RECT)
|
||||
{
|
||||
half clipRectCoverage = min_value(cast_float4_to_half4(v_clipRect));
|
||||
coverage = clamp(clipRectCoverage, make_half(.0), coverage);
|
||||
}
|
||||
#endif
|
||||
|
||||
PLS_INTERLOCK_BEGIN;
|
||||
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
if (@ENABLE_CLIPPING && v_clipID != .0)
|
||||
{
|
||||
half2 clipData = unpackHalf2x16(PLS_LOADUI(clipBuffer));
|
||||
half clipContentID = clipData.g;
|
||||
half clipCoverage =
|
||||
clipContentID == v_clipID ? clipData.r : make_half(.0);
|
||||
coverage = min(coverage, clipCoverage);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Blend with the framebuffer color.
|
||||
half4 dstColorPremul = PLS_LOAD4F(colorBuffer);
|
||||
#ifdef @ENABLE_ADVANCED_BLEND
|
||||
if (@ENABLE_ADVANCED_BLEND && imageDrawUniforms.blendMode != BLEND_SRC_OVER)
|
||||
{
|
||||
color.rgb = advanced_color_blend(
|
||||
unmultiply_rgb(color),
|
||||
dstColorPremul,
|
||||
cast_uint_to_ushort(imageDrawUniforms.blendMode)) *
|
||||
color.a;
|
||||
}
|
||||
#endif
|
||||
color *= imageDrawUniforms.opacity * coverage;
|
||||
color += dstColorPremul * (1. - color.a);
|
||||
|
||||
PLS_STORE4F(colorBuffer, color);
|
||||
PLS_PRESERVE_UI(clipBuffer);
|
||||
PLS_PRESERVE_UI(coverageCountBuffer);
|
||||
|
||||
PLS_INTERLOCK_END;
|
||||
|
||||
EMIT_PLS;
|
||||
}
|
||||
|
||||
#endif // @FRAGMENT
|
||||
254
renderer/src/shaders/draw_raster_order_path.frag
Normal file
254
renderer/src/shaders/draw_raster_order_path.frag
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright 2022 Rive
|
||||
*/
|
||||
|
||||
#ifdef @FRAGMENT
|
||||
|
||||
PLS_BLOCK_BEGIN
|
||||
PLS_DECL4F(COLOR_PLANE_IDX, colorBuffer);
|
||||
PLS_DECLUI(CLIP_PLANE_IDX, clipBuffer);
|
||||
PLS_DECL4F(SCRATCH_COLOR_PLANE_IDX, scratchColorBuffer);
|
||||
PLS_DECLUI(COVERAGE_PLANE_IDX, coverageCountBuffer);
|
||||
PLS_BLOCK_END
|
||||
|
||||
PLS_MAIN(@drawFragmentMain)
|
||||
{
|
||||
VARYING_UNPACK(v_paint, float4);
|
||||
|
||||
#ifdef @ATLAS_BLIT
|
||||
VARYING_UNPACK(v_atlasCoord, float2);
|
||||
#else
|
||||
#ifdef @DRAW_INTERIOR_TRIANGLES
|
||||
VARYING_UNPACK(v_windingWeight, half);
|
||||
#else
|
||||
VARYING_UNPACK(v_coverages, COVERAGE_TYPE);
|
||||
#endif //@DRAW_INTERIOR_TRIANGLES
|
||||
VARYING_UNPACK(v_pathID, half);
|
||||
#endif
|
||||
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
VARYING_UNPACK(v_clipIDs, half2);
|
||||
#endif
|
||||
#ifdef @ENABLE_CLIP_RECT
|
||||
VARYING_UNPACK(v_clipRect, float4);
|
||||
#endif
|
||||
#ifdef @ENABLE_ADVANCED_BLEND
|
||||
VARYING_UNPACK(v_blendMode, half);
|
||||
#endif
|
||||
|
||||
#if !defined(@DRAW_INTERIOR_TRIANGLES) || defined(@ATLAS_BLIT)
|
||||
// Interior triangles don't overlap, so don't need raster ordering.
|
||||
PLS_INTERLOCK_BEGIN;
|
||||
#endif
|
||||
|
||||
half coverage;
|
||||
#ifdef @ATLAS_BLIT
|
||||
coverage = filter_feather_atlas(
|
||||
v_atlasCoord,
|
||||
uniforms.atlasTextureInverseSize TEXTURE_CONTEXT_FORWARD);
|
||||
#else
|
||||
half2 coverageData = unpackHalf2x16(PLS_LOADUI(coverageCountBuffer));
|
||||
half coverageBufferID = coverageData.g;
|
||||
half coverageCount =
|
||||
coverageBufferID == v_pathID ? coverageData.r : make_half(.0);
|
||||
|
||||
#ifdef @DRAW_INTERIOR_TRIANGLES
|
||||
coverageCount += v_windingWeight;
|
||||
// Preserve the coverage buffer even though we don't use it, so it doesn't
|
||||
// get overwritten in a way that would corrupt a future draw (e.g., by
|
||||
// accidentally writing the next path's id with a bogus coverage.)
|
||||
PLS_PRESERVE_UI(coverageCountBuffer);
|
||||
#else
|
||||
coverageCount =
|
||||
apply_frag_coverage(coverageCount, v_coverages TEXTURE_CONTEXT_FORWARD);
|
||||
// Save the updated coverage.
|
||||
PLS_STOREUI(coverageCountBuffer,
|
||||
packHalf2x16(make_half2(coverageCount, v_pathID)));
|
||||
#endif // !@DRAW_INTERIOR_TRIANGLES
|
||||
|
||||
// Convert coverageCount to coverage.
|
||||
#ifdef @CLOCKWISE_FILL
|
||||
if (@CLOCKWISE_FILL)
|
||||
{
|
||||
#ifdef @VULKAN_VENDOR_ID
|
||||
if (@VULKAN_VENDOR_ID == VULKAN_VENDOR_ARM)
|
||||
{
|
||||
// ARM hits a bug if we use clamp() here.
|
||||
if (coverageCount < .0)
|
||||
coverage = .0;
|
||||
else if (coverageCount <= 1.)
|
||||
coverage = coverageCount;
|
||||
else
|
||||
coverage = 1.;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
coverage = clamp(coverageCount, make_half(.0), make_half(1.));
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // CLOCKWISE_FILL
|
||||
{
|
||||
coverage = abs(coverageCount);
|
||||
#ifdef @ENABLE_EVEN_ODD
|
||||
if (@ENABLE_EVEN_ODD && v_pathID < .0 /*even-odd*/)
|
||||
{
|
||||
coverage = 1. - make_half(abs(fract(coverage * .5) * 2. + -1.));
|
||||
}
|
||||
#endif
|
||||
// This also caps stroke coverage, which can be >1.
|
||||
coverage = min(coverage, make_half(1.));
|
||||
}
|
||||
#endif // !@ATLAS_BLIT
|
||||
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
if (@ENABLE_CLIPPING && v_clipIDs.x < .0) // Update the clip buffer.
|
||||
{
|
||||
half clipID = -v_clipIDs.x;
|
||||
#ifdef @ENABLE_NESTED_CLIPPING
|
||||
if (@ENABLE_NESTED_CLIPPING)
|
||||
{
|
||||
half outerClipID = v_clipIDs.y;
|
||||
if (outerClipID != .0)
|
||||
{
|
||||
// This is a nested clip. Intersect coverage with the enclosing
|
||||
// clip (outerClipID).
|
||||
half2 clipData = unpackHalf2x16(PLS_LOADUI(clipBuffer));
|
||||
half clipContentID = clipData.g;
|
||||
half outerClipCoverage;
|
||||
if (clipContentID != clipID)
|
||||
{
|
||||
// First hit: either clipBuffer contains outerClipCoverage,
|
||||
// or this pixel is not inside the outer clip and
|
||||
// outerClipCoverage is zero.
|
||||
outerClipCoverage =
|
||||
clipContentID == outerClipID ? clipData.r : .0;
|
||||
#ifndef @DRAW_INTERIOR_TRIANGLES
|
||||
// Stash outerClipCoverage before overwriting clipBuffer, in
|
||||
// case we hit this pixel again and need it. (Not necessary
|
||||
// when drawing interior triangles because they always go
|
||||
// last and don't overlap.)
|
||||
PLS_STORE4F(scratchColorBuffer,
|
||||
make_half4(outerClipCoverage, .0, .0, .0));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Subsequent hit: outerClipCoverage is stashed in
|
||||
// scratchColorBuffer.
|
||||
outerClipCoverage = PLS_LOAD4F(scratchColorBuffer).r;
|
||||
#ifndef @DRAW_INTERIOR_TRIANGLES
|
||||
// Since interior triangles are always last, there's no need
|
||||
// to preserve this value.
|
||||
PLS_PRESERVE_4F(scratchColorBuffer);
|
||||
#endif
|
||||
}
|
||||
coverage = min(coverage, outerClipCoverage);
|
||||
}
|
||||
}
|
||||
#endif // @ENABLE_NESTED_CLIPPING
|
||||
PLS_STOREUI(clipBuffer, packHalf2x16(make_half2(coverage, clipID)));
|
||||
PLS_PRESERVE_4F(colorBuffer);
|
||||
}
|
||||
else // Render to the main framebuffer.
|
||||
#endif // @ENABLE_CLIPPING
|
||||
{
|
||||
#ifdef @ENABLE_CLIPPING
|
||||
if (@ENABLE_CLIPPING)
|
||||
{
|
||||
// Apply the clip.
|
||||
half clipID = v_clipIDs.x;
|
||||
if (clipID != .0)
|
||||
{
|
||||
// Clip IDs are not necessarily drawn in monotonically
|
||||
// increasing order, so always check exact equality of the
|
||||
// clipID.
|
||||
half2 clipData = unpackHalf2x16(PLS_LOADUI(clipBuffer));
|
||||
half clipContentID = clipData.g;
|
||||
coverage = (clipContentID == clipID) ? min(clipData.r, coverage)
|
||||
: make_half(.0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef @ENABLE_CLIP_RECT
|
||||
if (@ENABLE_CLIP_RECT)
|
||||
{
|
||||
half clipRectCoverage = min_value(cast_float4_to_half4(v_clipRect));
|
||||
coverage = clamp(clipRectCoverage, make_half(.0), coverage);
|
||||
}
|
||||
#endif // ENABLE_CLIP_RECT
|
||||
|
||||
half4 color =
|
||||
find_paint_color(v_paint, coverage FRAGMENT_CONTEXT_UNPACK);
|
||||
|
||||
half4 dstColorPremul;
|
||||
#ifdef @ATLAS_BLIT
|
||||
dstColorPremul = PLS_LOAD4F(colorBuffer);
|
||||
#else
|
||||
if (coverageBufferID != v_pathID)
|
||||
{
|
||||
// This is the first fragment from pathID to touch this pixel.
|
||||
dstColorPremul = PLS_LOAD4F(colorBuffer);
|
||||
#ifndef @DRAW_INTERIOR_TRIANGLES
|
||||
// We don't need to store coverage when drawing interior triangles
|
||||
// because they always go last and don't overlap, so every fragment
|
||||
// is the final one in the path.
|
||||
PLS_STORE4F(scratchColorBuffer, dstColorPremul);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
dstColorPremul = PLS_LOAD4F(scratchColorBuffer);
|
||||
#ifndef @DRAW_INTERIOR_TRIANGLES
|
||||
// Since interior triangles are always last, there's no need to
|
||||
// preserve this value.
|
||||
PLS_PRESERVE_4F(scratchColorBuffer);
|
||||
#endif
|
||||
}
|
||||
#endif // @ATLAS_BLIT
|
||||
|
||||
// Blend with the framebuffer color.
|
||||
#ifdef @ENABLE_ADVANCED_BLEND
|
||||
if (@ENABLE_ADVANCED_BLEND)
|
||||
{
|
||||
// GENERATE_PREMULTIPLIED_PAINT_COLORS is false in this case because
|
||||
// advanced blend needs unmultiplied colors.
|
||||
if (v_blendMode != cast_uint_to_half(BLEND_SRC_OVER))
|
||||
{
|
||||
color.rgb =
|
||||
advanced_color_blend(color.rgb,
|
||||
dstColorPremul,
|
||||
cast_half_to_ushort(v_blendMode));
|
||||
}
|
||||
// Premultiply alpha now.
|
||||
color.rgb *= color.a;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Certain platforms give us less control of the format of what we are
|
||||
// rendering too. Specifically, we are auto converted from linear ->
|
||||
// sRGB on render target writes in unreal. In those cases we made need
|
||||
// to end up in linear color space
|
||||
#ifdef @NEEDS_GAMMA_CORRECTION
|
||||
if (@NEEDS_GAMMA_CORRECTION)
|
||||
{
|
||||
color = gamma_to_linear(color);
|
||||
}
|
||||
#endif
|
||||
|
||||
color += dstColorPremul * (1. - color.a);
|
||||
|
||||
PLS_STORE4F(colorBuffer, color);
|
||||
PLS_PRESERVE_UI(clipBuffer);
|
||||
}
|
||||
|
||||
#if !defined(@DRAW_INTERIOR_TRIANGLES) || defined(@ATLAS_BLIT)
|
||||
// Interior triangles don't overlap, so don't need raster ordering.
|
||||
PLS_INTERLOCK_END;
|
||||
#endif
|
||||
|
||||
EMIT_PLS;
|
||||
}
|
||||
|
||||
#endif // FRAGMENT
|
||||
@@ -87,12 +87,14 @@ def emit_shader(out, shader_type, draw_type, fill_type, feature_set):
|
||||
('c' if fill_type == FillType.CLOCKWISE else 'p',
|
||||
''.join(namespace_id)))
|
||||
out.write('{\n')
|
||||
out.write('#include "draw_path.minified.glsl"\n')
|
||||
out.write('#include "draw_path.minified.vert"\n')
|
||||
out.write('#include "draw_raster_order_path.minified.frag"\n')
|
||||
out.write('}\n')
|
||||
else:
|
||||
out.write('namespace m%s\n' % ''.join(namespace_id))
|
||||
out.write('{\n')
|
||||
out.write('#include "draw_image_mesh.minified.glsl"\n')
|
||||
out.write('#include "draw_image_mesh.minified.vert"\n')
|
||||
out.write('#include "draw_raster_order_image_mesh.minified.frag"\n')
|
||||
out.write('}\n')
|
||||
for feature in feature_set:
|
||||
out.write('#undef %s\n' % feature.name)
|
||||
|
||||
@@ -549,8 +549,8 @@ class Minifier:
|
||||
|
||||
|
||||
def write_exports(self, outdir):
|
||||
output_path = os.path.join(outdir, os.path.splitext(self.basename)[0] + ".exports.h")
|
||||
print("Exporting %s <- %s" % (output_path, self.basename))
|
||||
output_path = os.path.join(outdir, f"{self.basename}.exports.h")
|
||||
print(f"Exporting {output_path} <- {self.basename}")
|
||||
out = open(output_path, "w", newline='\n')
|
||||
out.write('#pragma once\n\n')
|
||||
for exp in sorted(self.exports):
|
||||
@@ -565,13 +565,17 @@ class Minifier:
|
||||
out = open(output_path, "w", newline='\n')
|
||||
out.write("#pragma once\n\n")
|
||||
|
||||
out.write('#include "%s"\n\n' % (os.path.splitext(self.basename)[0] + ".exports.h"))
|
||||
out.write(f'#include "{self.basename}.exports.h"\n\n')
|
||||
|
||||
# emit shader code.
|
||||
root, ext = os.path.splitext(self.basename)
|
||||
cpp_name = root
|
||||
if ext != '.glsl':
|
||||
cpp_name = f"{root}_{ext[1:]}"
|
||||
out.write("namespace rive {\n")
|
||||
out.write("namespace gpu {\n")
|
||||
out.write("namespace glsl {\n")
|
||||
out.write('const char %s[] = R"===(' % os.path.splitext(self.basename)[0])
|
||||
out.write(f'const char {cpp_name}[] = R"===(')
|
||||
|
||||
is_newline = self.emit_tokens_to_rewritten_glsl(out, preserve_exported_switches=False)
|
||||
if not is_newline:
|
||||
@@ -584,8 +588,9 @@ class Minifier:
|
||||
out.close()
|
||||
|
||||
def write_offline_glsl(self, outdir):
|
||||
output_path = os.path.join(outdir, os.path.splitext(self.basename)[0] + ".minified.glsl")
|
||||
print("Minifying %s <- %s" % (output_path, self.basename))
|
||||
root, ext = os.path.splitext(self.basename)
|
||||
output_path = os.path.join(outdir, f"{root}.minified{ext}")
|
||||
print(f"Minifying f{output_path} <- {self.basename}")
|
||||
out = open(output_path, "w", newline='\n')
|
||||
self.emit_tokens_to_rewritten_glsl(out, preserve_exported_switches=True)
|
||||
out.close()
|
||||
|
||||
@@ -10,4 +10,5 @@
|
||||
#include "common.minified.glsl"
|
||||
#include "draw_path_common.minified.glsl"
|
||||
#include "advanced_blend.minified.glsl"
|
||||
#include "draw_path.minified.glsl"
|
||||
#include "draw_path.minified.vert"
|
||||
#include "draw_raster_order_path.minified.frag"
|
||||
|
||||
@@ -9,4 +9,5 @@
|
||||
#include "specialization.minified.glsl"
|
||||
#include "common.minified.glsl"
|
||||
#include "advanced_blend.minified.glsl"
|
||||
#include "draw_image_mesh.minified.glsl"
|
||||
#include "draw_image_mesh.minified.vert"
|
||||
#include "draw_raster_order_image_mesh.minified.frag"
|
||||
|
||||
@@ -9,4 +9,5 @@
|
||||
#include "common.minified.glsl"
|
||||
#include "draw_path_common.minified.glsl"
|
||||
#include "advanced_blend.minified.glsl"
|
||||
#include "draw_path.minified.glsl"
|
||||
#include "draw_path.minified.vert"
|
||||
#include "draw_raster_order_path.minified.frag"
|
||||
|
||||
@@ -11,4 +11,5 @@
|
||||
#include "common.minified.glsl"
|
||||
#include "draw_path_common.minified.glsl"
|
||||
#include "advanced_blend.minified.glsl"
|
||||
#include "draw_path.minified.glsl"
|
||||
#include "draw_path.minified.vert"
|
||||
#include "draw_msaa_path.minified.frag"
|
||||
|
||||
@@ -10,4 +10,5 @@
|
||||
#include "specialization.minified.glsl"
|
||||
#include "common.minified.glsl"
|
||||
#include "advanced_blend.minified.glsl"
|
||||
#include "draw_image_mesh.minified.glsl"
|
||||
#include "draw_image_mesh.minified.vert"
|
||||
#include "draw_msaa_image_mesh.minified.frag"
|
||||
|
||||
@@ -11,4 +11,5 @@
|
||||
#include "common.minified.glsl"
|
||||
#include "draw_path_common.minified.glsl"
|
||||
#include "advanced_blend.minified.glsl"
|
||||
#include "draw_path.minified.glsl"
|
||||
#include "draw_path.minified.vert"
|
||||
#include "draw_msaa_path.minified.frag"
|
||||
|
||||
@@ -10,4 +10,5 @@
|
||||
#include "common.minified.glsl"
|
||||
#include "draw_path_common.minified.glsl"
|
||||
#include "advanced_blend.minified.glsl"
|
||||
#include "draw_path.minified.glsl"
|
||||
#include "draw_path.minified.vert"
|
||||
#include "draw_raster_order_path.minified.frag"
|
||||
|
||||
@@ -14,4 +14,5 @@
|
||||
#include "Generated/constants.minified.ush"
|
||||
#include "Generated/common.minified.ush"
|
||||
#include "Generated/advanced_blend.minified.ush"
|
||||
#include "Generated/draw_image_mesh.minified.ush"
|
||||
#include "Generated/draw_image_mesh.minified.vert.ush"
|
||||
#include "Generated/draw_raster_order_image_mesh.minified.frag.ush"
|
||||
|
||||
@@ -13,4 +13,5 @@
|
||||
#include "Generated/common.minified.ush"
|
||||
#include "Generated/draw_path_common.minified.ush"
|
||||
#include "Generated/advanced_blend.minified.ush"
|
||||
#include "Generated/draw_path.minified.ush"
|
||||
#include "Generated/draw_path.minified.vert.ush"
|
||||
#include "Generated/draw_raster_order_path.minified.frag.ush"
|
||||
|
||||
@@ -15,4 +15,5 @@
|
||||
#include "Generated/common.minified.ush"
|
||||
#include "Generated/draw_path_common.minified.ush"
|
||||
#include "Generated/advanced_blend.minified.ush"
|
||||
#include "Generated/draw_path.minified.ush"
|
||||
#include "Generated/draw_path.minified.vert.ush"
|
||||
#include "Generated/draw_raster_order_path.minified.frag.ush"
|
||||
|
||||
@@ -69,9 +69,11 @@ constexpr static auto RIVE_FRONT_FACE = wgpu::FrontFace::CW;
|
||||
#include "generated/shaders/tessellate.glsl.hpp"
|
||||
#include "generated/shaders/render_atlas.glsl.hpp"
|
||||
#include "generated/shaders/advanced_blend.glsl.hpp"
|
||||
#include "generated/shaders/draw_path.glsl.hpp"
|
||||
#include "generated/shaders/draw_path_common.glsl.hpp"
|
||||
#include "generated/shaders/draw_image_mesh.glsl.hpp"
|
||||
#include "generated/shaders/draw_path.vert.hpp"
|
||||
#include "generated/shaders/draw_raster_order_path.frag.hpp"
|
||||
#include "generated/shaders/draw_image_mesh.vert.hpp"
|
||||
#include "generated/shaders/draw_raster_order_image_mesh.frag.hpp"
|
||||
|
||||
// When compiling "glslRaw" shaders, the WebGPU driver will automatically
|
||||
// search for a uniform with this name and update its value when draw commands
|
||||
@@ -845,15 +847,19 @@ public:
|
||||
case DrawType::outerCurvePatches:
|
||||
addDefine(GLSL_DRAW_PATH);
|
||||
glsl << gpu::glsl::draw_path_common << '\n';
|
||||
glsl << gpu::glsl::draw_path << '\n';
|
||||
glsl << gpu::glsl::draw_path_vert << '\n';
|
||||
glsl << gpu::glsl::draw_raster_order_path_frag << '\n';
|
||||
break;
|
||||
case DrawType::interiorTriangulation:
|
||||
case DrawType::atlasBlit:
|
||||
glsl << gpu::glsl::draw_path_common << '\n';
|
||||
glsl << gpu::glsl::draw_path << '\n';
|
||||
glsl << gpu::glsl::draw_path_vert << '\n';
|
||||
glsl << gpu::glsl::draw_raster_order_path_frag << '\n';
|
||||
break;
|
||||
case DrawType::imageMesh:
|
||||
glsl << gpu::glsl::draw_image_mesh << '\n';
|
||||
glsl << gpu::glsl::draw_image_mesh_vert << '\n';
|
||||
glsl << gpu::glsl::draw_raster_order_image_mesh_frag
|
||||
<< '\n';
|
||||
break;
|
||||
case DrawType::imageRect:
|
||||
case DrawType::msaaStrokes:
|
||||
|
||||
Reference in New Issue
Block a user