mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Upgrade WebRender to e491e1ae637b2eed1e7195855d88357e5eb3ddf9 (#30323)
* Upgrade vendored version of WebRender * Patch WebRender: upgrade version of gleam * Restore hit testing implementation * Fix WebRender warnings * Adapt Servo to new WebRender * Update results * Add a workaround for #30313 This slightly expands text boundaries in order to take into account the fact that layout isn't measuring glyph boundaries.
This commit is contained in:
parent
c079acb3c3
commit
a9d37cb85a
563 changed files with 48524 additions and 51657 deletions
2
third_party/webrender/glsl-to-cxx/Cargo.toml
vendored
2
third_party/webrender/glsl-to-cxx/Cargo.toml
vendored
|
@ -2,7 +2,7 @@
|
|||
name = "glsl-to-cxx"
|
||||
version = "0.1.0"
|
||||
license = "MPL-2.0"
|
||||
authors = ["The Mozilla Project Developers"]
|
||||
authors = ["The Mozilla Project Developers", "Dimitri Sabadie"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
|
18
third_party/webrender/glsl-to-cxx/README.md
vendored
18
third_party/webrender/glsl-to-cxx/README.md
vendored
|
@ -1,3 +1,21 @@
|
|||
A GLSL to C++ translator.
|
||||
|
||||
Translates GLSL to vectorized C++. Intended for use with WebRender software backend.
|
||||
|
||||
Architecture
|
||||
------------
|
||||
GLSL code is parsed by the glsl crate. In hir.rs we traverse the resulting AST
|
||||
and build a higher level representation by doing type checking and name
|
||||
resolution. The resulting hir tree is traversed by lib.rs to output C++ code.
|
||||
|
||||
The generated C++ code is 4x wider then the original glsl. i.e. a glsl 'float'
|
||||
becomes a C++ 'Float' which is represented by a xmm register (a vector of 4 floats).
|
||||
Likewise, a vec4 becomes a struct of 4 'Float's for a total of 4 xmm registers and
|
||||
16 floating point values.
|
||||
|
||||
Vector branching is flattened to non-branching code that unconditionally runs both
|
||||
sides of the branch and combines the results with a mask based on the condition.
|
||||
|
||||
The compiler also supports scalarization. Values that are known to be the same
|
||||
across all vector lanes are translated to scalars instead of vectors. Branches on
|
||||
scalars are translated as actual branches.
|
||||
|
|
1015
third_party/webrender/glsl-to-cxx/src/hir.rs
vendored
1015
third_party/webrender/glsl-to-cxx/src/hir.rs
vendored
File diff suppressed because it is too large
Load diff
358
third_party/webrender/glsl-to-cxx/src/lib.rs
vendored
358
third_party/webrender/glsl-to-cxx/src/lib.rs
vendored
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use glsl;
|
||||
extern crate glsl;
|
||||
|
||||
mod hir;
|
||||
|
||||
|
@ -61,8 +61,6 @@ pub fn translate(args: &mut dyn Iterator<Item = String>) -> String {
|
|||
.to_string_lossy()
|
||||
.to_string();
|
||||
|
||||
let frag_include = args.next();
|
||||
|
||||
let (vs_state, vs_hir, vs_is_frag) = parse_shader(vertex_file);
|
||||
let (fs_state, fs_hir, fs_is_frag) = parse_shader(frag_file);
|
||||
|
||||
|
@ -79,7 +77,6 @@ pub fn translate(args: &mut dyn Iterator<Item = String>) -> String {
|
|||
vs_hir,
|
||||
vs_is_frag,
|
||||
&uniform_indices,
|
||||
None,
|
||||
);
|
||||
result += "\n";
|
||||
result += &translate_shader(
|
||||
|
@ -88,7 +85,6 @@ pub fn translate(args: &mut dyn Iterator<Item = String>) -> String {
|
|||
fs_hir,
|
||||
fs_is_frag,
|
||||
&uniform_indices,
|
||||
frag_include,
|
||||
);
|
||||
result
|
||||
}
|
||||
|
@ -120,7 +116,6 @@ fn translate_shader(
|
|||
hir: hir::TranslationUnit,
|
||||
is_frag: bool,
|
||||
uniform_indices: &UniformIndices,
|
||||
include_file: Option<String>,
|
||||
) -> String {
|
||||
//println!("{:#?}", state);
|
||||
|
||||
|
@ -185,8 +180,6 @@ fn translate_shader(
|
|||
uses_discard: false,
|
||||
used_fragcoord: Cell::new(0),
|
||||
use_perspective: false,
|
||||
has_draw_span_rgba8: false,
|
||||
has_draw_span_r8: false,
|
||||
used_globals: RefCell::new(Vec::new()),
|
||||
texel_fetches: RefCell::new(Vec::new()),
|
||||
};
|
||||
|
@ -215,10 +208,6 @@ fn translate_shader(
|
|||
|
||||
show_translation_unit(&mut state, &hir);
|
||||
|
||||
if let Some(include_file) = include_file {
|
||||
write_include_file(&mut state, include_file);
|
||||
}
|
||||
|
||||
let pruned_inputs: Vec<_> = inputs
|
||||
.iter()
|
||||
.filter(|i| state.used_globals.borrow().contains(i))
|
||||
|
@ -250,6 +239,7 @@ fn translate_shader(
|
|||
write!(state, " return this;\n}}\n");
|
||||
write!(state, "FragmentShaderImpl* get_fragment_shader() override {{\n");
|
||||
write!(state, " return this;\n}}\n");
|
||||
write!(state, "const char* get_name() const override {{ return \"{}\"; }}\n", name);
|
||||
write!(state, "static ProgramImpl* loader() {{ return new {}_program; }}\n", name);
|
||||
write!(state, "}};\n\n");
|
||||
}
|
||||
|
@ -302,8 +292,7 @@ fn write_program_samplers(state: &mut OutputState, uniform_indices: &UniformIndi
|
|||
match tk {
|
||||
hir::TypeKind::Sampler2D
|
||||
| hir::TypeKind::Sampler2DRect
|
||||
| hir::TypeKind::ISampler2D
|
||||
| hir::TypeKind::Sampler2DArray => {
|
||||
| hir::TypeKind::ISampler2D => {
|
||||
write!(state, " ");
|
||||
show_type_kind(state, &tk);
|
||||
let suffix = if let hir::StorageClass::Sampler(format) = storage {
|
||||
|
@ -326,8 +315,7 @@ fn write_program_samplers(state: &mut OutputState, uniform_indices: &UniformIndi
|
|||
match tk {
|
||||
hir::TypeKind::Sampler2D
|
||||
| hir::TypeKind::Sampler2DRect
|
||||
| hir::TypeKind::ISampler2D
|
||||
| hir::TypeKind::Sampler2DArray => {
|
||||
| hir::TypeKind::ISampler2D => {
|
||||
write!(state, " case {}:\n", index);
|
||||
write!(state, " {}_slot = value;\n", name);
|
||||
write!(state, " return true;\n");
|
||||
|
@ -355,9 +343,6 @@ fn write_bind_textures(state: &mut OutputState, uniforms: &UniformIndices) {
|
|||
hir::TypeKind::ISampler2D => write!(state,
|
||||
" {0} = lookup_isampler(&samplers.{0}_impl, samplers.{0}_slot);\n",
|
||||
name),
|
||||
hir::TypeKind::Sampler2DArray => write!(state,
|
||||
" {0} = lookup_sampler_array(&samplers.{0}_impl, samplers.{0}_slot);\n",
|
||||
name),
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
@ -408,9 +393,8 @@ fn write_set_uniform_4fv(
|
|||
if float4_compatible(tk.clone()) {
|
||||
write!(
|
||||
state,
|
||||
" self->{} = {}_scalar(value);\n",
|
||||
name,
|
||||
tk.glsl_primitive_type_name().unwrap(),
|
||||
" self->{} = vec4_scalar::load_from_ptr(value);\n",
|
||||
name
|
||||
);
|
||||
} else {
|
||||
write!(state, " assert(0); // {}\n", name);
|
||||
|
@ -551,6 +535,9 @@ fn write_load_attribs(state: &mut OutputState, attribs: &[hir::SymRef]) {
|
|||
fn write_store_outputs(state: &mut OutputState, outputs: &[hir::SymRef]) {
|
||||
let is_scalar = state.is_scalar.replace(true);
|
||||
write!(state, "public:\nstruct InterpOutputs {{\n");
|
||||
if state.hir.used_clip_dist != 0 {
|
||||
state.write(" Float swgl_ClipDistance;\n");
|
||||
}
|
||||
for i in outputs {
|
||||
let sym = state.hir.sym(*i);
|
||||
match &sym.decl {
|
||||
|
@ -576,6 +563,15 @@ fn write_store_outputs(state: &mut OutputState, outputs: &[hir::SymRef]) {
|
|||
state,
|
||||
" auto* dest = reinterpret_cast<InterpOutputs*>(dest_ptr);\n"
|
||||
);
|
||||
if state.hir.used_clip_dist != 0 {
|
||||
for (i, comp) in "xyzw".chars().enumerate() {
|
||||
if (state.hir.used_clip_dist & (1 << i)) != 0 {
|
||||
write!(state, " dest->swgl_ClipDistance.{} = get_nth(gl_ClipDistance[{}], n);\n", comp, i);
|
||||
} else {
|
||||
write!(state, " dest->swgl_ClipDistance.{} = 0.0f;\n", comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
for i in outputs {
|
||||
let sym = state.hir.sym(*i);
|
||||
match &sym.decl {
|
||||
|
@ -626,7 +622,7 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) {
|
|||
|
||||
write!(state,
|
||||
"static void read_interp_inputs(\
|
||||
Self *self, const InterpInputs *init, const InterpInputs *step, float step_width) {{\n");
|
||||
Self *self, const InterpInputs *init, const InterpInputs *step) {{\n");
|
||||
for i in inputs {
|
||||
let sym = state.hir.sym(*i);
|
||||
match &sym.decl {
|
||||
|
@ -640,7 +636,7 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) {
|
|||
);
|
||||
write!(
|
||||
state,
|
||||
" self->interp_step.{0} = step->{0} * step_width;\n",
|
||||
" self->interp_step.{0} = step->{0} * 4.0f;\n",
|
||||
name
|
||||
);
|
||||
}
|
||||
|
@ -657,7 +653,7 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) {
|
|||
if state.use_perspective {
|
||||
write!(state,
|
||||
"static void read_perspective_inputs(\
|
||||
Self *self, const InterpInputs *init, const InterpInputs *step, float step_width) {{\n");
|
||||
Self *self, const InterpInputs *init, const InterpInputs *step) {{\n");
|
||||
if has_varying {
|
||||
write!(state, " Float w = 1.0f / self->gl_FragCoord.w;\n");
|
||||
}
|
||||
|
@ -675,7 +671,7 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) {
|
|||
write!(state, " self->{0} = self->interp_perspective.{0} * w;\n", name);
|
||||
write!(
|
||||
state,
|
||||
" self->interp_step.{0} = step->{0} * step_width;\n",
|
||||
" self->interp_step.{0} = step->{0} * 4.0f;\n",
|
||||
name
|
||||
);
|
||||
}
|
||||
|
@ -686,9 +682,12 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) {
|
|||
write!(state, "}}\n");
|
||||
}
|
||||
|
||||
write!(state, "ALWAYS_INLINE void step_interp_inputs() {{\n");
|
||||
write!(state, "ALWAYS_INLINE void step_interp_inputs(int steps = 4) {{\n");
|
||||
if (used_fragcoord & 1) != 0 {
|
||||
write!(state, " step_fragcoord();\n");
|
||||
write!(state, " step_fragcoord(steps);\n");
|
||||
}
|
||||
if !inputs.is_empty() {
|
||||
write!(state, " float chunks = steps * 0.25f;\n");
|
||||
}
|
||||
for i in inputs {
|
||||
let sym = state.hir.sym(*i);
|
||||
|
@ -696,7 +695,7 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) {
|
|||
hir::SymDecl::Global(_, _, _, run_class) => {
|
||||
if *run_class != hir::RunClass::Scalar {
|
||||
let name = sym.name.as_str();
|
||||
write!(state, " {0} += interp_step.{0};\n", name);
|
||||
write!(state, " {0} += interp_step.{0} * chunks;\n", name);
|
||||
}
|
||||
}
|
||||
_ => panic!(),
|
||||
|
@ -705,11 +704,14 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) {
|
|||
write!(state, "}}\n");
|
||||
|
||||
if state.use_perspective {
|
||||
write!(state, "ALWAYS_INLINE void step_perspective_inputs() {{\n");
|
||||
write!(state, "ALWAYS_INLINE void step_perspective_inputs(int steps = 4) {{\n");
|
||||
if (used_fragcoord & 1) != 0 {
|
||||
write!(state, " step_fragcoord();\n");
|
||||
write!(state, " step_fragcoord(steps);\n");
|
||||
}
|
||||
write!(state, " step_perspective(steps);\n");
|
||||
if !inputs.is_empty() {
|
||||
write!(state, " float chunks = steps * 0.25f;\n");
|
||||
}
|
||||
write!(state, " step_perspective();\n");
|
||||
if has_varying {
|
||||
write!(state, " Float w = 1.0f / gl_FragCoord.w;\n");
|
||||
}
|
||||
|
@ -719,7 +721,7 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) {
|
|||
hir::SymDecl::Global(_, _, _, run_class) => {
|
||||
if *run_class != hir::RunClass::Scalar {
|
||||
let name = sym.name.as_str();
|
||||
write!(state, " interp_perspective.{0} += interp_step.{0};\n", name);
|
||||
write!(state, " interp_perspective.{0} += interp_step.{0} * chunks;\n", name);
|
||||
write!(state, " {0} = w * interp_perspective.{0};\n", name);
|
||||
}
|
||||
}
|
||||
|
@ -728,58 +730,6 @@ fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) {
|
|||
}
|
||||
write!(state, "}}\n");
|
||||
}
|
||||
|
||||
if state.has_draw_span_rgba8 || state.has_draw_span_r8 {
|
||||
write!(
|
||||
state,
|
||||
"ALWAYS_INLINE void step_interp_inputs(int chunks) {{\n"
|
||||
);
|
||||
if (used_fragcoord & 1) != 0 {
|
||||
write!(state, " step_fragcoord(chunks);\n");
|
||||
}
|
||||
for i in inputs {
|
||||
let sym = state.hir.sym(*i);
|
||||
match &sym.decl {
|
||||
hir::SymDecl::Global(_, _, _, run_class) => {
|
||||
if *run_class != hir::RunClass::Scalar {
|
||||
let name = sym.name.as_str();
|
||||
write!(state, " {0} += interp_step.{0} * chunks;\n", name);
|
||||
}
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
write!(state, "}}\n");
|
||||
}
|
||||
}
|
||||
|
||||
fn write_include_file(state: &mut OutputState, include_file: String) {
|
||||
let include_contents = std::fs::read_to_string(&include_file).unwrap();
|
||||
|
||||
let mut offset = 0;
|
||||
while offset < include_contents.len() {
|
||||
let s = &include_contents[offset ..];
|
||||
if let Some(start_proto) = s.find("draw_span") {
|
||||
let s = &s[start_proto ..];
|
||||
if let Some(end_proto) = s.find(')') {
|
||||
let proto = &s[.. end_proto];
|
||||
if proto.contains("uint32_t") {
|
||||
state.has_draw_span_rgba8 = true;
|
||||
} else if proto.contains("uint8_t") {
|
||||
state.has_draw_span_r8 = true;
|
||||
}
|
||||
offset += start_proto + end_proto;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
let include_name = std::path::Path::new(&include_file)
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.to_string_lossy();
|
||||
write!(state, "\n#include \"{}\"\n\n", include_name);
|
||||
}
|
||||
|
||||
pub struct OutputState {
|
||||
|
@ -804,8 +754,6 @@ pub struct OutputState {
|
|||
uses_discard: bool,
|
||||
used_fragcoord: Cell<i32>,
|
||||
use_perspective: bool,
|
||||
has_draw_span_rgba8: bool,
|
||||
has_draw_span_r8: bool,
|
||||
used_globals: RefCell<Vec<hir::SymRef>>,
|
||||
texel_fetches: RefCell<Vec<(hir::SymRef, hir::SymRef, hir::TexelFetchOffsets)>>,
|
||||
}
|
||||
|
@ -874,7 +822,7 @@ fn add_used_global(state: &OutputState, i: &hir::SymRef) {
|
|||
pub fn show_sym(state: &OutputState, i: &hir::SymRef) {
|
||||
let sym = state.hir.sym(*i);
|
||||
match &sym.decl {
|
||||
hir::SymDecl::NativeFunction(_, ref cxx_name) => {
|
||||
hir::SymDecl::NativeFunction(_, ref cxx_name, _) => {
|
||||
let mut name = sym.name.as_str();
|
||||
if state.output_cxx {
|
||||
name = cxx_name.unwrap_or(name);
|
||||
|
@ -1567,8 +1515,10 @@ fn expr_run_class(state: &OutputState, expr: &hir::Expr) -> hir::RunClass {
|
|||
});
|
||||
match fun {
|
||||
hir::FunIdentifier::Identifier(ref sym) => match &state.hir.sym(*sym).decl {
|
||||
hir::SymDecl::NativeFunction(..) => {
|
||||
if arg_mask != 0 {
|
||||
hir::SymDecl::NativeFunction(_, _, ref ret_class) => {
|
||||
if *ret_class != hir::RunClass::Unknown {
|
||||
*ret_class
|
||||
} else if arg_mask != 0 {
|
||||
hir::RunClass::Vector
|
||||
} else {
|
||||
hir::RunClass::Scalar
|
||||
|
@ -1896,33 +1846,21 @@ pub fn show_hir_expr_inner(state: &OutputState, expr: &hir::Expr, top_level: boo
|
|||
&state.hir, &args[0], &args[1], &args[3],
|
||||
) {
|
||||
let base_sym = state.hir.sym(base);
|
||||
if symbol_run_class(&base_sym.decl, state.vector_mask)
|
||||
== hir::RunClass::Scalar
|
||||
{
|
||||
let sampler_sym = state.hir.sym(sampler);
|
||||
add_used_global(state, &sampler);
|
||||
if let hir::SymDecl::Global(..) = &base_sym.decl {
|
||||
add_used_global(state, &base);
|
||||
}
|
||||
if y != 0 {
|
||||
write!(
|
||||
state,
|
||||
"{}_{}_fetch[{}+{}*{}->stride]",
|
||||
sampler_sym.name,
|
||||
base_sym.name,
|
||||
x,
|
||||
y,
|
||||
sampler_sym.name
|
||||
);
|
||||
} else {
|
||||
write!(
|
||||
state,
|
||||
"{}_{}_fetch[{}]",
|
||||
sampler_sym.name, base_sym.name, x
|
||||
);
|
||||
}
|
||||
return;
|
||||
let sampler_sym = state.hir.sym(sampler);
|
||||
add_used_global(state, &sampler);
|
||||
if let hir::SymDecl::Global(..) = &base_sym.decl {
|
||||
add_used_global(state, &base);
|
||||
}
|
||||
write!(
|
||||
state,
|
||||
"texelFetchUnchecked({}, {}_{}_fetch, {}, {})",
|
||||
sampler_sym.name,
|
||||
sampler_sym.name,
|
||||
base_sym.name,
|
||||
x,
|
||||
y,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
show_sym(state, name)
|
||||
|
@ -2358,15 +2296,12 @@ pub fn show_declaration(state: &mut OutputState, d: &hir::Declaration) {
|
|||
let base = list.head.name;
|
||||
let base_sym = state.hir.sym(base);
|
||||
if let hir::SymDecl::Local(..) = &base_sym.decl {
|
||||
if symbol_run_class(&base_sym.decl, state.vector_mask) == hir::RunClass::Scalar
|
||||
let mut texel_fetches = state.texel_fetches.borrow_mut();
|
||||
while let Some(idx) = texel_fetches.iter().position(|&(_, b, _)| b == base)
|
||||
{
|
||||
let mut texel_fetches = state.texel_fetches.borrow_mut();
|
||||
while let Some(idx) = texel_fetches.iter().position(|&(_, b, _)| b == base)
|
||||
{
|
||||
let (sampler, _, offsets) = texel_fetches.remove(idx);
|
||||
let sampler_sym = state.hir.sym(sampler);
|
||||
define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets);
|
||||
}
|
||||
let (sampler, _, offsets) = texel_fetches.remove(idx);
|
||||
let sampler_sym = state.hir.sym(sampler);
|
||||
define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2384,19 +2319,22 @@ pub fn show_declaration(state: &mut OutputState, d: &hir::Declaration) {
|
|||
//state.write(";\n");
|
||||
}
|
||||
hir::Declaration::Global(ref qual, ref identifiers) => {
|
||||
show_type_qualifier(state, &qual);
|
||||
// We only want to output GLSL layout qualifiers if not C++
|
||||
if !state.output_cxx {
|
||||
show_type_qualifier(state, &qual);
|
||||
|
||||
if !identifiers.is_empty() {
|
||||
let mut iter = identifiers.iter();
|
||||
let first = iter.next().unwrap();
|
||||
show_identifier(state, first);
|
||||
if !identifiers.is_empty() {
|
||||
let mut iter = identifiers.iter();
|
||||
let first = iter.next().unwrap();
|
||||
show_identifier(state, first);
|
||||
|
||||
for identifier in iter {
|
||||
let _ = write!(state, ", {}", identifier);
|
||||
for identifier in iter {
|
||||
let _ = write!(state, ", {}", identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.write(";\n");
|
||||
state.write(";\n");
|
||||
}
|
||||
}
|
||||
hir::Declaration::StructDefinition(ref sym) => {
|
||||
show_sym_decl(state, sym);
|
||||
|
@ -2672,32 +2610,32 @@ fn define_texel_fetch_ptr(
|
|||
offsets: &hir::TexelFetchOffsets,
|
||||
) {
|
||||
show_indent(state);
|
||||
if let hir::SymDecl::Global(_, _, ty, _) = &sampler_sym.decl {
|
||||
match ty.kind {
|
||||
hir::TypeKind::Sampler2D
|
||||
| hir::TypeKind::Sampler2DRect => {
|
||||
write!(
|
||||
state,
|
||||
"vec4_scalar* {}_{}_fetch = ",
|
||||
sampler_sym.name, base_sym.name
|
||||
);
|
||||
let ptr_type = if let hir::SymDecl::Global(_, _, ty, _) = &sampler_sym.decl {
|
||||
if symbol_run_class(&base_sym.decl, state.vector_mask) == hir::RunClass::Scalar {
|
||||
match ty.kind {
|
||||
hir::TypeKind::Sampler2D
|
||||
| hir::TypeKind::Sampler2DRect => "vec4_scalar*",
|
||||
hir::TypeKind::ISampler2D => "ivec4_scalar*",
|
||||
_ => panic!(),
|
||||
}
|
||||
hir::TypeKind::ISampler2D => {
|
||||
write!(
|
||||
state,
|
||||
"ivec4_scalar* {}_{}_fetch = ",
|
||||
sampler_sym.name, base_sym.name
|
||||
);
|
||||
}
|
||||
_ => panic!(),
|
||||
} else {
|
||||
"I32"
|
||||
}
|
||||
} else {
|
||||
panic!();
|
||||
}
|
||||
};
|
||||
write!(
|
||||
state,
|
||||
"texelFetchPtr({}, {}, {}, {}, {}, {});\n",
|
||||
sampler_sym.name, base_sym.name, offsets.min_x, offsets.max_x, offsets.min_y, offsets.max_y
|
||||
"{} {}_{}_fetch = texelFetchPtr({}, {}, {}, {}, {}, {});\n",
|
||||
ptr_type,
|
||||
sampler_sym.name,
|
||||
base_sym.name,
|
||||
sampler_sym.name,
|
||||
base_sym.name,
|
||||
offsets.min_x,
|
||||
offsets.max_x,
|
||||
offsets.min_y,
|
||||
offsets.max_y,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2750,27 +2688,64 @@ pub fn show_function_definition(
|
|||
}
|
||||
|
||||
if state.output_cxx {
|
||||
match fd.prototype.name.as_str() {
|
||||
"swgl_drawSpanRGBA8" |
|
||||
"swgl_drawSpanR8" => {
|
||||
// Partial spans are not drawn using span shaders, but rather drawn with a fragment shader
|
||||
// where the span shader left off. We need to undo any changes to the interpolants made by
|
||||
// the span shaders so that we can reset the interpolants to where the fragment shader
|
||||
// expects them. We do this by saving them in an _Undo_ struct on entry to the span shader,
|
||||
// and then restore them in the _Undo_ struct destructor.
|
||||
let mut needs_undo = vec![];
|
||||
for global in &fd.globals {
|
||||
let sym = state.hir.sym(*global);
|
||||
match &sym.decl {
|
||||
hir::SymDecl::Global(hir::StorageClass::In, _, ty, hir::RunClass::Vector) => {
|
||||
if needs_undo.is_empty() {
|
||||
state.write("struct _Undo_ {\nSelf* self;\n");
|
||||
}
|
||||
show_type(state, ty);
|
||||
write!(state, " {};\n", sym.name);
|
||||
needs_undo.push(sym.name.clone());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if !needs_undo.is_empty() {
|
||||
state.write("explicit _Undo_(Self* self) : self(self)");
|
||||
for name in &needs_undo {
|
||||
write!(state, ", {0}(self->{0})", name);
|
||||
}
|
||||
state.write(" {}\n");
|
||||
state.write("~_Undo_() {\n");
|
||||
for name in &needs_undo {
|
||||
write!(state, "self->{0} = {0};\n", name);
|
||||
}
|
||||
state.write("}} _undo_(this);\n");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let mut texel_fetches = state.texel_fetches.borrow_mut();
|
||||
texel_fetches.clear();
|
||||
for ((sampler, base), offsets) in fd.texel_fetches.iter() {
|
||||
add_used_global(state, sampler);
|
||||
let sampler_sym = state.hir.sym(*sampler);
|
||||
let base_sym = state.hir.sym(*base);
|
||||
if symbol_run_class(&base_sym.decl, vector_mask) == hir::RunClass::Scalar {
|
||||
add_used_global(state, sampler);
|
||||
let sampler_sym = state.hir.sym(*sampler);
|
||||
match &base_sym.decl {
|
||||
hir::SymDecl::Global(..) => {
|
||||
add_used_global(state, base);
|
||||
define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets);
|
||||
}
|
||||
hir::SymDecl::Local(..) => {
|
||||
if fd.prototype.has_parameter(*base) {
|
||||
define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets);
|
||||
} else {
|
||||
texel_fetches.push((*sampler, *base, offsets.clone()));
|
||||
}
|
||||
}
|
||||
_ => panic!(),
|
||||
match &base_sym.decl {
|
||||
hir::SymDecl::Global(..) => {
|
||||
add_used_global(state, base);
|
||||
define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets);
|
||||
}
|
||||
hir::SymDecl::Local(..) => {
|
||||
if fd.prototype.has_parameter(*base) {
|
||||
define_texel_fetch_ptr(state, &base_sym, &sampler_sym, &offsets);
|
||||
} else {
|
||||
texel_fetches.push((*sampler, *base, offsets.clone()));
|
||||
}
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3195,7 +3170,7 @@ pub fn show_iteration_statement(state: &mut OutputState, ist: &hir::IterationSta
|
|||
show_statement(state, body);
|
||||
state.write(" while (");
|
||||
show_hir_expr(state, cond);
|
||||
state.write(")\n");
|
||||
state.write(");\n");
|
||||
}
|
||||
hir::IterationStatement::For(ref init, ref rest, ref body) => {
|
||||
state.write("for (");
|
||||
|
@ -3266,7 +3241,7 @@ pub fn show_jump_statement(state: &mut OutputState, j: &hir::JumpStatement) {
|
|||
if state.output_cxx {
|
||||
state.uses_discard = true;
|
||||
if let Some(mask) = &state.mask {
|
||||
state.write("isPixelDiscarded |= (");
|
||||
state.write("swgl_IsPixelDiscarded |= (");
|
||||
show_hir_expr(state, mask);
|
||||
state.write(")");
|
||||
if state.return_declared {
|
||||
|
@ -3274,7 +3249,7 @@ pub fn show_jump_statement(state: &mut OutputState, j: &hir::JumpStatement) {
|
|||
}
|
||||
state.write(";\n");
|
||||
} else {
|
||||
state.write("isPixelDiscarded = true;\n");
|
||||
state.write("swgl_IsPixelDiscarded = true;\n");
|
||||
}
|
||||
} else {
|
||||
state.write("discard;\n");
|
||||
|
@ -3579,9 +3554,11 @@ pub fn show_translation_unit(state: &mut OutputState, tu: &hir::TranslationUnit)
|
|||
state.flush_buffer();
|
||||
}
|
||||
if state.output_cxx {
|
||||
if let Some(name) = state.hir.lookup("main") {
|
||||
show_cxx_function_definition(state, name, 0);
|
||||
state.flush_buffer();
|
||||
for name in &["main", "swgl_drawSpanRGBA8", "swgl_drawSpanR8"] {
|
||||
if let Some(sym) = state.hir.lookup(name) {
|
||||
show_cxx_function_definition(state, sym, 0);
|
||||
state.flush_buffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3591,37 +3568,33 @@ fn write_abi(state: &mut OutputState) {
|
|||
ShaderKind::Fragment => {
|
||||
state.write("static void run(Self *self) {\n");
|
||||
if state.uses_discard {
|
||||
state.write(" self->isPixelDiscarded = false;\n");
|
||||
state.write(" self->swgl_IsPixelDiscarded = false;\n");
|
||||
}
|
||||
state.write(" self->main();\n");
|
||||
state.write(" self->step_interp_inputs();\n");
|
||||
state.write("}\n");
|
||||
state.write("static void skip(Self* self, int chunks) {\n");
|
||||
state.write(" self->step_interp_inputs();\n");
|
||||
state.write(" while (--chunks > 0) self->step_interp_inputs();\n");
|
||||
state.write("static void skip(Self* self, int steps) {\n");
|
||||
state.write(" self->step_interp_inputs(steps);\n");
|
||||
state.write("}\n");
|
||||
if state.use_perspective {
|
||||
state.write("static void run_perspective(Self *self) {\n");
|
||||
if state.uses_discard {
|
||||
state.write(" self->isPixelDiscarded = false;\n");
|
||||
state.write(" self->swgl_IsPixelDiscarded = false;\n");
|
||||
}
|
||||
state.write(" self->main();\n");
|
||||
state.write(" self->step_perspective_inputs();\n");
|
||||
state.write("}\n");
|
||||
state.write("static void skip_perspective(Self* self, int chunks) {\n");
|
||||
state.write(" self->step_perspective_inputs();\n");
|
||||
state.write(" while (--chunks > 0) self->step_perspective_inputs();\n");
|
||||
state.write("static void skip_perspective(Self* self, int steps) {\n");
|
||||
state.write(" self->step_perspective_inputs(steps);\n");
|
||||
state.write("}\n");
|
||||
}
|
||||
if state.has_draw_span_rgba8 {
|
||||
if state.hir.lookup("swgl_drawSpanRGBA8").is_some() {
|
||||
state.write(
|
||||
"static void draw_span_RGBA8(Self* self, uint32_t* buf, int len) { \
|
||||
DISPATCH_DRAW_SPAN(self, buf, len); }\n");
|
||||
"static int draw_span_RGBA8(Self* self) { DISPATCH_DRAW_SPAN(self, RGBA8); }\n");
|
||||
}
|
||||
if state.has_draw_span_r8 {
|
||||
if state.hir.lookup("swgl_drawSpanR8").is_some() {
|
||||
state.write(
|
||||
"static void draw_span_R8(Self* self, uint8_t* buf, int len) { \
|
||||
DISPATCH_DRAW_SPAN(self, buf, len); }\n");
|
||||
"static int draw_span_R8(Self* self) { DISPATCH_DRAW_SPAN(self, R8); }\n");
|
||||
}
|
||||
|
||||
write!(state, "public:\n{}_frag() {{\n", state.name);
|
||||
|
@ -3643,10 +3616,10 @@ fn write_abi(state: &mut OutputState) {
|
|||
state.write(" init_span_func = (InitSpanFunc)&read_interp_inputs;\n");
|
||||
state.write(" run_func = (RunFunc)&run;\n");
|
||||
state.write(" skip_func = (SkipFunc)&skip;\n");
|
||||
if state.has_draw_span_rgba8 {
|
||||
if state.hir.lookup("swgl_drawSpanRGBA8").is_some() {
|
||||
state.write(" draw_span_RGBA8_func = (DrawSpanRGBA8Func)&draw_span_RGBA8;\n");
|
||||
}
|
||||
if state.has_draw_span_r8 {
|
||||
if state.hir.lookup("swgl_drawSpanR8").is_some() {
|
||||
state.write(" draw_span_R8_func = (DrawSpanR8Func)&draw_span_R8;\n");
|
||||
}
|
||||
if state.uses_discard {
|
||||
|
@ -3670,6 +3643,9 @@ fn write_abi(state: &mut OutputState) {
|
|||
state.write(" init_batch_func = (InitBatchFunc)&init_batch;\n");
|
||||
state.write(" load_attribs_func = (LoadAttribsFunc)&load_attribs;\n");
|
||||
state.write(" run_primitive_func = (RunPrimitiveFunc)&run;\n");
|
||||
if state.hir.used_clip_dist != 0 {
|
||||
state.write(" enable_clip_distance();\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
state.write("}\n");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue