зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1634452 - allow SWGL vertex and fragment shaders to share data. r=jrmuizel
Currently SWGL stores separate copies of flat interpolants, uniforms, and samplers for vertex shaders and fragment shaders. We can just make the fragment shader inherit from the vertex shader, which allows us to only have to store one copy of these, and also obviates the need to store them out and read them back to transition from vertex shader to fragment shader per-primitive. This will help offset the performance cost of perspective checking in bug 1634447. Differential Revision: https://phabricator.services.mozilla.com/D73299
This commit is contained in:
Родитель
f9b1f690e4
Коммит
d6438ad24b
|
@ -201,30 +201,14 @@ fn translate_shader(
|
||||||
ShaderKind::Vertex => "_vert",
|
ShaderKind::Vertex => "_vert",
|
||||||
ShaderKind::Fragment => "_frag",
|
ShaderKind::Fragment => "_frag",
|
||||||
};
|
};
|
||||||
let shader_impl = match state.kind {
|
|
||||||
ShaderKind::Vertex => "VertexShaderImpl",
|
|
||||||
ShaderKind::Fragment => "FragmentShaderImpl",
|
|
||||||
};
|
|
||||||
|
|
||||||
if state.kind == ShaderKind::Vertex {
|
if state.kind == ShaderKind::Vertex {
|
||||||
write!(state, "struct {}_program : ProgramImpl {{\n", name);
|
write_common_globals(&mut state, &inputs, &outputs, uniform_indices);
|
||||||
write_get_uniform_index(&mut state, uniform_indices);
|
write!(state, "struct {0}_vert : VertexShaderImpl, {0}_common {{\nprivate:\n", name);
|
||||||
write_program_samplers(&mut state, uniform_indices);
|
} else {
|
||||||
write_bind_attrib_location(&mut state, &inputs);
|
write!(state, "struct {0}_frag : FragmentShaderImpl, {0}_vert {{\nprivate:\n", name);
|
||||||
write!(state, "VertexShaderImpl* get_vertex_shader() override;\n");
|
|
||||||
write!(
|
|
||||||
state,
|
|
||||||
"FragmentShaderImpl* get_fragment_shader() override;\n"
|
|
||||||
);
|
|
||||||
write!(
|
|
||||||
state,
|
|
||||||
"static ProgramImpl* loader() {{ return new {}_program; }}\n",
|
|
||||||
name
|
|
||||||
);
|
|
||||||
write!(state, "}};\n\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(state, "struct {} : {} {{\n", part_name, shader_impl);
|
|
||||||
write!(state, "typedef {} Self;\n", part_name);
|
write!(state, "typedef {} Self;\n", part_name);
|
||||||
|
|
||||||
show_translation_unit(&mut state, &hir);
|
show_translation_unit(&mut state, &hir);
|
||||||
|
@ -233,44 +217,38 @@ fn translate_shader(
|
||||||
write_include_file(&mut state, include_file);
|
write_include_file(&mut state, include_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
write_set_uniform_1i(&mut state, &uniforms, uniform_indices);
|
|
||||||
write_set_uniform_4fv(&mut state, &uniforms, uniform_indices);
|
|
||||||
write_set_uniform_matrix4fv(&mut state, &uniforms, uniform_indices);
|
|
||||||
|
|
||||||
let pruned_inputs: Vec<_> = inputs
|
let pruned_inputs: Vec<_> = inputs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|i| state.used_globals.borrow().contains(i))
|
.filter(|i| state.used_globals.borrow().contains(i))
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
let pruned_uniforms: Vec<_> = uniforms
|
|
||||||
.iter()
|
|
||||||
.filter(|u| state.used_globals.borrow().contains(u))
|
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
if state.kind == ShaderKind::Vertex {
|
if state.kind == ShaderKind::Vertex {
|
||||||
|
write_set_uniform_1i(&mut state, uniform_indices);
|
||||||
|
write_set_uniform_4fv(&mut state, uniform_indices);
|
||||||
|
write_set_uniform_matrix4fv(&mut state, uniform_indices);
|
||||||
write_load_attribs(&mut state, &pruned_inputs);
|
write_load_attribs(&mut state, &pruned_inputs);
|
||||||
write_store_outputs(&mut state, &outputs);
|
write_store_outputs(&mut state, &outputs);
|
||||||
} else {
|
} else {
|
||||||
write_read_inputs(&mut state, &pruned_inputs);
|
write_read_inputs(&mut state, &pruned_inputs);
|
||||||
}
|
}
|
||||||
write_bind_textures(&mut state, &pruned_uniforms);
|
|
||||||
|
|
||||||
write_abi(&mut state);
|
write_abi(&mut state);
|
||||||
write!(state, "}};\n\n");
|
write!(state, "}};\n\n");
|
||||||
|
|
||||||
if state.kind == ShaderKind::Vertex {
|
if state.kind == ShaderKind::Fragment {
|
||||||
write!(
|
write!(state, "struct {0}_program : ProgramImpl, {0}_frag {{\n", name);
|
||||||
state,
|
write_get_uniform_index(&mut state, uniform_indices);
|
||||||
"VertexShaderImpl* {}_program::get_vertex_shader() {{ return new {}; }}\n",
|
write!(state, "void bind_attrib(const char* name, int index) override {{\n");
|
||||||
name, part_name
|
write!(state, " attrib_locations.bind_loc(name, index);\n}}\n");
|
||||||
);
|
write!(state, "int get_attrib(const char* name) const override {{\n");
|
||||||
} else {
|
write!(state, " return attrib_locations.get_loc(name);\n}}\n");
|
||||||
write!(
|
write!(state, "VertexShaderImpl* get_vertex_shader() override {{\n");
|
||||||
state,
|
write!(state, " return this;\n}}\n");
|
||||||
"FragmentShaderImpl* {}_program::get_fragment_shader() {{ return new {}; }}\n",
|
write!(state, "FragmentShaderImpl* get_fragment_shader() override {{\n");
|
||||||
name, part_name
|
write!(state, " return this;\n}}\n");
|
||||||
);
|
write!(state, "static ProgramImpl* loader() {{ return new {}_program; }}\n", name);
|
||||||
|
write!(state, "}};\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
define_global_consts(&mut state, &hir, &part_name);
|
define_global_consts(&mut state, &hir, &part_name);
|
||||||
|
@ -303,6 +281,7 @@ fn write_get_uniform_index(state: &mut OutputState, uniform_indices: &UniformInd
|
||||||
|
|
||||||
fn float4_compatible(ty: hir::TypeKind) -> bool {
|
fn float4_compatible(ty: hir::TypeKind) -> bool {
|
||||||
match ty {
|
match ty {
|
||||||
|
hir::TypeKind::Vec4 => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -335,11 +314,9 @@ fn write_program_samplers(state: &mut OutputState, uniform_indices: &UniformIndi
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write!(state, "}} samplers;\n");
|
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
state,
|
state,
|
||||||
"bool set_sampler(int index, int value) override {{\n"
|
" bool set_slot(int index, int value) {{\n"
|
||||||
);
|
);
|
||||||
write!(state, " switch (index) {{\n");
|
write!(state, " switch (index) {{\n");
|
||||||
for (name, (index, tk, _)) in uniform_indices.iter() {
|
for (name, (index, tk, _)) in uniform_indices.iter() {
|
||||||
|
@ -349,7 +326,7 @@ fn write_program_samplers(state: &mut OutputState, uniform_indices: &UniformIndi
|
||||||
| hir::TypeKind::ISampler2D
|
| hir::TypeKind::ISampler2D
|
||||||
| hir::TypeKind::Sampler2DArray => {
|
| hir::TypeKind::Sampler2DArray => {
|
||||||
write!(state, " case {}:\n", index);
|
write!(state, " case {}:\n", index);
|
||||||
write!(state, " samplers.{}_slot = value;\n", name);
|
write!(state, " {}_slot = value;\n", name);
|
||||||
write!(state, " return true;\n");
|
write!(state, " return true;\n");
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -358,35 +335,30 @@ fn write_program_samplers(state: &mut OutputState, uniform_indices: &UniformIndi
|
||||||
write!(state, " }}\n");
|
write!(state, " }}\n");
|
||||||
write!(state, " return false;\n");
|
write!(state, " return false;\n");
|
||||||
write!(state, " }}\n");
|
write!(state, " }}\n");
|
||||||
|
write!(state, "}} samplers;\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_bind_textures(state: &mut OutputState, uniforms: &[hir::SymRef]) {
|
fn write_bind_textures(state: &mut OutputState, uniforms: &UniformIndices) {
|
||||||
write!(
|
write!(state, "void bind_textures() {{\n");
|
||||||
state,
|
for (name, (_, tk, storage)) in uniforms {
|
||||||
"static void bind_textures(Self *self, {}_program *prog) {{\n",
|
match storage {
|
||||||
state.name
|
hir::StorageClass::Sampler(_format) => {
|
||||||
);
|
match tk {
|
||||||
for i in uniforms {
|
|
||||||
let sym = state.hir.sym(*i);
|
|
||||||
match &sym.decl {
|
|
||||||
hir::SymDecl::Global(hir::StorageClass::Sampler(_format), _, ty, _) => {
|
|
||||||
let name = sym.name.as_str();
|
|
||||||
match ty.kind {
|
|
||||||
hir::TypeKind::Sampler2D
|
hir::TypeKind::Sampler2D
|
||||||
| hir::TypeKind::Sampler2DRect => write!(state,
|
| hir::TypeKind::Sampler2DRect => write!(state,
|
||||||
" self->{0} = lookup_sampler(&prog->samplers.{0}_impl, prog->samplers.{0}_slot);\n",
|
" {0} = lookup_sampler(&samplers.{0}_impl, samplers.{0}_slot);\n",
|
||||||
name),
|
name),
|
||||||
hir::TypeKind::ISampler2D => write!(state,
|
hir::TypeKind::ISampler2D => write!(state,
|
||||||
" self->{0} = lookup_isampler(&prog->samplers.{0}_impl, prog->samplers.{0}_slot);\n",
|
" {0} = lookup_isampler(&samplers.{0}_impl, samplers.{0}_slot);\n",
|
||||||
name),
|
name),
|
||||||
hir::TypeKind::Sampler2DArray => write!(state,
|
hir::TypeKind::Sampler2DArray => write!(state,
|
||||||
" self->{0} = lookup_sampler_array(&prog->samplers.{0}_impl, prog->samplers.{0}_slot);\n",
|
" {0} = lookup_sampler_array(&samplers.{0}_impl, samplers.{0}_slot);\n",
|
||||||
name),
|
name),
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
hir::SymDecl::Global(..) => {}
|
_ => {}
|
||||||
_ => panic!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write!(state, "}}\n");
|
write!(state, "}}\n");
|
||||||
|
@ -394,94 +366,70 @@ fn write_bind_textures(state: &mut OutputState, uniforms: &[hir::SymRef]) {
|
||||||
|
|
||||||
fn write_set_uniform_1i(
|
fn write_set_uniform_1i(
|
||||||
state: &mut OutputState,
|
state: &mut OutputState,
|
||||||
uniforms: &[hir::SymRef],
|
uniforms: &UniformIndices,
|
||||||
uniform_indices: &UniformIndices,
|
|
||||||
) {
|
) {
|
||||||
write!(
|
write!(
|
||||||
state,
|
state,
|
||||||
"static void set_uniform_1i(Self *self, int index, int value) {{\n"
|
"static void set_uniform_1i(Self *self, int index, int value) {{\n"
|
||||||
);
|
);
|
||||||
|
write!(state, " if (self->samplers.set_slot(index, value)) return;\n");
|
||||||
write!(state, " switch (index) {{\n");
|
write!(state, " switch (index) {{\n");
|
||||||
for i in uniforms {
|
for (name, (index, tk, _)) in uniforms {
|
||||||
let sym = state.hir.sym(*i);
|
|
||||||
match &sym.decl {
|
|
||||||
hir::SymDecl::Global(_, _, ty, _) => {
|
|
||||||
let name = sym.name.as_str();
|
|
||||||
let (index, _, _) = uniform_indices.get(name).unwrap();
|
|
||||||
write!(state, " case {}:\n", index);
|
write!(state, " case {}:\n", index);
|
||||||
match ty.kind {
|
match tk {
|
||||||
hir::TypeKind::Int => write!(
|
hir::TypeKind::Int => write!(
|
||||||
state,
|
state,
|
||||||
" self->{} = {}(value);\n",
|
" self->{} = {}(value);\n",
|
||||||
name,
|
name,
|
||||||
scalar_type_name(state, ty)
|
tk.cxx_primitive_scalar_type_name().unwrap(),
|
||||||
),
|
),
|
||||||
_ => write!(state, " assert(0); // {}\n", name),
|
_ => write!(state, " assert(0); // {}\n", name),
|
||||||
};
|
};
|
||||||
write!(state, " break;\n");
|
write!(state, " break;\n");
|
||||||
}
|
}
|
||||||
_ => panic!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write!(state, " }}\n");
|
write!(state, " }}\n");
|
||||||
write!(state, "}}\n");
|
write!(state, "}}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_set_uniform_4fv(
|
fn write_set_uniform_4fv(
|
||||||
state: &mut OutputState,
|
state: &mut OutputState,
|
||||||
uniforms: &[hir::SymRef],
|
uniforms: &UniformIndices,
|
||||||
uniform_indices: &UniformIndices,
|
|
||||||
) {
|
) {
|
||||||
write!(
|
write!(
|
||||||
state,
|
state,
|
||||||
"static void set_uniform_4fv(Self *self, int index, const float *value) {{\n"
|
"static void set_uniform_4fv(Self *self, int index, const float *value) {{\n"
|
||||||
);
|
);
|
||||||
write!(state, " switch (index) {{\n");
|
write!(state, " switch (index) {{\n");
|
||||||
for i in uniforms {
|
for (name, (index, tk, _)) in uniforms {
|
||||||
let sym = state.hir.sym(*i);
|
|
||||||
match &sym.decl {
|
|
||||||
hir::SymDecl::Global(_, _, ty, _) => {
|
|
||||||
let name = sym.name.as_str();
|
|
||||||
let (index, _, _) = uniform_indices.get(name).unwrap();
|
|
||||||
write!(state, " case {}:\n", index);
|
write!(state, " case {}:\n", index);
|
||||||
if float4_compatible(ty.kind.clone()) {
|
if float4_compatible(tk.clone()) {
|
||||||
write!(
|
write!(
|
||||||
state,
|
state,
|
||||||
" self->{} = {}(value);\n",
|
" self->{} = {}_scalar(value);\n",
|
||||||
name,
|
name,
|
||||||
scalar_type_name(state, ty)
|
tk.glsl_primitive_type_name().unwrap(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
write!(state, " assert(0); // {}\n", name);
|
write!(state, " assert(0); // {}\n", name);
|
||||||
}
|
}
|
||||||
write!(state, " break;\n");
|
write!(state, " break;\n");
|
||||||
}
|
}
|
||||||
_ => panic!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write!(state, " }}\n");
|
write!(state, " }}\n");
|
||||||
write!(state, "}}\n");
|
write!(state, "}}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_set_uniform_matrix4fv(
|
fn write_set_uniform_matrix4fv(
|
||||||
state: &mut OutputState,
|
state: &mut OutputState,
|
||||||
uniforms: &[hir::SymRef],
|
uniforms: &UniformIndices,
|
||||||
uniform_indices: &UniformIndices,
|
|
||||||
) {
|
) {
|
||||||
write!(
|
write!(
|
||||||
state,
|
state,
|
||||||
"static void set_uniform_matrix4fv(Self *self, int index, const float *value) {{\n"
|
"static void set_uniform_matrix4fv(Self *self, int index, const float *value) {{\n"
|
||||||
);
|
);
|
||||||
write!(state, " switch (index) {{\n");
|
write!(state, " switch (index) {{\n");
|
||||||
for i in uniforms {
|
for (name, (index, tk, _)) in uniforms {
|
||||||
let sym = state.hir.sym(*i);
|
|
||||||
match &sym.decl {
|
|
||||||
hir::SymDecl::Global(_, _, ty, _) => {
|
|
||||||
let name = sym.name.as_str();
|
|
||||||
let (index, _, _) = uniform_indices.get(name).unwrap();
|
|
||||||
|
|
||||||
write!(state, " case {}:\n", index);
|
write!(state, " case {}:\n", index);
|
||||||
if matrix4_compatible(ty.kind.clone()) {
|
if matrix4_compatible(tk.clone()) {
|
||||||
write!(
|
write!(
|
||||||
state,
|
state,
|
||||||
" self->{} = mat4_scalar::load_from_ptr(value);\n",
|
" self->{} = mat4_scalar::load_from_ptr(value);\n",
|
||||||
|
@ -492,9 +440,6 @@ fn write_set_uniform_matrix4fv(
|
||||||
}
|
}
|
||||||
write!(state, " break;\n");
|
write!(state, " break;\n");
|
||||||
}
|
}
|
||||||
_ => panic!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write!(state, " }}\n");
|
write!(state, " }}\n");
|
||||||
write!(state, "}}\n");
|
write!(state, "}}\n");
|
||||||
}
|
}
|
||||||
|
@ -505,59 +450,69 @@ fn write_bind_attrib_location(state: &mut OutputState, attribs: &[hir::SymRef])
|
||||||
let sym = state.hir.sym(*i);
|
let sym = state.hir.sym(*i);
|
||||||
write!(state, " int {} = NULL_ATTRIB;\n", sym.name.as_str());
|
write!(state, " int {} = NULL_ATTRIB;\n", sym.name.as_str());
|
||||||
}
|
}
|
||||||
write!(state, "}} attrib_locations;\n");
|
write!(state, " void bind_loc(const char* name, int index) {{\n");
|
||||||
|
|
||||||
write!(
|
|
||||||
state,
|
|
||||||
"void bind_attrib(const char* name, int index) override {{\n"
|
|
||||||
);
|
|
||||||
for i in attribs {
|
for i in attribs {
|
||||||
let sym = state.hir.sym(*i);
|
let sym = state.hir.sym(*i);
|
||||||
write!(
|
write!(
|
||||||
state,
|
state,
|
||||||
" if (strcmp(\"{0}\", name) == 0) {{ attrib_locations.{0} = index; return; }}\n",
|
" if (strcmp(\"{0}\", name) == 0) {{ {0} = index; return; }}\n",
|
||||||
sym.name.as_str()
|
sym.name.as_str()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
write!(state, " }}\n");
|
write!(state, " }}\n");
|
||||||
|
write!(state, " int get_loc(const char* name) const {{\n");
|
||||||
write!(
|
|
||||||
state,
|
|
||||||
"int get_attrib(const char* name) const override {{\n"
|
|
||||||
);
|
|
||||||
for i in attribs {
|
for i in attribs {
|
||||||
let sym = state.hir.sym(*i);
|
let sym = state.hir.sym(*i);
|
||||||
write!(state,
|
write!(state,
|
||||||
" if (strcmp(\"{0}\", name) == 0) {{ \
|
" if (strcmp(\"{0}\", name) == 0) {{ \
|
||||||
return attrib_locations.{0} != NULL_ATTRIB ? attrib_locations.{0} : -1;\
|
return {0} != NULL_ATTRIB ? {0} : -1; \
|
||||||
}}\n",
|
}}\n",
|
||||||
sym.name.as_str());
|
sym.name.as_str());
|
||||||
}
|
}
|
||||||
write!(state, " return -1;\n");
|
write!(state, " return -1;\n");
|
||||||
write!(state, " }}\n");
|
write!(state, " }}\n");
|
||||||
|
write!(state, "}} attrib_locations;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scalar_type_name(state: &OutputState, ty: &Type) -> String {
|
fn write_common_globals(state: &mut OutputState, attribs: &[hir::SymRef],
|
||||||
let kind_name = if let Some(name) = ty.kind.cxx_primitive_scalar_type_name() {
|
outputs: &[hir::SymRef], uniforms: &UniformIndices) {
|
||||||
name.into()
|
write!(state, "struct {}_common {{\n", state.name);
|
||||||
} else {
|
|
||||||
let buffer = state.push_buffer();
|
write_program_samplers(state, uniforms);
|
||||||
|
write_bind_attrib_location(state, attribs);
|
||||||
|
|
||||||
|
let is_scalar = state.is_scalar.replace(true);
|
||||||
|
for i in outputs {
|
||||||
|
let sym = state.hir.sym(*i);
|
||||||
|
match &sym.decl {
|
||||||
|
hir::SymDecl::Global(hir::StorageClass::Out, _, ty, hir::RunClass::Scalar) => {
|
||||||
show_type(state, ty);
|
show_type(state, ty);
|
||||||
state.pop_buffer(buffer) + "_scalar"
|
write!(state, " {};\n", sym.name.as_str());
|
||||||
};
|
|
||||||
if let Some(ref array) = ty.array_sizes {
|
|
||||||
let size = match &array.sizes[..] {
|
|
||||||
[size] => size,
|
|
||||||
_ => panic!(),
|
|
||||||
};
|
|
||||||
let buffer = state.push_buffer();
|
|
||||||
show_hir_expr(state, size);
|
|
||||||
let size_string = state.pop_buffer(buffer);
|
|
||||||
|
|
||||||
format!("Array<{}, {}>", kind_name, size_string)
|
|
||||||
} else {
|
|
||||||
kind_name
|
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (name, (_, tk, storage)) in uniforms {
|
||||||
|
match storage {
|
||||||
|
hir::StorageClass::Sampler(format) => {
|
||||||
|
write!(state,
|
||||||
|
"{}{} {};\n",
|
||||||
|
tk.cxx_primitive_type_name().unwrap(),
|
||||||
|
format.type_suffix().unwrap_or(""),
|
||||||
|
name,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
show_type_kind(state, tk);
|
||||||
|
write!(state, " {};\n", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.is_scalar.set(is_scalar);
|
||||||
|
|
||||||
|
write_bind_textures(state, uniforms);
|
||||||
|
|
||||||
|
write!(state, "}};\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//fn type_name(state: &OutputState, ty: &Type) -> String {
|
//fn type_name(state: &OutputState, ty: &Type) -> String {
|
||||||
|
@ -568,8 +523,8 @@ fn scalar_type_name(state: &OutputState, ty: &Type) -> String {
|
||||||
|
|
||||||
fn write_load_attribs(state: &mut OutputState, attribs: &[hir::SymRef]) {
|
fn write_load_attribs(state: &mut OutputState, attribs: &[hir::SymRef]) {
|
||||||
write!(state, "static void load_attribs(\
|
write!(state, "static void load_attribs(\
|
||||||
Self *self, {}_program *prog, VertexAttrib *attribs, \
|
Self *self, VertexAttrib *attribs, \
|
||||||
uint32_t start, int instance, int count) {{\n", state.name);
|
uint32_t start, int instance, int count) {{\n");
|
||||||
for i in attribs {
|
for i in attribs {
|
||||||
let sym = state.hir.sym(*i);
|
let sym = state.hir.sym(*i);
|
||||||
match &sym.decl {
|
match &sym.decl {
|
||||||
|
@ -581,7 +536,7 @@ fn write_load_attribs(state: &mut OutputState, attribs: &[hir::SymRef]) {
|
||||||
"load_attrib"
|
"load_attrib"
|
||||||
};
|
};
|
||||||
write!(state,
|
write!(state,
|
||||||
" {0}(self->{1}, attribs[prog->attrib_locations.{1}], start, instance, count);\n",
|
" {0}(self->{1}, attribs[self->attrib_locations.{1}], start, instance, count);\n",
|
||||||
func, name);
|
func, name);
|
||||||
}
|
}
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
|
@ -592,22 +547,7 @@ fn write_load_attribs(state: &mut OutputState, attribs: &[hir::SymRef]) {
|
||||||
|
|
||||||
fn write_store_outputs(state: &mut OutputState, outputs: &[hir::SymRef]) {
|
fn write_store_outputs(state: &mut OutputState, outputs: &[hir::SymRef]) {
|
||||||
let is_scalar = state.is_scalar.replace(true);
|
let is_scalar = state.is_scalar.replace(true);
|
||||||
write!(state, "struct FlatOutputs {{\n");
|
write!(state, "public:\nstruct InterpOutputs {{\n");
|
||||||
for i in outputs {
|
|
||||||
let sym = state.hir.sym(*i);
|
|
||||||
match &sym.decl {
|
|
||||||
hir::SymDecl::Global(_, _, ty, run_class) => {
|
|
||||||
if *run_class == hir::RunClass::Scalar {
|
|
||||||
show_type(state, ty);
|
|
||||||
write!(state, " {};\n", sym.name.as_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => panic!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write!(state, "}};\n");
|
|
||||||
|
|
||||||
write!(state, "struct InterpOutputs {{\n");
|
|
||||||
for i in outputs {
|
for i in outputs {
|
||||||
let sym = state.hir.sym(*i);
|
let sym = state.hir.sym(*i);
|
||||||
match &sym.decl {
|
match &sym.decl {
|
||||||
|
@ -621,31 +561,9 @@ fn write_store_outputs(state: &mut OutputState, outputs: &[hir::SymRef]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(state, "}};\n");
|
write!(state, "}};\nprivate:\n");
|
||||||
state.is_scalar.set(is_scalar);
|
state.is_scalar.set(is_scalar);
|
||||||
|
|
||||||
write!(
|
|
||||||
state,
|
|
||||||
"ALWAYS_INLINE void store_flat_outputs(char* dest_ptr) {{\n"
|
|
||||||
);
|
|
||||||
write!(
|
|
||||||
state,
|
|
||||||
" auto* dest = reinterpret_cast<FlatOutputs*>(dest_ptr);\n"
|
|
||||||
);
|
|
||||||
for i in outputs {
|
|
||||||
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, " dest->{} = {};\n", name, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => panic!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write!(state, "}}\n");
|
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
state,
|
state,
|
||||||
"ALWAYS_INLINE void store_interp_outputs(char* dest_ptr, size_t stride) {{\n"
|
"ALWAYS_INLINE void store_interp_outputs(char* dest_ptr, size_t stride) {{\n"
|
||||||
|
@ -673,35 +591,12 @@ fn write_store_outputs(state: &mut OutputState, outputs: &[hir::SymRef]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) {
|
fn write_read_inputs(state: &mut OutputState, inputs: &[hir::SymRef]) {
|
||||||
write!(
|
|
||||||
state,
|
|
||||||
"typedef {}_vert::FlatOutputs FlatInputs;\n",
|
|
||||||
state.name
|
|
||||||
);
|
|
||||||
write!(
|
write!(
|
||||||
state,
|
state,
|
||||||
"typedef {}_vert::InterpOutputs InterpInputs;\n",
|
"typedef {}_vert::InterpOutputs InterpInputs;\n",
|
||||||
state.name
|
state.name
|
||||||
);
|
);
|
||||||
|
|
||||||
write!(
|
|
||||||
state,
|
|
||||||
"static void read_flat_inputs(Self *self, const FlatInputs *src) {{\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, " self->{} = src->{};\n", name, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => panic!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write!(state, "}}\n");
|
|
||||||
|
|
||||||
write!(state, "InterpInputs interp_step;\n");
|
write!(state, "InterpInputs interp_step;\n");
|
||||||
|
|
||||||
let mut has_perspective: bool = false;
|
let mut has_perspective: bool = false;
|
||||||
|
@ -2631,20 +2526,16 @@ fn symbol_run_class(decl: &hir::SymDecl, vector_mask: u32) -> hir::RunClass {
|
||||||
|
|
||||||
pub fn show_single_declaration_cxx(state: &mut OutputState, d: &hir::SingleDeclaration) {
|
pub fn show_single_declaration_cxx(state: &mut OutputState, d: &hir::SingleDeclaration) {
|
||||||
let sym = state.hir.sym(d.name);
|
let sym = state.hir.sym(d.name);
|
||||||
|
if state.kind == ShaderKind::Vertex {
|
||||||
match &sym.decl {
|
match &sym.decl {
|
||||||
hir::SymDecl::Global(hir::StorageClass::Sampler(format), ..) => {
|
hir::SymDecl::Global(hir::StorageClass::Uniform, ..) |
|
||||||
write!(
|
hir::SymDecl::Global(hir::StorageClass::Sampler(_), ..) |
|
||||||
state,
|
hir::SymDecl::Global(hir::StorageClass::Out, _, _, hir::RunClass::Scalar) => {
|
||||||
"{}{} {}",
|
state.write("// ");
|
||||||
d.ty.kind.cxx_primitive_type_name().unwrap(),
|
|
||||||
format.type_suffix().unwrap_or(""),
|
|
||||||
sym.name.as_str()
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
if state.kind == ShaderKind::Fragment {
|
} else {
|
||||||
match &sym.decl {
|
match &sym.decl {
|
||||||
hir::SymDecl::Global(hir::StorageClass::FragColor(index), ..) => {
|
hir::SymDecl::Global(hir::StorageClass::FragColor(index), ..) => {
|
||||||
let fragcolor = match index {
|
let fragcolor = match index {
|
||||||
|
@ -2661,6 +2552,11 @@ pub fn show_single_declaration_cxx(state: &mut OutputState, d: &hir::SingleDecla
|
||||||
show_indent(state);
|
show_indent(state);
|
||||||
state.write("// ");
|
state.write("// ");
|
||||||
}
|
}
|
||||||
|
hir::SymDecl::Global(hir::StorageClass::Uniform, ..) |
|
||||||
|
hir::SymDecl::Global(hir::StorageClass::Sampler(_), ..) |
|
||||||
|
hir::SymDecl::Global(hir::StorageClass::In, _, _, hir::RunClass::Scalar) => {
|
||||||
|
state.write("// ");
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3697,35 +3593,30 @@ fn write_abi(state: &mut OutputState) {
|
||||||
if state.has_draw_span_rgba8 {
|
if state.has_draw_span_rgba8 {
|
||||||
state.write(
|
state.write(
|
||||||
"static void draw_span_RGBA8(Self* self, uint32_t* buf, int len) { \
|
"static void draw_span_RGBA8(Self* self, uint32_t* buf, int len) { \
|
||||||
dispatch_draw_span(self, buf, len); }\n");
|
DISPATCH_DRAW_SPAN(self, buf, len); }\n");
|
||||||
}
|
}
|
||||||
if state.has_draw_span_r8 {
|
if state.has_draw_span_r8 {
|
||||||
state.write(
|
state.write(
|
||||||
"static void draw_span_R8(Self* self, uint8_t* buf, int len) { \
|
"static void draw_span_R8(Self* self, uint8_t* buf, int len) { \
|
||||||
dispatch_draw_span(self, buf, len); }\n");
|
DISPATCH_DRAW_SPAN(self, buf, len); }\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(state, "{}_frag() {{\n", state.name);
|
write!(state, "public:\n{}_frag() {{\n", state.name);
|
||||||
}
|
}
|
||||||
ShaderKind::Vertex => {
|
ShaderKind::Vertex => {
|
||||||
state.write(
|
state.write(
|
||||||
"static void run(Self* self, char* flats, char* interps, size_t interp_stride) {\n",
|
"static void run(Self* self, char* interps, size_t interp_stride) {\n",
|
||||||
);
|
);
|
||||||
state.write(" self->main();\n");
|
state.write(" self->main();\n");
|
||||||
state.write(" self->store_flat_outputs(flats);\n");
|
|
||||||
state.write(" self->store_interp_outputs(interps, interp_stride);\n");
|
state.write(" self->store_interp_outputs(interps, interp_stride);\n");
|
||||||
state.write("}\n");
|
state.write("}\n");
|
||||||
|
state.write("static void init_batch(Self *self) { self->bind_textures(); }\n");
|
||||||
|
|
||||||
write!(state, "{}_vert() {{\n", state.name);
|
write!(state, "public:\n{}_vert() {{\n", state.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.write(" set_uniform_1i_func = (SetUniform1iFunc)&set_uniform_1i;\n");
|
|
||||||
state.write(" set_uniform_4fv_func = (SetUniform4fvFunc)&set_uniform_4fv;\n");
|
|
||||||
state.write(" set_uniform_matrix4fv_func = (SetUniformMatrix4fvFunc)&set_uniform_matrix4fv;\n");
|
|
||||||
match state.kind {
|
match state.kind {
|
||||||
ShaderKind::Fragment => {
|
ShaderKind::Fragment => {
|
||||||
state.write(" init_batch_func = (InitBatchFunc)&bind_textures;\n");
|
|
||||||
state.write(" init_primitive_func = (InitPrimitiveFunc)&read_flat_inputs;\n");
|
|
||||||
state.write(" init_span_func = (InitSpanFunc)&read_interp_inputs;\n");
|
state.write(" init_span_func = (InitSpanFunc)&read_interp_inputs;\n");
|
||||||
state.write(" run_func = (RunFunc)&run;\n");
|
state.write(" run_func = (RunFunc)&run;\n");
|
||||||
state.write(" skip_func = (SkipFunc)&skip;\n");
|
state.write(" skip_func = (SkipFunc)&skip;\n");
|
||||||
|
@ -3744,9 +3635,12 @@ fn write_abi(state: &mut OutputState) {
|
||||||
state.write(" skip_w_func = (SkipWFunc)&skip_perspective;\n");
|
state.write(" skip_w_func = (SkipWFunc)&skip_perspective;\n");
|
||||||
}
|
}
|
||||||
ShaderKind::Vertex => {
|
ShaderKind::Vertex => {
|
||||||
state.write(" init_batch_func = (InitBatchFunc)&bind_textures;\n");
|
state.write(" set_uniform_1i_func = (SetUniform1iFunc)&set_uniform_1i;\n");
|
||||||
|
state.write(" set_uniform_4fv_func = (SetUniform4fvFunc)&set_uniform_4fv;\n");
|
||||||
|
state.write(" set_uniform_matrix4fv_func = (SetUniformMatrix4fvFunc)&set_uniform_matrix4fv;\n");
|
||||||
|
state.write(" init_batch_func = (InitBatchFunc)&init_batch;\n");
|
||||||
state.write(" load_attribs_func = (LoadAttribsFunc)&load_attribs;\n");
|
state.write(" load_attribs_func = (LoadAttribsFunc)&load_attribs;\n");
|
||||||
state.write(" run_func = (RunFunc)&run;\n");
|
state.write(" run_primitive_func = (RunPrimitiveFunc)&run;\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.write("}\n");
|
state.write("}\n");
|
||||||
|
|
|
@ -371,8 +371,6 @@ struct Program {
|
||||||
|
|
||||||
~Program() {
|
~Program() {
|
||||||
delete impl;
|
delete impl;
|
||||||
delete vert_impl;
|
|
||||||
delete frag_impl;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -605,7 +603,6 @@ struct Context {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static Context* ctx = nullptr;
|
static Context* ctx = nullptr;
|
||||||
static ProgramImpl* program_impl = nullptr;
|
|
||||||
static VertexShaderImpl* vertex_shader = nullptr;
|
static VertexShaderImpl* vertex_shader = nullptr;
|
||||||
static FragmentShaderImpl* fragment_shader = nullptr;
|
static FragmentShaderImpl* fragment_shader = nullptr;
|
||||||
static BlendKey blend_key = BLEND_KEY_NONE;
|
static BlendKey blend_key = BLEND_KEY_NONE;
|
||||||
|
@ -775,7 +772,6 @@ void load_flat_attrib(T& attrib, VertexAttrib& va, uint32_t start, int instance,
|
||||||
|
|
||||||
void setup_program(GLuint program) {
|
void setup_program(GLuint program) {
|
||||||
if (!program) {
|
if (!program) {
|
||||||
program_impl = nullptr;
|
|
||||||
vertex_shader = nullptr;
|
vertex_shader = nullptr;
|
||||||
fragment_shader = nullptr;
|
fragment_shader = nullptr;
|
||||||
return;
|
return;
|
||||||
|
@ -784,7 +780,6 @@ void setup_program(GLuint program) {
|
||||||
assert(p.impl);
|
assert(p.impl);
|
||||||
assert(p.vert_impl);
|
assert(p.vert_impl);
|
||||||
assert(p.frag_impl);
|
assert(p.frag_impl);
|
||||||
program_impl = p.impl;
|
|
||||||
vertex_shader = p.vert_impl;
|
vertex_shader = p.vert_impl;
|
||||||
fragment_shader = p.frag_impl;
|
fragment_shader = p.frag_impl;
|
||||||
}
|
}
|
||||||
|
@ -1677,22 +1672,17 @@ GLboolean UnmapBuffer(GLenum target) {
|
||||||
|
|
||||||
void Uniform1i(GLint location, GLint V0) {
|
void Uniform1i(GLint location, GLint V0) {
|
||||||
// debugf("tex: %d\n", (int)ctx->textures.size);
|
// debugf("tex: %d\n", (int)ctx->textures.size);
|
||||||
if (!program_impl->set_sampler(location, V0)) {
|
|
||||||
vertex_shader->set_uniform_1i(location, V0);
|
vertex_shader->set_uniform_1i(location, V0);
|
||||||
fragment_shader->set_uniform_1i(location, V0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void Uniform4fv(GLint location, GLsizei count, const GLfloat* v) {
|
void Uniform4fv(GLint location, GLsizei count, const GLfloat* v) {
|
||||||
assert(count == 1);
|
assert(count == 1);
|
||||||
vertex_shader->set_uniform_4fv(location, v);
|
vertex_shader->set_uniform_4fv(location, v);
|
||||||
fragment_shader->set_uniform_4fv(location, v);
|
|
||||||
}
|
}
|
||||||
void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
|
void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
|
||||||
const GLfloat* value) {
|
const GLfloat* value) {
|
||||||
assert(count == 1);
|
assert(count == 1);
|
||||||
assert(!transpose);
|
assert(!transpose);
|
||||||
vertex_shader->set_uniform_matrix4fv(location, value);
|
vertex_shader->set_uniform_matrix4fv(location, value);
|
||||||
fragment_shader->set_uniform_matrix4fv(location, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget,
|
void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget,
|
||||||
|
@ -2591,15 +2581,14 @@ UNUSED static inline void commit_solid_span(uint8_t* buf, PackedR8 r, int len) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename P>
|
#define DISPATCH_DRAW_SPAN(self, buf, len) do { \
|
||||||
static ALWAYS_INLINE void dispatch_draw_span(S* shader, P* buf, int len) {
|
int drawn = self->draw_span(buf, len); \
|
||||||
int drawn = shader->draw_span(buf, len);
|
if (drawn) self->step_interp_inputs(drawn >> 2); \
|
||||||
if (drawn) shader->step_interp_inputs(drawn >> 2);
|
for (buf += drawn; drawn < len; drawn += 4, buf += 4) { \
|
||||||
for (buf += drawn; drawn < len; drawn += 4, buf += 4) {
|
run(self); \
|
||||||
S::run(shader);
|
commit_span(buf, pack_span(buf)); \
|
||||||
commit_span(buf, pack_span(buf));
|
} \
|
||||||
}
|
} while (0)
|
||||||
}
|
|
||||||
|
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
|
||||||
|
@ -2607,6 +2596,7 @@ static ALWAYS_INLINE void dispatch_draw_span(S* shader, P* buf, int len) {
|
||||||
#pragma GCC diagnostic ignored "-Wuninitialized"
|
#pragma GCC diagnostic ignored "-Wuninitialized"
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-private-field"
|
||||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||||
#ifndef __clang__
|
#ifndef __clang__
|
||||||
|
@ -2615,9 +2605,6 @@ static ALWAYS_INLINE void dispatch_draw_span(S* shader, P* buf, int len) {
|
||||||
#include "load_shader.h"
|
#include "load_shader.h"
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
static const size_t MAX_FLATS = 64;
|
|
||||||
typedef float Flats[MAX_FLATS];
|
|
||||||
|
|
||||||
static const size_t MAX_INTERPOLANTS = 16;
|
static const size_t MAX_INTERPOLANTS = 16;
|
||||||
typedef VectorType<float, MAX_INTERPOLANTS> Interpolants;
|
typedef VectorType<float, MAX_INTERPOLANTS> Interpolants;
|
||||||
|
|
||||||
|
@ -3339,10 +3326,7 @@ static int clip_near_far(int nump, Point3D* p, Interpolants* interp) {
|
||||||
// by W again to produce the final correct attribute value for each fragment.
|
// by W again to produce the final correct attribute value for each fragment.
|
||||||
// This process is expensive and should be avoided if possible for primitive
|
// This process is expensive and should be avoided if possible for primitive
|
||||||
// batches that are known ahead of time to not need perspective-correction.
|
// batches that are known ahead of time to not need perspective-correction.
|
||||||
// To trigger this path, the shader should use the PERSPECTIVE feature so that
|
static void draw_perspective(int nump,
|
||||||
// the glsl-to-cxx compiler can generate the appropriate interpolation code
|
|
||||||
// needed to participate with SWGL's perspective-correction.
|
|
||||||
static void draw_perspective(int nump, Flats flat_outs,
|
|
||||||
Interpolants interp_outs[6],
|
Interpolants interp_outs[6],
|
||||||
Texture& colortex, int layer,
|
Texture& colortex, int layer,
|
||||||
Texture& depthtex) {
|
Texture& depthtex) {
|
||||||
|
@ -3391,9 +3375,6 @@ static void draw_perspective(int nump, Flats flat_outs,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize any flat/non-varying inputs.
|
|
||||||
fragment_shader->init_primitive(flat_outs);
|
|
||||||
|
|
||||||
// Finally draw perspective-correct spans for the polygon.
|
// Finally draw perspective-correct spans for the polygon.
|
||||||
if (colortex.internal_format == GL_RGBA8) {
|
if (colortex.internal_format == GL_RGBA8) {
|
||||||
draw_perspective_spans<uint32_t>(nump, p, interp_outs, colortex, layer,
|
draw_perspective_spans<uint32_t>(nump, p, interp_outs, colortex, layer,
|
||||||
|
@ -3409,16 +3390,14 @@ static void draw_perspective(int nump, Flats flat_outs,
|
||||||
static void draw_quad(int nump, Texture& colortex, int layer,
|
static void draw_quad(int nump, Texture& colortex, int layer,
|
||||||
Texture& depthtex) {
|
Texture& depthtex) {
|
||||||
// Run vertex shader once for the primitive's vertices.
|
// Run vertex shader once for the primitive's vertices.
|
||||||
Flats flat_outs;
|
|
||||||
// Reserve space for 6 sets of interpolants, in case we need to clip against
|
// Reserve space for 6 sets of interpolants, in case we need to clip against
|
||||||
// near and far planes in the perspective case.
|
// near and far planes in the perspective case.
|
||||||
Interpolants interp_outs[6] = {0};
|
Interpolants interp_outs[6] = {0};
|
||||||
vertex_shader->run((char*)flat_outs, (char*)interp_outs,
|
vertex_shader->run_primitive((char*)interp_outs, sizeof(Interpolants));
|
||||||
sizeof(Interpolants));
|
|
||||||
vec4 pos = vertex_shader->gl_Position;
|
vec4 pos = vertex_shader->gl_Position;
|
||||||
// Check if any vertex W is different from another. If so, use perspective.
|
// Check if any vertex W is different from another. If so, use perspective.
|
||||||
if (test_any(pos.w != pos.w.x)) {
|
if (test_any(pos.w != pos.w.x)) {
|
||||||
draw_perspective(nump, flat_outs, interp_outs, colortex, layer, depthtex);
|
draw_perspective(nump, interp_outs, colortex, layer, depthtex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3453,9 +3432,6 @@ static void draw_quad(int nump, Texture& colortex, int layer,
|
||||||
fragment_shader->gl_FragCoord.z = screenZ;
|
fragment_shader->gl_FragCoord.z = screenZ;
|
||||||
fragment_shader->gl_FragCoord.w = w;
|
fragment_shader->gl_FragCoord.w = w;
|
||||||
|
|
||||||
// Initialize any flat/non-varying inputs.
|
|
||||||
fragment_shader->init_primitive(flat_outs);
|
|
||||||
|
|
||||||
// Finally draw 2D spans for the quad. Currently only supports drawing to
|
// Finally draw 2D spans for the quad. Currently only supports drawing to
|
||||||
// RGBA8 and R8 color buffers.
|
// RGBA8 and R8 color buffers.
|
||||||
if (colortex.internal_format == GL_RGBA8) {
|
if (colortex.internal_format == GL_RGBA8) {
|
||||||
|
@ -3503,11 +3479,10 @@ static inline void draw_elements(GLsizei count, GLsizei instancecount,
|
||||||
// Fast path - since there is only a single quad, we only load per-vertex
|
// Fast path - since there is only a single quad, we only load per-vertex
|
||||||
// attribs once for all instances, as they won't change across instances
|
// attribs once for all instances, as they won't change across instances
|
||||||
// or within an instance.
|
// or within an instance.
|
||||||
vertex_shader->load_attribs(program_impl, v.attribs, indices[0], 0, 4);
|
vertex_shader->load_attribs(v.attribs, indices[0], 0, 4);
|
||||||
draw_quad(4, colortex, layer, depthtex);
|
draw_quad(4, colortex, layer, depthtex);
|
||||||
for (GLsizei instance = 1; instance < instancecount; instance++) {
|
for (GLsizei instance = 1; instance < instancecount; instance++) {
|
||||||
vertex_shader->load_attribs(program_impl, v.attribs, indices[0],
|
vertex_shader->load_attribs(v.attribs, indices[0], instance, 0);
|
||||||
instance, 0);
|
|
||||||
draw_quad(4, colortex, layer, depthtex);
|
draw_quad(4, colortex, layer, depthtex);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -3524,8 +3499,7 @@ static inline void draw_elements(GLsizei count, GLsizei instancecount,
|
||||||
nump = 4;
|
nump = 4;
|
||||||
i += 3;
|
i += 3;
|
||||||
}
|
}
|
||||||
vertex_shader->load_attribs(program_impl, v.attribs, indices[i],
|
vertex_shader->load_attribs(v.attribs, indices[i], instance, nump);
|
||||||
instance, nump);
|
|
||||||
draw_quad(nump, colortex, layer, depthtex);
|
draw_quad(nump, colortex, layer, depthtex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3577,8 +3551,7 @@ void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
|
||||||
ctx->shaded_rows = 0;
|
ctx->shaded_rows = 0;
|
||||||
ctx->shaded_pixels = 0;
|
ctx->shaded_pixels = 0;
|
||||||
|
|
||||||
vertex_shader->init_batch(program_impl);
|
vertex_shader->init_batch();
|
||||||
fragment_shader->init_batch(program_impl);
|
|
||||||
|
|
||||||
if (type == GL_UNSIGNED_SHORT) {
|
if (type == GL_UNSIGNED_SHORT) {
|
||||||
draw_elements<uint16_t>(count, instancecount, indices_buf, offset, v,
|
draw_elements<uint16_t>(count, instancecount, indices_buf, offset, v,
|
||||||
|
|
|
@ -12,7 +12,6 @@ struct FragmentShaderImpl;
|
||||||
struct ProgramImpl {
|
struct ProgramImpl {
|
||||||
virtual ~ProgramImpl() {}
|
virtual ~ProgramImpl() {}
|
||||||
virtual int get_uniform(const char* name) const = 0;
|
virtual int get_uniform(const char* name) const = 0;
|
||||||
virtual bool set_sampler(int index, int value) = 0;
|
|
||||||
virtual void bind_attrib(const char* name, int index) = 0;
|
virtual void bind_attrib(const char* name, int index) = 0;
|
||||||
virtual int get_attrib(const char* name) const = 0;
|
virtual int get_attrib(const char* name) const = 0;
|
||||||
virtual VertexShaderImpl* get_vertex_shader() = 0;
|
virtual VertexShaderImpl* get_vertex_shader() = 0;
|
||||||
|
@ -21,15 +20,26 @@ struct ProgramImpl {
|
||||||
|
|
||||||
typedef ProgramImpl* (*ProgramLoader)();
|
typedef ProgramImpl* (*ProgramLoader)();
|
||||||
|
|
||||||
struct ShaderImpl {
|
struct VertexShaderImpl {
|
||||||
typedef void (*SetUniform1iFunc)(ShaderImpl*, int index, int value);
|
typedef void (*SetUniform1iFunc)(VertexShaderImpl*, int index, int value);
|
||||||
typedef void (*SetUniform4fvFunc)(ShaderImpl*, int index, const float* value);
|
typedef void (*SetUniform4fvFunc)(VertexShaderImpl*, int index,
|
||||||
typedef void (*SetUniformMatrix4fvFunc)(ShaderImpl*, int index,
|
|
||||||
const float* value);
|
const float* value);
|
||||||
|
typedef void (*SetUniformMatrix4fvFunc)(VertexShaderImpl*, int index,
|
||||||
|
const float* value);
|
||||||
|
typedef void (*InitBatchFunc)(VertexShaderImpl*);
|
||||||
|
typedef void (*LoadAttribsFunc)(VertexShaderImpl*, VertexAttrib* attribs,
|
||||||
|
uint32_t start, int instance, int count);
|
||||||
|
typedef void (*RunPrimitiveFunc)(VertexShaderImpl*, char* interps,
|
||||||
|
size_t interp_stride);
|
||||||
|
|
||||||
SetUniform1iFunc set_uniform_1i_func = nullptr;
|
SetUniform1iFunc set_uniform_1i_func = nullptr;
|
||||||
SetUniform4fvFunc set_uniform_4fv_func = nullptr;
|
SetUniform4fvFunc set_uniform_4fv_func = nullptr;
|
||||||
SetUniformMatrix4fvFunc set_uniform_matrix4fv_func = nullptr;
|
SetUniformMatrix4fvFunc set_uniform_matrix4fv_func = nullptr;
|
||||||
|
InitBatchFunc init_batch_func = nullptr;
|
||||||
|
LoadAttribsFunc load_attribs_func = nullptr;
|
||||||
|
RunPrimitiveFunc run_primitive_func = nullptr;
|
||||||
|
|
||||||
|
vec4 gl_Position;
|
||||||
|
|
||||||
void set_uniform_1i(int index, int value) {
|
void set_uniform_1i(int index, int value) {
|
||||||
(*set_uniform_1i_func)(this, index, value);
|
(*set_uniform_1i_func)(this, index, value);
|
||||||
|
@ -42,37 +52,20 @@ struct ShaderImpl {
|
||||||
void set_uniform_matrix4fv(int index, const float* value) {
|
void set_uniform_matrix4fv(int index, const float* value) {
|
||||||
(*set_uniform_matrix4fv_func)(this, index, value);
|
(*set_uniform_matrix4fv_func)(this, index, value);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
struct VertexShaderImpl : ShaderImpl {
|
void init_batch() { (*init_batch_func)(this); }
|
||||||
typedef void (*InitBatchFunc)(VertexShaderImpl*, ProgramImpl* prog);
|
|
||||||
typedef void (*LoadAttribsFunc)(VertexShaderImpl*, ProgramImpl* prog,
|
|
||||||
VertexAttrib* attribs, uint32_t start,
|
|
||||||
int instance, int count);
|
|
||||||
typedef void (*RunFunc)(VertexShaderImpl*, char* flats, char* interps,
|
|
||||||
size_t interp_stride);
|
|
||||||
|
|
||||||
InitBatchFunc init_batch_func = nullptr;
|
ALWAYS_INLINE void load_attribs(VertexAttrib* attribs, uint32_t start,
|
||||||
LoadAttribsFunc load_attribs_func = nullptr;
|
int instance, int count) {
|
||||||
RunFunc run_func = nullptr;
|
(*load_attribs_func)(this, attribs, start, instance, count);
|
||||||
|
|
||||||
vec4 gl_Position;
|
|
||||||
|
|
||||||
void init_batch(ProgramImpl* prog) { (*init_batch_func)(this, prog); }
|
|
||||||
|
|
||||||
ALWAYS_INLINE void load_attribs(ProgramImpl* prog, VertexAttrib* attribs,
|
|
||||||
uint32_t start, int instance, int count) {
|
|
||||||
(*load_attribs_func)(this, prog, attribs, start, instance, count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void run(char* flats, char* interps, size_t interp_stride) {
|
ALWAYS_INLINE void run_primitive(char* interps, size_t interp_stride) {
|
||||||
(*run_func)(this, flats, interps, interp_stride);
|
(*run_primitive_func)(this, interps, interp_stride);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FragmentShaderImpl : ShaderImpl {
|
struct FragmentShaderImpl {
|
||||||
typedef void (*InitBatchFunc)(FragmentShaderImpl*, ProgramImpl* prog);
|
|
||||||
typedef void (*InitPrimitiveFunc)(FragmentShaderImpl*, const void* flats);
|
|
||||||
typedef void (*InitSpanFunc)(FragmentShaderImpl*, const void* interps,
|
typedef void (*InitSpanFunc)(FragmentShaderImpl*, const void* interps,
|
||||||
const void* step, float step_width);
|
const void* step, float step_width);
|
||||||
typedef void (*RunFunc)(FragmentShaderImpl*);
|
typedef void (*RunFunc)(FragmentShaderImpl*);
|
||||||
|
@ -85,8 +78,6 @@ struct FragmentShaderImpl : ShaderImpl {
|
||||||
int len);
|
int len);
|
||||||
typedef void (*DrawSpanR8Func)(FragmentShaderImpl*, uint8_t* buf, int len);
|
typedef void (*DrawSpanR8Func)(FragmentShaderImpl*, uint8_t* buf, int len);
|
||||||
|
|
||||||
InitBatchFunc init_batch_func = nullptr;
|
|
||||||
InitPrimitiveFunc init_primitive_func = nullptr;
|
|
||||||
InitSpanFunc init_span_func = nullptr;
|
InitSpanFunc init_span_func = nullptr;
|
||||||
RunFunc run_func = nullptr;
|
RunFunc run_func = nullptr;
|
||||||
SkipFunc skip_func = nullptr;
|
SkipFunc skip_func = nullptr;
|
||||||
|
@ -130,12 +121,6 @@ struct FragmentShaderImpl : ShaderImpl {
|
||||||
gl_FragCoord.w += stepZW.y * chunks;
|
gl_FragCoord.w += stepZW.y * chunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_batch(ProgramImpl* prog) { (*init_batch_func)(this, prog); }
|
|
||||||
|
|
||||||
void init_primitive(const void* flats) {
|
|
||||||
(*init_primitive_func)(this, flats);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool W = false>
|
template <bool W = false>
|
||||||
ALWAYS_INLINE void init_span(const void* interps, const void* step,
|
ALWAYS_INLINE void init_span(const void* interps, const void* step,
|
||||||
float step_width) {
|
float step_width) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче