Skip to content

Commit

Permalink
Bug 1749225 - Avoid casting function pointers in glsl-to-cxx. r=aosmond
Browse files Browse the repository at this point in the history
Due to the presence of multiple inheritance, casting between ShaderImpl and
derived types in function pointers may be classified as undefined behavior.
While the multiple inheritance chain tries to ensure that the ShaderImpl
is the first in the list of class parents, this might not be sufficiently
safe. Explicitly do the casting of individual parameters without casting the
function pointers to work around this.

Differential Revision: https://phabricator.services.mozilla.com/D136611

[ghsync] From https://hg.mozilla.org/mozilla-central/rev/ba18c6833fd629140b8e4757883f328450d5bd93
  • Loading branch information
lsalzman committed Jan 22, 2022
1 parent 53be4c1 commit 2984735
Showing 1 changed file with 51 additions and 37 deletions.
88 changes: 51 additions & 37 deletions glsl-to-cxx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,9 +357,10 @@ fn write_set_uniform_1i(
uniforms: &UniformIndices,
) {
write!(
state,
"static void set_uniform_1i(Self *self, int index, int value) {{\n"
state,
"static void set_uniform_1i(VertexShaderImpl* impl, int index, int value) {{\n"
);
write!(state, " Self* self = (Self*)impl;\n");
write!(state, " if (self->samplers.set_slot(index, value)) return;\n");
write!(state, " switch (index) {{\n");
for (name, (index, tk, _)) in uniforms {
Expand All @@ -385,8 +386,9 @@ fn write_set_uniform_4fv(
) {
write!(
state,
"static void set_uniform_4fv(Self *self, int index, const float *value) {{\n"
"static void set_uniform_4fv(VertexShaderImpl* impl, int index, const float *value) {{\n"
);
write!(state, " Self* self = (Self*)impl;\n");
write!(state, " switch (index) {{\n");
for (name, (index, tk, _)) in uniforms {
write!(state, " case {}:\n", index);
Expand All @@ -411,8 +413,9 @@ fn write_set_uniform_matrix4fv(
) {
write!(
state,
"static void set_uniform_matrix4fv(Self *self, int index, const float *value) {{\n"
"static void set_uniform_matrix4fv(VertexShaderImpl* impl, int index, const float *value) {{\n"
);
write!(state, " Self* self = (Self*)impl;\n");
write!(state, " switch (index) {{\n");
for (name, (index, tk, _)) in uniforms {
write!(state, " case {}:\n", index);
Expand Down Expand Up @@ -510,8 +513,9 @@ fn write_common_globals(state: &mut OutputState, attribs: &[hir::SymRef],

fn write_load_attribs(state: &mut OutputState, attribs: &[hir::SymRef]) {
write!(state, "static void load_attribs(\
Self *self, VertexAttrib *attribs, \
uint32_t start, int instance, int count) {{\n");
VertexShaderImpl* impl, VertexAttrib *attribs, \
uint32_t start, int instance, int count) {{\
Self* self = (Self*)impl;\n");
for i in attribs {
let sym = state.hir.sym(*i);
match &sym.decl {
Expand Down Expand Up @@ -622,7 +626,10 @@ 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) {{\n");
FragmentShaderImpl* impl, const void* init_, const void* step_) {{\
Self* self = (Self*)impl;\
const InterpInputs* init = (const InterpInputs*)init_;\
const InterpInputs* step = (const InterpInputs*)step_;\n");
for i in inputs {
let sym = state.hir.sym(*i);
match &sym.decl {
Expand Down Expand Up @@ -653,7 +660,10 @@ 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) {{\n");
FragmentShaderImpl* impl, const void* init_, const void* step_) {{\
Self* self = (Self*)impl;\
const InterpInputs* init = (const InterpInputs*)init_;\
const InterpInputs* step = (const InterpInputs*)step_;\n");
if has_varying {
write!(state, " Float w = 1.0f / self->gl_FragCoord.w;\n");
}
Expand Down Expand Up @@ -3544,83 +3554,87 @@ pub fn show_translation_unit(state: &mut OutputState, tu: &hir::TranslationUnit)
fn write_abi(state: &mut OutputState) {
match state.kind {
ShaderKind::Fragment => {
state.write("static void run(Self *self) {\n");
state.write("static void run(FragmentShaderImpl* impl) {\n");
state.write(" Self* self = (Self*)impl;\n");
if state.uses_discard {
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 steps) {\n");
state.write("static void skip(FragmentShaderImpl* impl, int steps) {\n");
state.write(" Self* self = (Self*)impl;\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");
state.write("static void run_perspective(FragmentShaderImpl* impl) {\n");
state.write(" Self* self = (Self*)impl;\n");
if state.uses_discard {
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 steps) {\n");
state.write("static void skip_perspective(FragmentShaderImpl* impl, int steps) {\n");
state.write(" Self* self = (Self*)impl;\n");
state.write(" self->step_perspective_inputs(steps);\n");
state.write("}\n");
}
if state.hir.lookup("swgl_drawSpanRGBA8").is_some() {
state.write(
"static int draw_span_RGBA8(Self* self) { DISPATCH_DRAW_SPAN(self, RGBA8); }\n");
state.write("static int draw_span_RGBA8(FragmentShaderImpl* impl) {\n");
state.write(" Self* self = (Self*)impl; DISPATCH_DRAW_SPAN(self, RGBA8); }\n");
}
if state.hir.lookup("swgl_drawSpanR8").is_some() {
state.write(
"static int draw_span_R8(Self* self) { DISPATCH_DRAW_SPAN(self, R8); }\n");
state.write("static int draw_span_R8(FragmentShaderImpl* impl) {\n");
state.write(" Self* self = (Self*)impl; DISPATCH_DRAW_SPAN(self, R8); }\n");
}

write!(state, "public:\n{}_frag() {{\n", state.name);
}
ShaderKind::Vertex => {
state.write(
"static void run(Self* self, char* interps, size_t interp_stride) {\n",
);
state.write("static void run(VertexShaderImpl* impl, char* interps, size_t interp_stride) {\n");
state.write(" Self* self = (Self*)impl;\n");
state.write(" self->main();\n");
state.write(" self->store_interp_outputs(interps, interp_stride);\n");
state.write("}\n");
state.write("static void init_batch(Self *self) { self->bind_textures(); }\n");
state.write("static void init_batch(VertexShaderImpl* impl) {\n");
state.write(" Self* self = (Self*)impl; self->bind_textures(); }\n");

write!(state, "public:\n{}_vert() {{\n", state.name);
}
}
match state.kind {
ShaderKind::Fragment => {
state.write(" init_span_func = (InitSpanFunc)&read_interp_inputs;\n");
state.write(" run_func = (RunFunc)&run;\n");
state.write(" skip_func = (SkipFunc)&skip;\n");
state.write(" init_span_func = &read_interp_inputs;\n");
state.write(" run_func = &run;\n");
state.write(" skip_func = &skip;\n");
if state.hir.lookup("swgl_drawSpanRGBA8").is_some() {
state.write(" draw_span_RGBA8_func = (DrawSpanRGBA8Func)&draw_span_RGBA8;\n");
state.write(" draw_span_RGBA8_func = &draw_span_RGBA8;\n");
}
if state.hir.lookup("swgl_drawSpanR8").is_some() {
state.write(" draw_span_R8_func = (DrawSpanR8Func)&draw_span_R8;\n");
state.write(" draw_span_R8_func = &draw_span_R8;\n");
}
if state.uses_discard {
state.write(" enable_discard();\n");
}
if state.use_perspective {
state.write(" enable_perspective();\n");
state.write(" init_span_w_func = (InitSpanWFunc)&read_perspective_inputs;\n");
state.write(" run_w_func = (RunWFunc)&run_perspective;\n");
state.write(" skip_w_func = (SkipWFunc)&skip_perspective;\n");
state.write(" init_span_w_func = &read_perspective_inputs;\n");
state.write(" run_w_func = &run_perspective;\n");
state.write(" skip_w_func = &skip_perspective;\n");
} else {
state.write(" init_span_w_func = (InitSpanWFunc)&read_interp_inputs;\n");
state.write(" run_w_func = (RunWFunc)&run;\n");
state.write(" skip_w_func = (SkipWFunc)&skip;\n");
state.write(" init_span_w_func = &read_interp_inputs;\n");
state.write(" run_w_func = &run;\n");
state.write(" skip_w_func = &skip;\n");
}
}
ShaderKind::Vertex => {
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(" run_primitive_func = (RunPrimitiveFunc)&run;\n");
state.write(" set_uniform_1i_func = &set_uniform_1i;\n");
state.write(" set_uniform_4fv_func = &set_uniform_4fv;\n");
state.write(" set_uniform_matrix4fv_func = &set_uniform_matrix4fv;\n");
state.write(" init_batch_func = &init_batch;\n");
state.write(" load_attribs_func = &load_attribs;\n");
state.write(" run_primitive_func = &run;\n");
if state.hir.used_clip_dist != 0 {
state.write(" enable_clip_distance();\n");
}
Expand Down

0 comments on commit 2984735

Please sign in to comment.