mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-07 11:56:51 +00:00
Bug 1688921 - Support GPU cache resize when EXT_color_buffer_float is not supported. r=kvark
Currently when the GPU cache is resized we allocate a new texture and then copy the contents of the old texture to the new texture. This copy requires either EXT_copy_image (for glCopyImageSubData) or EXT_color_buffer_float (to bind the RGBAF32 texture to a framebuffer). On devices where neither extension is supported, don't attempt to copy the old texture. Instead mark the entire CPU-side copy of the cache as dirty, meaning we will subsequently upload the entire contents to the new texture. (A complete CPU-side copy is only mainted for the PixelBuffer gpu cache bus type, not for Scatter ones. However, as the Scatter type also requires EXT_color_buffer_float, we will only be in this situation for PixelBuffer buses.) Differential Revision: https://phabricator.services.mozilla.com/D103071
This commit is contained in:
parent
fd5fcc2c87
commit
62eb49693e
@ -954,6 +954,8 @@ pub struct Capabilities {
|
||||
pub supports_multisampling: bool,
|
||||
/// Whether the function `glCopyImageSubData` is available.
|
||||
pub supports_copy_image_sub_data: bool,
|
||||
/// Whether the RGBAF32 textures can be bound to framebuffers.
|
||||
pub supports_color_buffer_float: bool,
|
||||
/// Whether the device supports persistently mapped buffers, via glBufferStorage.
|
||||
pub supports_buffer_storage: bool,
|
||||
/// Whether we are able to use `glBlitFramebuffers` with the draw fbo
|
||||
@ -1540,6 +1542,11 @@ impl Device {
|
||||
supports_extension(&extensions, "GL_ARB_copy_image")
|
||||
};
|
||||
|
||||
let supports_color_buffer_float = match gl.get_type() {
|
||||
gl::GlType::Gl => true,
|
||||
gl::GlType::Gles => supports_extension(&extensions, "GL_EXT_color_buffer_float"),
|
||||
};
|
||||
|
||||
let is_adreno = renderer_name.starts_with("Adreno");
|
||||
|
||||
// There appears to be a driver bug on older versions of the Adreno
|
||||
@ -1652,6 +1659,7 @@ impl Device {
|
||||
capabilities: Capabilities {
|
||||
supports_multisampling: false, //TODO
|
||||
supports_copy_image_sub_data,
|
||||
supports_color_buffer_float,
|
||||
supports_buffer_storage,
|
||||
supports_blit_to_texture_array,
|
||||
supports_advanced_blend_equation,
|
||||
|
@ -91,8 +91,7 @@ pub struct GpuCacheTexture {
|
||||
}
|
||||
|
||||
impl GpuCacheTexture {
|
||||
/// Ensures that we have an appropriately-sized texture. Returns true if a
|
||||
/// new texture was created.
|
||||
/// Ensures that we have an appropriately-sized texture.
|
||||
fn ensure_texture(&mut self, device: &mut Device, height: i32) {
|
||||
// If we already have a texture that works, we're done.
|
||||
if self.texture.as_ref().map_or(false, |t| t.get_dimensions().height >= height) {
|
||||
@ -109,17 +108,20 @@ impl GpuCacheTexture {
|
||||
// Create the new texture.
|
||||
assert!(height >= 2, "Height is too small for ANGLE");
|
||||
let new_size = DeviceIntSize::new(super::MAX_VERTEX_TEXTURE_WIDTH as _, height);
|
||||
// If glCopyImageSubData is supported, this texture doesn't need
|
||||
// to be a render target. This prevents GL errors due to framebuffer
|
||||
// incompleteness on devices that don't support RGBAF32 render targets.
|
||||
// TODO(gw): We still need a proper solution for the subset of devices
|
||||
// that don't support glCopyImageSubData *OR* rendering to a
|
||||
// RGBAF32 render target. These devices will currently fail
|
||||
// to resize the GPU cache texture.
|
||||
// GpuCacheBus::Scatter always requires the texture to be a render target. For
|
||||
// GpuCacheBus::PixelBuffer, we only create the texture with a render target if
|
||||
// RGBAF32 render targets are actually supported, and only if glCopyImageSubData
|
||||
// is not. glCopyImageSubData does not require a render target to copy the texture
|
||||
// data, and if neither RGBAF32 render targets nor glCopyImageSubData is supported,
|
||||
// we simply re-upload the entire contents rather than copying upon resize.
|
||||
let supports_copy_image_sub_data = device.get_capabilities().supports_copy_image_sub_data;
|
||||
let rt_info = match self.bus {
|
||||
GpuCacheBus::PixelBuffer { .. } if supports_copy_image_sub_data => None,
|
||||
_ => Some(RenderTargetInfo { has_depth: false }),
|
||||
let supports_color_buffer_float = device.get_capabilities().supports_color_buffer_float;
|
||||
let rt_info = if matches!(self.bus, GpuCacheBus::PixelBuffer { .. })
|
||||
&& (supports_copy_image_sub_data || !supports_color_buffer_float)
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(RenderTargetInfo { has_depth: false })
|
||||
};
|
||||
let mut texture = device.create_texture(
|
||||
api::ImageBufferKind::Texture2D,
|
||||
@ -133,7 +135,21 @@ impl GpuCacheTexture {
|
||||
|
||||
// Copy the contents of the previous texture, if applicable.
|
||||
if let Some(blit_source) = blit_source {
|
||||
device.copy_entire_texture(&mut texture, &blit_source);
|
||||
if !supports_copy_image_sub_data && !supports_color_buffer_float {
|
||||
// Cannot copy texture, so must re-upload everything.
|
||||
match self.bus {
|
||||
GpuCacheBus::PixelBuffer { ref mut rows } => {
|
||||
for row in rows {
|
||||
row.add_dirty(0, super::MAX_VERTEX_TEXTURE_WIDTH);
|
||||
}
|
||||
}
|
||||
GpuCacheBus::Scatter { .. } => {
|
||||
panic!("Texture must be copyable to use scatter GPU cache bus method");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
device.copy_entire_texture(&mut texture, &blit_source);
|
||||
}
|
||||
device.delete_texture(blit_source);
|
||||
}
|
||||
|
||||
@ -144,6 +160,10 @@ impl GpuCacheTexture {
|
||||
use super::desc::GPU_CACHE_UPDATE;
|
||||
|
||||
let bus = if use_scatter {
|
||||
assert!(
|
||||
device.get_capabilities().supports_color_buffer_float,
|
||||
"GpuCache scatter method requires EXT_color_buffer_float",
|
||||
);
|
||||
let program = device.create_program_linked(
|
||||
"gpu_cache_update",
|
||||
&[],
|
||||
|
@ -1059,11 +1059,7 @@ impl Renderer {
|
||||
// On other GL platforms, like macOS or Android, creating many PBOs is very inefficient.
|
||||
// This is what happens in GPU cache updates in PBO path. Instead, we switch everything
|
||||
// except software GL to use the GPU scattered updates.
|
||||
let supports_scatter = match gl_type {
|
||||
gl::GlType::Gl => true,
|
||||
gl::GlType::Gles => device.supports_extension("GL_EXT_color_buffer_float"),
|
||||
};
|
||||
|
||||
let supports_scatter = device.get_capabilities().supports_color_buffer_float;
|
||||
let gpu_cache_texture = gpu_cache::GpuCacheTexture::new(
|
||||
&mut device,
|
||||
supports_scatter && !is_software,
|
||||
|
Loading…
Reference in New Issue
Block a user