From 2421de6616ddbc4b215aa911fb6a96be84b49596 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 8 May 2020 12:16:31 -0700 Subject: [PATCH] Enable compute shader by default if the OpenGL version is high enough. --- c/src/lib.rs | 2 +- demo/common/src/lib.rs | 16 ++++++++-------- demo/common/src/renderer.rs | 2 +- gl/src/lib.rs | 17 ++++++++++++----- gpu/src/lib.rs | 9 +++++++++ metal/src/lib.rs | 14 ++++++++++---- renderer/src/gpu/options.rs | 2 +- renderer/src/gpu/shaders.rs | 15 +++++++++------ webgl/src/lib.rs | 16 +++++++++++----- 9 files changed, 62 insertions(+), 31 deletions(-) diff --git a/c/src/lib.rs b/c/src/lib.rs index ecf4f6c7..ce322344 100644 --- a/c/src/lib.rs +++ b/c/src/lib.rs @@ -803,7 +803,7 @@ impl PFRendererOptions { None }, // TODO(pcwalton): Expose this in the C API. - use_compute: false, + no_compute: false, } } } diff --git a/demo/common/src/lib.rs b/demo/common/src/lib.rs index 3f1a24a0..0f27a5c5 100644 --- a/demo/common/src/lib.rs +++ b/demo/common/src/lib.rs @@ -137,7 +137,7 @@ impl DemoApp where W: Window { let mut ui_model = DemoUIModel::new(&options); let render_options = RendererOptions { background_color: None, - use_compute: options.compute, + no_compute: options.no_compute, }; let filter = build_filter(&ui_model); @@ -625,7 +625,7 @@ pub struct Options { pub ui: UIVisibility, pub background_color: BackgroundColor, pub high_performance_gpu: bool, - pub compute: bool, + pub no_compute: bool, hidden_field_for_future_proofing: (), } @@ -638,7 +638,7 @@ impl Default for Options { ui: UIVisibility::All, background_color: BackgroundColor::Light, high_performance_gpu: false, - compute: false, + no_compute: false, hidden_field_for_future_proofing: (), } } @@ -692,10 +692,10 @@ impl Options { .help("Use the high-performance (discrete) GPU, if available") ) .arg( - Arg::with_name("compute") + Arg::with_name("no-compute") .short("c") - .long("compute") - .help("Use compute shaders for certain tasks, if available") + .long("no-compute") + .help("Never use compute shaders") ) .arg( Arg::with_name("INPUT") @@ -734,8 +734,8 @@ impl Options { self.high_performance_gpu = true; } - if matches.is_present("compute") { - self.compute = true; + if matches.is_present("no-compute") { + self.no_compute = true; } if let Some(path) = matches.value_of("INPUT") { diff --git a/demo/common/src/renderer.rs b/demo/common/src/renderer.rs index a142cd99..05a29575 100644 --- a/demo/common/src/renderer.rs +++ b/demo/common/src/renderer.rs @@ -91,7 +91,7 @@ impl DemoApp where W: Window { }; self.renderer.set_options(RendererOptions { background_color: clear_color, - use_compute: self.options.compute, + no_compute: self.options.no_compute, }); scene_count diff --git a/gl/src/lib.rs b/gl/src/lib.rs index 232e0ccc..dabfec0c 100644 --- a/gl/src/lib.rs +++ b/gl/src/lib.rs @@ -19,11 +19,11 @@ use half::f16; use pathfinder_geometry::rect::RectI; use pathfinder_geometry::vector::Vector2I; use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, BufferUploadMode, ClearOps}; -use pathfinder_gpu::{ComputeDimensions, ComputeState, DepthFunc, Device, ImageAccess}; -use pathfinder_gpu::{ImageBinding, Primitive, ProgramKind, RenderOptions, RenderState}; -use pathfinder_gpu::{RenderTarget, ShaderKind, StencilFunc, TextureData, TextureDataRef}; -use pathfinder_gpu::{TextureFormat, TextureSamplingFlags, UniformData, VertexAttrClass}; -use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType}; +use pathfinder_gpu::{ComputeDimensions, ComputeState, DepthFunc, Device, FeatureLevel}; +use pathfinder_gpu::{ImageAccess, ImageBinding, Primitive, ProgramKind, RenderOptions}; +use pathfinder_gpu::{RenderState, RenderTarget, ShaderKind, StencilFunc, TextureData}; +use pathfinder_gpu::{TextureDataRef, TextureFormat, TextureSamplingFlags, UniformData}; +use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType}; use pathfinder_resources::ResourceLoader; use pathfinder_simd::default::F32x4; use std::ffi::CString; @@ -276,6 +276,13 @@ impl Device for GLDevice { type VertexArray = GLVertexArray; type VertexAttr = GLVertexAttr; + fn feature_level(&self) -> FeatureLevel { + match self.version { + GLVersion::GL3 | GLVersion::GLES3 => FeatureLevel::D3D10, + GLVersion::GL4 => FeatureLevel::D3D11, + } + } + fn create_texture(&self, format: TextureFormat, size: Vector2I) -> GLTexture { let mut texture = GLTexture { gl_texture: 0, size, format }; unsafe { diff --git a/gpu/src/lib.rs b/gpu/src/lib.rs index bc578620..50a7116f 100644 --- a/gpu/src/lib.rs +++ b/gpu/src/lib.rs @@ -38,6 +38,7 @@ pub trait Device: Sized { type VertexArray; type VertexAttr; + fn feature_level(&self) -> FeatureLevel; fn create_texture(&self, format: TextureFormat, size: Vector2I) -> Self::Texture; fn create_texture_from_data(&self, format: TextureFormat, size: Vector2I, data: TextureDataRef) -> Self::Texture; @@ -157,6 +158,14 @@ pub trait Device: Sized { } } +/// These are rough analogues to D3D versions; don't expect them to represent exactly the feature +/// set of the versions. +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum FeatureLevel { + D3D10, + D3D11, +} + #[derive(Clone, Copy, Debug, PartialEq)] pub enum TextureFormat { R8, diff --git a/metal/src/lib.rs b/metal/src/lib.rs index bbf14262..6e85722b 100644 --- a/metal/src/lib.rs +++ b/metal/src/lib.rs @@ -47,10 +47,11 @@ use objc::runtime::{Class, Object}; use pathfinder_geometry::rect::RectI; use pathfinder_geometry::vector::{Vector2I, vec2i}; use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, BufferUploadMode}; -use pathfinder_gpu::{ComputeDimensions, ComputeState, DepthFunc, Device, ImageAccess, Primitive}; -use pathfinder_gpu::{ProgramKind, RenderState, RenderTarget, ShaderKind, StencilFunc, TextureData}; -use pathfinder_gpu::{TextureDataRef, TextureFormat, TextureSamplingFlags, UniformData}; -use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType}; +use pathfinder_gpu::{ComputeDimensions, ComputeState, DepthFunc, Device, FeatureLevel}; +use pathfinder_gpu::{ImageAccess, Primitive, ProgramKind, RenderState, RenderTarget, ShaderKind}; +use pathfinder_gpu::{StencilFunc, TextureData, TextureDataRef, TextureFormat}; +use pathfinder_gpu::{TextureSamplingFlags, UniformData, VertexAttrClass}; +use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType}; use pathfinder_resources::ResourceLoader; use pathfinder_simd::default::{F32x2, F32x4, I32x2}; use std::cell::{Cell, RefCell}; @@ -272,6 +273,11 @@ impl Device for MetalDevice { type VertexArray = MetalVertexArray; type VertexAttr = VertexAttribute; + #[inline] + fn feature_level(&self) -> FeatureLevel { + FeatureLevel::D3D11 + } + // TODO: Add texture usage hint. fn create_texture(&self, format: TextureFormat, size: Vector2I) -> MetalTexture { let descriptor = TextureDescriptor::new(); diff --git a/renderer/src/gpu/options.rs b/renderer/src/gpu/options.rs index e34e61ec..435a6317 100644 --- a/renderer/src/gpu/options.rs +++ b/renderer/src/gpu/options.rs @@ -17,7 +17,7 @@ use pathfinder_gpu::Device; #[derive(Default)] pub struct RendererOptions { pub background_color: Option, - pub use_compute: bool, + pub no_compute: bool, } #[derive(Clone)] diff --git a/renderer/src/gpu/shaders.rs b/renderer/src/gpu/shaders.rs index 033fbd01..06f419d1 100644 --- a/renderer/src/gpu/shaders.rs +++ b/renderer/src/gpu/shaders.rs @@ -11,8 +11,8 @@ use crate::gpu::options::RendererOptions; use crate::gpu::renderer::{MASK_TILES_ACROSS, MASK_TILES_DOWN}; use crate::tiles::{TILE_HEIGHT, TILE_WIDTH}; -use pathfinder_gpu::{BufferTarget, BufferUploadMode, ComputeDimensions, Device, VertexAttrClass}; -use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType}; +use pathfinder_gpu::{BufferTarget, BufferUploadMode, ComputeDimensions, Device, FeatureLevel}; +use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType}; use pathfinder_resources::ResourceLoader; // TODO(pcwalton): Replace with `mem::size_of` calls? @@ -391,10 +391,13 @@ pub enum FillProgram where D: Device { impl FillProgram where D: Device { pub fn new(device: &D, resources: &dyn ResourceLoader, options: &RendererOptions) -> FillProgram { - if options.use_compute { - FillProgram::Compute(FillComputeProgram::new(device, resources)) - } else { - FillProgram::Raster(FillRasterProgram::new(device, resources)) + match (options.no_compute, device.feature_level()) { + (false, FeatureLevel::D3D11) => { + FillProgram::Compute(FillComputeProgram::new(device, resources)) + } + (_, FeatureLevel::D3D10) | (true, _) => { + FillProgram::Raster(FillRasterProgram::new(device, resources)) + } } } } diff --git a/webgl/src/lib.rs b/webgl/src/lib.rs index 37c1e9dc..ed3ddf59 100644 --- a/webgl/src/lib.rs +++ b/webgl/src/lib.rs @@ -15,11 +15,12 @@ extern crate log; use pathfinder_geometry::rect::RectI; use pathfinder_geometry::vector::Vector2I; -use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, RenderTarget}; -use pathfinder_gpu::{BufferUploadMode, ClearOps, ComputeDimensions, ComputeState, DepthFunc, Device, Primitive, ProgramKind}; -use pathfinder_gpu::{RenderOptions, RenderState, ShaderKind, StencilFunc, TextureData}; -use pathfinder_gpu::{TextureDataRef, TextureFormat, TextureSamplingFlags, UniformData}; -use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType}; +use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, BufferUploadMode, ClearOps}; +use pathfinder_gpu::{ComputeDimensions, ComputeState, DepthFunc, Device, FeatureLevel, Primitive}; +use pathfinder_gpu::{ProgramKind, RenderOptions, RenderState, RenderTarget, ShaderKind}; +use pathfinder_gpu::{StencilFunc, TextureData, TextureDataRef, TextureFormat}; +use pathfinder_gpu::{TextureSamplingFlags, UniformData, VertexAttrClass}; +use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType}; use pathfinder_resources::ResourceLoader; use std::mem; use std::str; @@ -424,6 +425,11 @@ impl Device for WebGlDevice { type VertexArray = WebGlVertexArray; type VertexAttr = WebGlVertexAttr; + #[inline] + fn feature_level(&self) -> FeatureLevel { + FeatureLevel::D3D10 + } + fn create_texture(&self, format: TextureFormat, size: Vector2I) -> WebGlTexture { let texture = self.context.create_texture().unwrap(); let texture = WebGlTexture {