Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve OpenGL 3.1 support #4272

Merged
merged 2 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions wgpu-hal/src/gles/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,25 @@ impl super::Adapter {
.is_none()
.then_some(())
.and_then(|_| Self::parse_version(&version).ok());
let web_gl = cfg!(target_arch = "wasm32");

if let Some(full_ver) = full_ver {
let core_profile = (full_ver >= (3, 2)).then_some(unsafe {
gl.get_parameter_i32(glow::CONTEXT_PROFILE_MASK)
& glow::CONTEXT_CORE_PROFILE_BIT as i32
!= 0
});
log::trace!(
"Profile: {}",
core_profile
.map(|core_profile| if core_profile {
"Core"
} else {
"Compatibility"
})
.unwrap_or("Legacy")
);
}

if es_ver.is_none() && full_ver.is_none() {
log::warn!("Unable to parse OpenGL version");
Expand Down Expand Up @@ -584,6 +603,14 @@ impl super::Adapter {
},
);
private_caps.set(super::PrivateCapabilities::QUERY_BUFFERS, query_buffers);
private_caps.set(
super::PrivateCapabilities::TEXTURE_STORAGE,
supported((3, 0), (4, 2)),
);
private_caps.set(
super::PrivateCapabilities::DEBUG_FNS,
supported((3, 2), (4, 3)) && !web_gl,
);

let max_texture_size = unsafe { gl.get_parameter_i32(glow::MAX_TEXTURE_SIZE) } as u32;
let max_texture_3d_size = unsafe { gl.get_parameter_i32(glow::MAX_3D_TEXTURE_SIZE) } as u32;
Expand Down
15 changes: 8 additions & 7 deletions wgpu-hal/src/gles/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,13 +535,6 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
.push(glow::STENCIL_ATTACHMENT);
}
}

if !rendering_to_external_framebuffer {
// set the draw buffers and states
self.cmd_buffer
.commands
.push(C::SetDrawColorBuffers(desc.color_attachments.len() as u8));
}
}
}

Expand Down Expand Up @@ -586,6 +579,14 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
);
}
}

if !rendering_to_external_framebuffer {
// set the draw buffers and states
self.cmd_buffer
.commands
.push(C::SetDrawColorBuffers(desc.color_attachments.len() as u8));
}

if let Some(ref dsat) = desc.depth_stencil_attachment {
let clear_depth = !dsat.depth_ops.contains(crate::AttachmentOps::LOAD);
let clear_stencil = !dsat.stencil_ops.contains(crate::AttachmentOps::LOAD);
Expand Down
99 changes: 87 additions & 12 deletions wgpu-hal/src/gles/device.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use super::conv;
use super::{conv, PrivateCapabilities};
use crate::auxil::map_naga_stage;
use glow::HasContext;
use std::{
cmp::max,
convert::TryInto,
ptr,
sync::{Arc, Mutex},
Expand All @@ -28,9 +29,12 @@ struct CompilationContext<'a> {
impl CompilationContext<'_> {
fn consume_reflection(
self,
gl: &glow::Context,
module: &naga::Module,
ep_info: &naga::valid::FunctionInfo,
reflection_info: naga::back::glsl::ReflectionInfo,
naga_stage: naga::ShaderStage,
program: glow::Program,
) {
for (handle, var) in module.global_variables.iter() {
if ep_info[handle].is_empty() {
Expand Down Expand Up @@ -83,6 +87,20 @@ impl CompilationContext<'_> {
self.sampler_map[texture_linear_index as usize] = Some(sampler_linear_index);
}
}

for (name, location) in reflection_info.varying {
match naga_stage {
naga::ShaderStage::Vertex => {
assert_eq!(location.index, 0);
unsafe { gl.bind_attrib_location(program, location.location, &name) }
}
naga::ShaderStage::Fragment => {
assert_eq!(location.index, 0);
unsafe { gl.bind_frag_data_location(program, location.location, &name) }
}
naga::ShaderStage::Compute => {}
}
}
}
}

Expand Down Expand Up @@ -176,6 +194,8 @@ impl super::Device {
}
Ok(raw)
} else {
log::error!("\tShader compilation failed: {}", msg);
unsafe { gl.delete_shader(raw) };
Err(crate::PipelineError::Linkage(
map_naga_stage(naga_stage),
msg,
Expand All @@ -188,6 +208,7 @@ impl super::Device {
naga_stage: naga::ShaderStage,
stage: &crate::ProgrammableStage<super::Api>,
context: CompilationContext,
program: glow::Program,
) -> Result<glow::Shader, crate::PipelineError> {
use naga::back::glsl;
let pipeline_options = glsl::PipelineOptions {
Expand All @@ -205,9 +226,9 @@ impl super::Device {
.ok_or(crate::PipelineError::EntryPoint(naga_stage))?;

use naga::proc::BoundsCheckPolicy;
// The image bounds checks require the TEXTURE_LEVELS feature available in GL core 1.3+.
// The image bounds checks require the TEXTURE_LEVELS feature available in GL core 4.3+.
let version = gl.version();
let image_check = if !version.is_embedded && (version.major, version.minor) >= (1, 3) {
let image_check = if !version.is_embedded && (version.major, version.minor) >= (4, 3) {
BoundsCheckPolicy::ReadZeroSkipWrite
} else {
BoundsCheckPolicy::Unchecked
Expand Down Expand Up @@ -244,9 +265,12 @@ impl super::Device {
log::debug!("Naga generated shader:\n{}", output);

context.consume_reflection(
gl,
&shader.module,
shader.info.get_entry_point(entry_point_index),
reflection_info,
naga_stage,
program,
);

unsafe { Self::compile_shader(gl, &output, naga_stage, stage.module.label.as_deref()) }
Expand Down Expand Up @@ -308,7 +332,7 @@ impl super::Device {
#[cfg_attr(target_arch = "wasm32", allow(unused))] label: Option<&str>,
multiview: Option<std::num::NonZeroU32>,
glsl_version: naga::back::glsl::Version,
private_caps: super::PrivateCapabilities,
private_caps: PrivateCapabilities,
) -> Result<Arc<super::PipelineInner>, crate::PipelineError> {
let glsl_version = match glsl_version {
naga::back::glsl::Version::Embedded { version, .. } => format!("{version} es"),
Expand Down Expand Up @@ -337,7 +361,7 @@ impl super::Device {
multiview,
};

let shader = Self::create_shader(gl, naga_stage, stage, context)?;
let shader = Self::create_shader(gl, naga_stage, stage, context, program)?;
shaders_to_delete.push(shader);
}

Expand Down Expand Up @@ -748,13 +772,64 @@ impl crate::Device<super::Api> for super::Device {
};
} else {
unsafe {
gl.tex_storage_2d(
target,
desc.mip_level_count as i32,
format_desc.internal,
desc.size.width as i32,
desc.size.height as i32,
)
if self
.shared
.private_caps
.contains(PrivateCapabilities::TEXTURE_STORAGE)
{
gl.tex_storage_2d(
target,
desc.mip_level_count as i32,
format_desc.internal,
desc.size.width as i32,
desc.size.height as i32,
)
} else if target == glow::TEXTURE_CUBE_MAP {
let mut width = desc.size.width;
let mut height = desc.size.width;
for i in 0..desc.mip_level_count {
for face in [
glow::TEXTURE_CUBE_MAP_POSITIVE_X,
glow::TEXTURE_CUBE_MAP_NEGATIVE_X,
glow::TEXTURE_CUBE_MAP_POSITIVE_Y,
glow::TEXTURE_CUBE_MAP_NEGATIVE_Y,
glow::TEXTURE_CUBE_MAP_POSITIVE_Z,
glow::TEXTURE_CUBE_MAP_NEGATIVE_Z,
] {
gl.tex_image_2d(
face,
i as i32,
format_desc.internal as i32,
width as i32,
height as i32,
0,
format_desc.external,
format_desc.data_type,
None,
);
}
width = max(1, width / 2);
height = max(1, height / 2);
}
} else {
let mut width = desc.size.width;
let mut height = desc.size.width;
for i in 0..desc.mip_level_count {
gl.tex_image_2d(
target,
i as i32,
format_desc.internal as i32,
width as i32,
height as i32,
0,
format_desc.external,
format_desc.data_type,
None,
);
width = max(1, width / 2);
height = max(1, height / 2);
}
}
};
}

Expand Down
4 changes: 4 additions & 0 deletions wgpu-hal/src/gles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ bitflags::bitflags! {
const TEXTURE_FLOAT_LINEAR = 1 << 10;
/// Supports query buffer objects.
const QUERY_BUFFERS = 1 << 11;
/// Supports `glTexStorage2D`, etc.
const TEXTURE_STORAGE = 1 << 12;
/// Supports `push_debug_group`, `pop_debug_group` and `debug_message_insert`.
const DEBUG_FNS = 1 << 13;
}
}

Expand Down
70 changes: 48 additions & 22 deletions wgpu-hal/src/gles/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ use arrayvec::ArrayVec;
use glow::HasContext;
use std::{mem, slice, sync::Arc};

#[cfg(not(target_arch = "wasm32"))]
const DEBUG_ID: u32 = 0;

#[cfg(not(target_arch = "wasm32"))]
fn extract_marker<'a>(data: &'a [u8], range: &std::ops::Range<u32>) -> &'a str {
std::str::from_utf8(&data[range.start as usize..range.end as usize]).unwrap()
}
Expand Down Expand Up @@ -992,6 +990,14 @@ impl super::Queue {
&& is_srgb
{
unsafe { self.perform_shader_clear(gl, draw_buffer, *color) };
} else if draw_buffer < 32 {
// Prefer `clear_color` as `clear_buffer_f32_slice` crashes on Sandy Bridge
// on Windows.
unsafe {
gl.draw_buffers(&[glow::COLOR_ATTACHMENT0 + draw_buffer]);
gl.clear_color(color[0], color[1], color[2], color[3]);
gl.clear(glow::COLOR_BUFFER_BIT);
}
} else {
unsafe { gl.clear_buffer_f32_slice(glow::COLOR, draw_buffer, color) };
}
Expand Down Expand Up @@ -1364,34 +1370,45 @@ impl super::Queue {
)
};
}
#[cfg(not(target_arch = "wasm32"))]
C::InsertDebugMarker(ref range) => {
let marker = extract_marker(data_bytes, range);
unsafe {
gl.debug_message_insert(
glow::DEBUG_SOURCE_APPLICATION,
glow::DEBUG_TYPE_MARKER,
DEBUG_ID,
glow::DEBUG_SEVERITY_NOTIFICATION,
marker,
)
if self
.shared
.private_caps
.contains(PrivateCapabilities::DEBUG_FNS)
{
gl.debug_message_insert(
glow::DEBUG_SOURCE_APPLICATION,
glow::DEBUG_TYPE_MARKER,
DEBUG_ID,
glow::DEBUG_SEVERITY_NOTIFICATION,
marker,
)
}
};
}
#[cfg(target_arch = "wasm32")]
C::InsertDebugMarker(_) => (),
#[cfg_attr(target_arch = "wasm32", allow(unused))]
C::PushDebugGroup(ref range) => {
#[cfg(not(target_arch = "wasm32"))]
let marker = extract_marker(data_bytes, range);
#[cfg(not(target_arch = "wasm32"))]
unsafe {
gl.push_debug_group(glow::DEBUG_SOURCE_APPLICATION, DEBUG_ID, marker)
if self
.shared
.private_caps
.contains(PrivateCapabilities::DEBUG_FNS)
{
gl.push_debug_group(glow::DEBUG_SOURCE_APPLICATION, DEBUG_ID, marker)
}
};
}
C::PopDebugGroup => {
#[cfg(not(target_arch = "wasm32"))]
unsafe {
gl.pop_debug_group()
if self
.shared
.private_caps
.contains(PrivateCapabilities::DEBUG_FNS)
{
gl.pop_debug_group()
}
};
}
C::SetPushConstants {
Expand Down Expand Up @@ -1476,17 +1493,26 @@ impl crate::Queue<super::Api> for super::Queue {
// this at the beginning of the loop in case something outside of wgpu modified
// this state prior to commit.
unsafe { self.reset_state(gl) };
#[cfg(not(target_arch = "wasm32"))]
if let Some(ref label) = cmd_buf.label {
unsafe { gl.push_debug_group(glow::DEBUG_SOURCE_APPLICATION, DEBUG_ID, label) };
if self
.shared
.private_caps
.contains(PrivateCapabilities::DEBUG_FNS)
{
unsafe { gl.push_debug_group(glow::DEBUG_SOURCE_APPLICATION, DEBUG_ID, label) };
}
}

for command in cmd_buf.commands.iter() {
unsafe { self.process(gl, command, &cmd_buf.data_bytes, &cmd_buf.queries) };
}

#[cfg(not(target_arch = "wasm32"))]
if cmd_buf.label.is_some() {
if cmd_buf.label.is_some()
&& self
.shared
.private_caps
.contains(PrivateCapabilities::DEBUG_FNS)
{
unsafe { gl.pop_debug_group() };
}
}
Expand Down
Loading