Skip to content

Commit

Permalink
fix(client_core): 🐛 Workaround for blank right eye view (#2397)
Browse files Browse the repository at this point in the history
  • Loading branch information
zmerp committed Sep 20, 2024
1 parent ac0189b commit 3436a53
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 92 deletions.
7 changes: 5 additions & 2 deletions alvr/client_core/resources/staging_vertex.glsl
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#version 300 es

uniform int view_idx;

out vec2 uv;

void main() {
uv = vec2(gl_VertexID & 1, gl_VertexID >> 1);
gl_Position = vec4((uv - 0.5f) * 2.f, 0, 1);
vec2 screen_uv = vec2(gl_VertexID & 1, gl_VertexID >> 1);
gl_Position = vec4((screen_uv - 0.5f) * 2.f, 0, 1);
uv = vec2((screen_uv.x + float(view_idx)) / 2.f, screen_uv.y);
}
6 changes: 2 additions & 4 deletions alvr/client_core/resources/stream.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ override FIX_LIMITED_RANGE: bool;
override ENABLE_SRGB_CORRECTION: bool;
override ENCODING_GAMMA: f32;

var<push_constant> view_idx: u32;

struct VertexOutput {
@builtin(position) position: vec4f,
@location(0) uv: vec2f,
Expand All @@ -27,8 +25,8 @@ fn vertex_main(@builtin(vertex_index) vertex_index: u32) -> VertexOutput {
var result: VertexOutput;

let screen_uv = vec2f(f32(vertex_index & 1), f32(vertex_index >> 1));
result.position = vec4f((screen_uv - vec2f(0.5, 0.5)) * 2.0, 0.0, 1.0);
result.uv = vec2f((screen_uv.x + f32(view_idx)) / 2.0, screen_uv.y);
result.position = vec4f((screen_uv - 0.5) * 2.0, 0.0, 1.0);
result.uv = vec2f(screen_uv.x, screen_uv.y);

return result;
}
Expand Down
55 changes: 35 additions & 20 deletions alvr/client_core/src/graphics/staging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,17 @@ fn create_program(
pub struct StagingRenderer {
context: Rc<GraphicsContext>,
program: gl::Program,
view_idx_uloc: gl::UniformLocation,
surface_texture: gl::Texture,
framebuffer: gl::Framebuffer,
framebuffers: [gl::Framebuffer; 2],
viewport_size: IVec2,
}

impl StagingRenderer {
pub fn new(
context: Rc<GraphicsContext>,
staging_texture: gl::Texture,
resolution: UVec2,
staging_textures: [gl::Texture; 2],
view_resolution: UVec2,
) -> Self {
let gl = &context.gl_context;
context.make_current();
Expand All @@ -75,23 +76,32 @@ impl StagingRenderer {
// This is an external surface and storage should not be initialized
let surface_texture = ck!(gl.create_texture().unwrap());

let framebuffer = ck!(gl.create_framebuffer().unwrap());
ck!(gl.bind_framebuffer(gl::DRAW_FRAMEBUFFER, Some(framebuffer)));
ck!(gl.framebuffer_texture_2d(
gl::DRAW_FRAMEBUFFER,
gl::COLOR_ATTACHMENT0,
gl::TEXTURE_2D,
Some(staging_texture),
0,
));
let mut framebuffers = vec![];
for tex in staging_textures {
let framebuffer = ck!(gl.create_framebuffer().unwrap());
ck!(gl.bind_framebuffer(gl::DRAW_FRAMEBUFFER, Some(framebuffer)));
ck!(gl.framebuffer_texture_2d(
gl::DRAW_FRAMEBUFFER,
gl::COLOR_ATTACHMENT0,
gl::TEXTURE_2D,
Some(tex),
0,
));

framebuffers.push(framebuffer);
}

ck!(gl.bind_framebuffer(gl::FRAMEBUFFER, None));

let view_idx_uloc = ck!(gl.get_uniform_location(program, "view_idx")).unwrap();

Self {
context,
program,
surface_texture,
framebuffer,
viewport_size: resolution.as_ivec2(),
view_idx_uloc,
framebuffers: framebuffers.try_into().unwrap(),
viewport_size: view_resolution.as_ivec2(),
}
}
}
Expand All @@ -109,12 +119,15 @@ impl StagingRenderer {

ck!(gl.viewport(0, 0, self.viewport_size.x, self.viewport_size.y));

ck!(gl.bind_framebuffer(gl::DRAW_FRAMEBUFFER, Some(self.framebuffer)));
for (i, framebuffer) in self.framebuffers.iter().enumerate() {
ck!(gl.bind_framebuffer(gl::DRAW_FRAMEBUFFER, Some(*framebuffer)));

ck!(gl.active_texture(gl::TEXTURE0));
ck!(gl.bind_texture(GL_TEXTURE_EXTERNAL_OES, Some(self.surface_texture)));
ck!(gl.bind_sampler(0, None));
ck!(gl.draw_arrays(gl::TRIANGLE_STRIP, 0, 4));
ck!(gl.active_texture(gl::TEXTURE0));
ck!(gl.bind_texture(GL_TEXTURE_EXTERNAL_OES, Some(self.surface_texture)));
ck!(gl.bind_sampler(0, None));
ck!(gl.uniform_1_i32(Some(&self.view_idx_uloc), i as i32));
ck!(gl.draw_arrays(gl::TRIANGLE_STRIP, 0, 4));
}
},
);
}
Expand All @@ -128,7 +141,9 @@ impl Drop for StagingRenderer {
unsafe {
ck!(gl.delete_program(self.program));
ck!(gl.delete_texture(self.surface_texture));
ck!(gl.delete_framebuffer(self.framebuffer));
for framebuffer in &self.framebuffers {
ck!(gl.delete_framebuffer(*framebuffer));
}
}
}
}
131 changes: 65 additions & 66 deletions alvr/client_core/src/graphics/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@ use wgpu::{
include_wgsl, BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor,
BindGroupLayoutEntry, BindingResource, BindingType, ColorTargetState, ColorWrites,
FragmentState, LoadOp, PipelineCompilationOptions, PipelineLayoutDescriptor, PrimitiveState,
PrimitiveTopology, PushConstantRange, RenderPassColorAttachment, RenderPassDescriptor,
RenderPipeline, RenderPipelineDescriptor, SamplerBindingType, SamplerDescriptor, ShaderStages,
StoreOp, TextureSampleType, TextureView, TextureViewDescriptor, TextureViewDimension,
VertexState,
PrimitiveTopology, RenderPassColorAttachment, RenderPassDescriptor, RenderPipeline,
RenderPipelineDescriptor, SamplerBindingType, SamplerDescriptor, ShaderStages, StoreOp,
TextureSampleType, TextureView, TextureViewDescriptor, TextureViewDimension, VertexState,
};

#[derive(Debug)]
struct ViewObjects {
bind_group: BindGroup,
render_target: Vec<TextureView>,
}

struct RenderObjects {
staging_renderer: StagingRenderer,
pipeline: RenderPipeline,
bind_group: BindGroup,
render_targets: [Vec<TextureView>; 2],
views_objects: [ViewObjects; 2],
}

pub struct StreamRenderer {
Expand Down Expand Up @@ -73,13 +77,9 @@ impl StreamRenderer {
}
} else {
let device = &context.device;
let gl = &context.gl_context;

let staging_resolution = UVec2::new(view_resolution.x * 2, view_resolution.y);
let target_format = super::gl_format_to_wgpu(target_format);

let staging_texture = super::create_texture(device, staging_resolution, target_format);

let bind_group_layout = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: None,
entries: &[
Expand Down Expand Up @@ -120,10 +120,7 @@ impl StreamRenderer {
layout: Some(&device.create_pipeline_layout(&PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[&bind_group_layout],
push_constant_ranges: &[PushConstantRange {
stages: ShaderStages::VERTEX_FRAGMENT,
range: 0..4,
}],
push_constant_ranges: &[],
})),
vertex: VertexState {
module: &shader_module,
Expand Down Expand Up @@ -156,63 +153,70 @@ impl StreamRenderer {
multiview: None,
});

let bind_group = device.create_bind_group(&BindGroupDescriptor {
label: None,
layout: &bind_group_layout,
entries: &[
BindGroupEntry {
binding: 0,
resource: BindingResource::TextureView(
&staging_texture.create_view(&TextureViewDescriptor::default()),
),
},
BindGroupEntry {
binding: 1,
resource: BindingResource::Sampler(&device.create_sampler(
&SamplerDescriptor {
mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Linear,
..Default::default()
},
)),
},
],
let sampler = device.create_sampler(&SamplerDescriptor {
mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Linear,
..Default::default()
});

let render_targets = [
super::create_gl_swapchain(
device,
&swapchain_textures[0],
view_resolution,
target_format,
),
super::create_gl_swapchain(
let mut view_objects = vec![];
let mut staging_textures_gl = vec![];
for i in 0..2 {
let staging_texture =
super::create_texture(&device, view_resolution, target_format);

let staging_texture_gl = unsafe {
staging_texture.as_hal::<api::Gles, _, _>(|tex| {
let gles::TextureInner::Texture { raw, .. } = tex.unwrap().inner else {
panic!("invalid texture type");
};
raw
})
};

let bind_group = device.create_bind_group(&BindGroupDescriptor {
label: None,
layout: &bind_group_layout,
entries: &[
BindGroupEntry {
binding: 0,
resource: BindingResource::TextureView(
&staging_texture.create_view(&TextureViewDescriptor::default()),
),
},
BindGroupEntry {
binding: 1,
resource: BindingResource::Sampler(&sampler),
},
],
});

let render_target = super::create_gl_swapchain(
device,
&swapchain_textures[1],
&swapchain_textures[i],
view_resolution,
target_format,
),
];
);

let staging_texture_gl = unsafe {
staging_texture.as_hal::<api::Gles, _, _>(|tex| {
let gles::TextureInner::Texture { raw, .. } = tex.unwrap().inner else {
panic!("invalid texture type");
};
raw
})
};
view_objects.push(ViewObjects {
bind_group,
render_target,
});
staging_textures_gl.push(staging_texture_gl);
}

let staging_renderer =
StagingRenderer::new(Rc::clone(&context), staging_texture_gl, staging_resolution);
let staging_renderer = StagingRenderer::new(
Rc::clone(&context),
staging_textures_gl.try_into().unwrap(),
view_resolution,
);

Self {
context,
render_objects: Some(RenderObjects {
staging_renderer,
pipeline,
bind_group,
render_targets,
views_objects: view_objects.try_into().unwrap(),
}),
}
}
Expand All @@ -235,7 +239,7 @@ impl StreamRenderer {
let mut render_pass = encoder.begin_render_pass(&RenderPassDescriptor {
label: None,
color_attachments: &[Some(RenderPassColorAttachment {
view: &self.render_objects.as_ref().unwrap().render_targets[view_idx]
view: &render_objects.views_objects[view_idx].render_target
[*swapchain_idx as usize],
resolve_target: None,
ops: wgpu::Operations {
Expand All @@ -246,17 +250,12 @@ impl StreamRenderer {
..Default::default()
});

render_pass.set_pipeline(&self.render_objects.as_ref().unwrap().pipeline);
render_pass.set_pipeline(&render_objects.pipeline);
render_pass.set_bind_group(
0,
&self.render_objects.as_ref().unwrap().bind_group,
&render_objects.views_objects[view_idx].bind_group,
&[],
);
render_pass.set_push_constants(
ShaderStages::VERTEX_FRAGMENT,
0,
&(view_idx as u32).to_le_bytes(),
);
render_pass.draw(0..4, 0..1);
}

Expand Down

0 comments on commit 3436a53

Please sign in to comment.