Split shaders out into a separate module.

This commit is contained in:
Patrick Walton 2020-02-14 11:50:34 -08:00
parent 90445bac7e
commit 84ffc3151e
6 changed files with 552 additions and 523 deletions

View File

@ -173,9 +173,11 @@ impl CanvasRenderingContext2D {
let mut stroke_style = self.current_state.resolve_stroke_style();
// the smaller scale is relevant here, as we multiply by it and want to ensure it is always bigger than HAIRLINE_STROKE_WIDTH
let transform_scale = f32::min(self.current_state.transform.m11(), self.current_state.transform.m22());
// avoid the division in the normal case of sufficient thickness
// The smaller scale is relevant here, as we multiply by it and want to ensure it is always
// bigger than `HAIRLINE_STROKE_WIDTH`.
let transform_scale = f32::min(self.current_state.transform.m11(),
self.current_state.transform.m22());
// Avoid the division in the normal case of sufficient thickness.
if stroke_style.line_width * transform_scale < HAIRLINE_STROKE_WIDTH {
stroke_style.line_width = HAIRLINE_STROKE_WIDTH / transform_scale;
}

View File

@ -81,6 +81,9 @@ fn export_pdf<W: Write>(scene: &Scene, writer: &mut W) -> io::Result<()> {
Paint::Gradient(_) => {
// TODO(pcwalton): Gradients.
}
Paint::Pattern(_) => {
// TODO(pcwalton): Patterns.
}
}
for contour in outline.contours() {
@ -184,6 +187,9 @@ fn export_ps<W: Write>(scene: &Scene, writer: &mut W) -> io::Result<()> {
Paint::Gradient(_) => {
// TODO(pcwalton): Gradients.
}
Paint::Pattern(_) => {
// TODO(pcwalton): Patterns.
}
}
writeln!(writer, "fill")?;

View File

@ -13,3 +13,5 @@
pub mod debug;
pub mod options;
pub mod renderer;
pub(crate) mod shaders;

View File

@ -1,6 +1,6 @@
// pathfinder/renderer/src/gpu/renderer.rs
//
// Copyright © 2019 The Pathfinder Project Developers.
// Copyright © 2020 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
@ -10,6 +10,10 @@
use crate::gpu::debug::DebugUIPresenter;
use crate::gpu::options::{DestFramebuffer, RendererOptions};
use crate::gpu::shaders::{FillProgram, AlphaTileProgram, AlphaTileVertexArray, FillVertexArray};
use crate::gpu::shaders::{MAX_FILLS_PER_BATCH, PostprocessProgram, PostprocessVertexArray};
use crate::gpu::shaders::{ReprojectionProgram, ReprojectionVertexArray, SolidTileProgram};
use crate::gpu::shaders::{SolidTileVertexArray, StencilProgram, StencilVertexArray};
use crate::gpu_data::{AlphaTile, FillBatchPrimitive, PaintData, RenderCommand, SolidTileVertex};
use crate::post::DefringingKernel;
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
@ -20,8 +24,8 @@ use pathfinder_geometry::transform3d::Transform4F;
use pathfinder_gpu::resources::ResourceLoader;
use pathfinder_gpu::{BlendFunc, BlendState, BufferData, BufferTarget, BufferUploadMode, ClearOps};
use pathfinder_gpu::{DepthFunc, DepthState, Device, Primitive, RenderOptions, RenderState};
use pathfinder_gpu::{RenderTarget, StencilFunc, StencilState, TextureDataRef, TextureFormat};
use pathfinder_gpu::{UniformData, VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
use pathfinder_gpu::{RenderTarget, StencilFunc, StencilState, TextureDataRef};
use pathfinder_gpu::{TextureFormat, UniformData};
use pathfinder_simd::default::{F32x2, F32x4};
use std::cmp;
use std::collections::VecDeque;
@ -40,13 +44,6 @@ pub(crate) const MASK_TILES_DOWN: u32 = 256;
const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * MASK_TILES_ACROSS as i32;
const MASK_FRAMEBUFFER_HEIGHT: i32 = TILE_HEIGHT as i32 * MASK_TILES_DOWN as i32;
// TODO(pcwalton): Replace with `mem::size_of` calls?
const FILL_INSTANCE_SIZE: usize = 8;
const SOLID_TILE_VERTEX_SIZE: usize = 12;
const MASK_TILE_VERTEX_SIZE: usize = 16;
const MAX_FILLS_PER_BATCH: usize = 0x4000;
pub struct Renderer<D>
where
D: Device,
@ -836,8 +833,8 @@ where
}
fn mask_viewport(&self) -> RectI {
let texture = self.device.framebuffer_texture(&self.mask_framebuffer);
RectI::new(Vector2I::default(), self.device.texture_size(texture))
RectI::new(Vector2I::default(),
Vector2I::new(MASK_FRAMEBUFFER_WIDTH, MASK_FRAMEBUFFER_HEIGHT))
}
fn allocate_timer_query(&mut self) -> D::TimerQuery {
@ -860,512 +857,6 @@ where
}
}
struct FillVertexArray<D>
where
D: Device,
{
vertex_array: D::VertexArray,
vertex_buffer: D::Buffer,
}
impl<D> FillVertexArray<D>
where
D: Device,
{
fn new(
device: &D,
fill_program: &FillProgram<D>,
quad_vertex_positions_buffer: &D::Buffer,
quad_vertex_indices_buffer: &D::Buffer,
) -> FillVertexArray<D> {
let vertex_array = device.create_vertex_array();
let vertex_buffer = device.create_buffer();
let vertex_buffer_data: BufferData<FillBatchPrimitive> =
BufferData::Uninitialized(MAX_FILLS_PER_BATCH);
device.allocate_buffer(
&vertex_buffer,
vertex_buffer_data,
BufferTarget::Vertex,
BufferUploadMode::Dynamic,
);
let tess_coord_attr = device.get_vertex_attr(&fill_program.program, "TessCoord").unwrap();
let from_px_attr = device.get_vertex_attr(&fill_program.program, "FromPx").unwrap();
let to_px_attr = device.get_vertex_attr(&fill_program.program, "ToPx").unwrap();
let from_subpx_attr = device.get_vertex_attr(&fill_program.program, "FromSubpx").unwrap();
let to_subpx_attr = device.get_vertex_attr(&fill_program.program, "ToSubpx").unwrap();
let tile_index_attr = device.get_vertex_attr(&fill_program.program, "TileIndex").unwrap();
device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &tess_coord_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::U16,
stride: 4,
offset: 0,
divisor: 0,
buffer_index: 0,
});
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &from_px_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 0,
divisor: 1,
buffer_index: 1,
});
device.configure_vertex_attr(&vertex_array, &to_px_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 1,
divisor: 1,
buffer_index: 1,
});
device.configure_vertex_attr(&vertex_array, &from_subpx_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 2,
divisor: 1,
buffer_index: 1,
});
device.configure_vertex_attr(&vertex_array, &to_subpx_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 4,
divisor: 1,
buffer_index: 1,
});
device.configure_vertex_attr(&vertex_array, &tile_index_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::U16,
stride: FILL_INSTANCE_SIZE,
offset: 6,
divisor: 1,
buffer_index: 1,
});
device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index);
FillVertexArray { vertex_array, vertex_buffer }
}
}
struct AlphaTileVertexArray<D>
where
D: Device,
{
vertex_array: D::VertexArray,
vertex_buffer: D::Buffer,
}
impl<D> AlphaTileVertexArray<D>
where
D: Device,
{
fn new(
device: &D,
alpha_tile_program: &AlphaTileProgram<D>,
quads_vertex_indices_buffer: &D::Buffer,
) -> AlphaTileVertexArray<D> {
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
let tile_position_attr =
device.get_vertex_attr(&alpha_tile_program.program, "TilePosition").unwrap();
let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
"ColorTexCoord").unwrap();
let mask_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
"MaskTexCoord").unwrap();
let backdrop_attr = device.get_vertex_attr(&alpha_tile_program.program, "Backdrop")
.unwrap();
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
stride: MASK_TILE_VERTEX_SIZE,
offset: 0,
divisor: 0,
buffer_index: 0,
});
device.configure_vertex_attr(&vertex_array, &color_tex_coord_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U16,
stride: MASK_TILE_VERTEX_SIZE,
offset: 4,
divisor: 0,
buffer_index: 0,
});
device.configure_vertex_attr(&vertex_array, &mask_tex_coord_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U16,
stride: MASK_TILE_VERTEX_SIZE,
offset: 8,
divisor: 0,
buffer_index: 0,
});
device.configure_vertex_attr(&vertex_array, &backdrop_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
stride: MASK_TILE_VERTEX_SIZE,
offset: 12,
divisor: 0,
buffer_index: 0,
});
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
AlphaTileVertexArray { vertex_array, vertex_buffer }
}
}
struct SolidTileVertexArray<D>
where
D: Device,
{
vertex_array: D::VertexArray,
vertex_buffer: D::Buffer,
}
impl<D> SolidTileVertexArray<D>
where
D: Device,
{
fn new(
device: &D,
solid_tile_program: &SolidTileProgram<D>,
quads_vertex_indices_buffer: &D::Buffer,
) -> SolidTileVertexArray<D> {
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
let tile_position_attr =
device.get_vertex_attr(&solid_tile_program.program, "TilePosition").unwrap();
let color_tex_coord_attr =
device.get_vertex_attr(&solid_tile_program.program, "ColorTexCoord").unwrap();
// NB: The tile origin must be of type short, not unsigned short, to work around a macOS
// Radeon driver bug.
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
stride: SOLID_TILE_VERTEX_SIZE,
offset: 0,
divisor: 0,
buffer_index: 0,
});
device.configure_vertex_attr(&vertex_array,
&color_tex_coord_attr,
&VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U16,
stride: SOLID_TILE_VERTEX_SIZE,
offset: 4,
divisor: 0,
buffer_index: 0,
});
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
SolidTileVertexArray { vertex_array, vertex_buffer }
}
}
struct FillProgram<D>
where
D: Device,
{
program: D::Program,
framebuffer_size_uniform: D::Uniform,
tile_size_uniform: D::Uniform,
area_lut_uniform: D::Uniform,
}
impl<D> FillProgram<D>
where
D: Device,
{
fn new(device: &D, resources: &dyn ResourceLoader) -> FillProgram<D> {
let program = device.create_program(resources, "fill");
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
let tile_size_uniform = device.get_uniform(&program, "TileSize");
let area_lut_uniform = device.get_uniform(&program, "AreaLUT");
FillProgram {
program,
framebuffer_size_uniform,
tile_size_uniform,
area_lut_uniform,
}
}
}
struct SolidTileProgram<D> where D: Device {
program: D::Program,
transform_uniform: D::Uniform,
tile_size_uniform: D::Uniform,
paint_texture_uniform: D::Uniform,
paint_texture_size_uniform: D::Uniform,
}
impl<D> SolidTileProgram<D> where D: Device {
fn new(device: &D, resources: &dyn ResourceLoader) -> SolidTileProgram<D> {
let program = device.create_program(resources, "tile_solid");
let transform_uniform = device.get_uniform(&program, "Transform");
let tile_size_uniform = device.get_uniform(&program, "TileSize");
let paint_texture_uniform = device.get_uniform(&program, "PaintTexture");
let paint_texture_size_uniform = device.get_uniform(&program, "PaintTextureSize");
SolidTileProgram {
program,
transform_uniform,
tile_size_uniform,
paint_texture_uniform,
paint_texture_size_uniform,
}
}
}
struct AlphaTileProgram<D> where D: Device {
program: D::Program,
transform_uniform: D::Uniform,
tile_size_uniform: D::Uniform,
stencil_texture_uniform: D::Uniform,
stencil_texture_size_uniform: D::Uniform,
paint_texture_uniform: D::Uniform,
paint_texture_size_uniform: D::Uniform,
}
impl<D> AlphaTileProgram<D> where D: Device {
fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileProgram<D> {
let program = device.create_program(resources, "tile_alpha");
let transform_uniform = device.get_uniform(&program, "Transform");
let tile_size_uniform = device.get_uniform(&program, "TileSize");
let stencil_texture_uniform = device.get_uniform(&program, "StencilTexture");
let stencil_texture_size_uniform = device.get_uniform(&program, "StencilTextureSize");
let paint_texture_uniform = device.get_uniform(&program, "PaintTexture");
let paint_texture_size_uniform = device.get_uniform(&program, "PaintTextureSize");
AlphaTileProgram {
program,
transform_uniform,
tile_size_uniform,
stencil_texture_uniform,
stencil_texture_size_uniform,
paint_texture_uniform,
paint_texture_size_uniform,
}
}
}
struct PostprocessProgram<D>
where
D: Device,
{
program: D::Program,
source_uniform: D::Uniform,
source_size_uniform: D::Uniform,
framebuffer_size_uniform: D::Uniform,
kernel_uniform: D::Uniform,
gamma_lut_uniform: D::Uniform,
gamma_correction_enabled_uniform: D::Uniform,
fg_color_uniform: D::Uniform,
bg_color_uniform: D::Uniform,
}
impl<D> PostprocessProgram<D>
where
D: Device,
{
fn new(device: &D, resources: &dyn ResourceLoader) -> PostprocessProgram<D> {
let program = device.create_program(resources, "post");
let source_uniform = device.get_uniform(&program, "Source");
let source_size_uniform = device.get_uniform(&program, "SourceSize");
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
let kernel_uniform = device.get_uniform(&program, "Kernel");
let gamma_lut_uniform = device.get_uniform(&program, "GammaLUT");
let gamma_correction_enabled_uniform = device.get_uniform(&program,
"GammaCorrectionEnabled");
let fg_color_uniform = device.get_uniform(&program, "FGColor");
let bg_color_uniform = device.get_uniform(&program, "BGColor");
PostprocessProgram {
program,
source_uniform,
source_size_uniform,
framebuffer_size_uniform,
kernel_uniform,
gamma_lut_uniform,
gamma_correction_enabled_uniform,
fg_color_uniform,
bg_color_uniform,
}
}
}
struct PostprocessVertexArray<D>
where
D: Device,
{
vertex_array: D::VertexArray,
}
impl<D> PostprocessVertexArray<D>
where
D: Device,
{
fn new(
device: &D,
postprocess_program: &PostprocessProgram<D>,
quad_vertex_positions_buffer: &D::Buffer,
quad_vertex_indices_buffer: &D::Buffer,
) -> PostprocessVertexArray<D> {
let vertex_array = device.create_vertex_array();
let position_attr = device.get_vertex_attr(&postprocess_program.program, "Position")
.unwrap();
device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
stride: 4,
offset: 0,
divisor: 0,
buffer_index: 0,
});
device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index);
PostprocessVertexArray { vertex_array }
}
}
struct StencilProgram<D>
where
D: Device,
{
program: D::Program,
}
impl<D> StencilProgram<D>
where
D: Device,
{
fn new(device: &D, resources: &dyn ResourceLoader) -> StencilProgram<D> {
let program = device.create_program(resources, "stencil");
StencilProgram { program }
}
}
struct StencilVertexArray<D>
where
D: Device,
{
vertex_array: D::VertexArray,
vertex_buffer: D::Buffer,
index_buffer: D::Buffer,
}
impl<D> StencilVertexArray<D>
where
D: Device,
{
fn new(device: &D, stencil_program: &StencilProgram<D>) -> StencilVertexArray<D> {
let vertex_array = device.create_vertex_array();
let (vertex_buffer, index_buffer) = (device.create_buffer(), device.create_buffer());
let position_attr = device.get_vertex_attr(&stencil_program.program, "Position").unwrap();
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor {
size: 3,
class: VertexAttrClass::Float,
attr_type: VertexAttrType::F32,
stride: 4 * 4,
offset: 0,
divisor: 0,
buffer_index: 0,
});
device.bind_buffer(&vertex_array, &index_buffer, BufferTarget::Index);
StencilVertexArray { vertex_array, vertex_buffer, index_buffer }
}
}
struct ReprojectionProgram<D>
where
D: Device,
{
program: D::Program,
old_transform_uniform: D::Uniform,
new_transform_uniform: D::Uniform,
texture_uniform: D::Uniform,
}
impl<D> ReprojectionProgram<D>
where
D: Device,
{
fn new(device: &D, resources: &dyn ResourceLoader) -> ReprojectionProgram<D> {
let program = device.create_program(resources, "reproject");
let old_transform_uniform = device.get_uniform(&program, "OldTransform");
let new_transform_uniform = device.get_uniform(&program, "NewTransform");
let texture_uniform = device.get_uniform(&program, "Texture");
ReprojectionProgram {
program,
old_transform_uniform,
new_transform_uniform,
texture_uniform,
}
}
}
struct ReprojectionVertexArray<D>
where
D: Device,
{
vertex_array: D::VertexArray,
}
impl<D> ReprojectionVertexArray<D>
where
D: Device,
{
fn new(
device: &D,
reprojection_program: &ReprojectionProgram<D>,
quad_vertex_positions_buffer: &D::Buffer,
quad_vertex_indices_buffer: &D::Buffer,
) -> ReprojectionVertexArray<D> {
let vertex_array = device.create_vertex_array();
let position_attr = device.get_vertex_attr(&reprojection_program.program, "Position")
.unwrap();
device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
stride: 4,
offset: 0,
divisor: 0,
buffer_index: 0,
});
device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index);
ReprojectionVertexArray { vertex_array }
}
}
#[derive(Clone, Copy, Default)]
pub struct PostprocessOptions {
pub fg_color: ColorF,
@ -1374,6 +865,8 @@ pub struct PostprocessOptions {
pub gamma_correction: bool,
}
// Render stats
#[derive(Clone, Copy, Debug, Default)]
pub struct RenderStats {
pub path_count: usize,

526
renderer/src/gpu/shaders.rs Normal file
View File

@ -0,0 +1,526 @@
// pathfinder/renderer/src/gpu/shaders.rs
//
// Copyright © 2020 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use crate::gpu_data::FillBatchPrimitive;
use pathfinder_gpu::{BufferData, BufferTarget, BufferUploadMode, Device, VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
use pathfinder_gpu::resources::ResourceLoader;
// TODO(pcwalton): Replace with `mem::size_of` calls?
const FILL_INSTANCE_SIZE: usize = 8;
const SOLID_TILE_VERTEX_SIZE: usize = 12;
const MASK_TILE_VERTEX_SIZE: usize = 16;
pub const MAX_FILLS_PER_BATCH: usize = 0x4000;
pub struct FillVertexArray<D>
where
D: Device,
{
pub vertex_array: D::VertexArray,
pub vertex_buffer: D::Buffer,
}
impl<D> FillVertexArray<D>
where
D: Device,
{
pub fn new(
device: &D,
fill_program: &FillProgram<D>,
quad_vertex_positions_buffer: &D::Buffer,
quad_vertex_indices_buffer: &D::Buffer,
) -> FillVertexArray<D> {
let vertex_array = device.create_vertex_array();
let vertex_buffer = device.create_buffer();
let vertex_buffer_data: BufferData<FillBatchPrimitive> =
BufferData::Uninitialized(MAX_FILLS_PER_BATCH);
device.allocate_buffer(
&vertex_buffer,
vertex_buffer_data,
BufferTarget::Vertex,
BufferUploadMode::Dynamic,
);
let tess_coord_attr = device.get_vertex_attr(&fill_program.program, "TessCoord").unwrap();
let from_px_attr = device.get_vertex_attr(&fill_program.program, "FromPx").unwrap();
let to_px_attr = device.get_vertex_attr(&fill_program.program, "ToPx").unwrap();
let from_subpx_attr = device.get_vertex_attr(&fill_program.program, "FromSubpx").unwrap();
let to_subpx_attr = device.get_vertex_attr(&fill_program.program, "ToSubpx").unwrap();
let tile_index_attr = device.get_vertex_attr(&fill_program.program, "TileIndex").unwrap();
device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &tess_coord_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::U16,
stride: 4,
offset: 0,
divisor: 0,
buffer_index: 0,
});
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &from_px_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 0,
divisor: 1,
buffer_index: 1,
});
device.configure_vertex_attr(&vertex_array, &to_px_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 1,
divisor: 1,
buffer_index: 1,
});
device.configure_vertex_attr(&vertex_array, &from_subpx_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 2,
divisor: 1,
buffer_index: 1,
});
device.configure_vertex_attr(&vertex_array, &to_subpx_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U8,
stride: FILL_INSTANCE_SIZE,
offset: 4,
divisor: 1,
buffer_index: 1,
});
device.configure_vertex_attr(&vertex_array, &tile_index_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::U16,
stride: FILL_INSTANCE_SIZE,
offset: 6,
divisor: 1,
buffer_index: 1,
});
device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index);
FillVertexArray { vertex_array, vertex_buffer }
}
}
pub struct AlphaTileVertexArray<D>
where
D: Device,
{
pub vertex_array: D::VertexArray,
pub vertex_buffer: D::Buffer,
}
impl<D> AlphaTileVertexArray<D>
where
D: Device,
{
pub fn new(
device: &D,
alpha_tile_program: &AlphaTileProgram<D>,
quads_vertex_indices_buffer: &D::Buffer,
) -> AlphaTileVertexArray<D> {
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
let tile_position_attr =
device.get_vertex_attr(&alpha_tile_program.program, "TilePosition").unwrap();
let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
"ColorTexCoord").unwrap();
let mask_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
"MaskTexCoord").unwrap();
let backdrop_attr = device.get_vertex_attr(&alpha_tile_program.program, "Backdrop")
.unwrap();
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
stride: MASK_TILE_VERTEX_SIZE,
offset: 0,
divisor: 0,
buffer_index: 0,
});
device.configure_vertex_attr(&vertex_array, &mask_tex_coord_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U16,
stride: MASK_TILE_VERTEX_SIZE,
offset: 4,
divisor: 0,
buffer_index: 0,
});
device.configure_vertex_attr(&vertex_array, &color_tex_coord_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U16,
stride: MASK_TILE_VERTEX_SIZE,
offset: 8,
divisor: 0,
buffer_index: 0,
});
device.configure_vertex_attr(&vertex_array, &backdrop_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
stride: MASK_TILE_VERTEX_SIZE,
offset: 12,
divisor: 0,
buffer_index: 0,
});
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
AlphaTileVertexArray { vertex_array, vertex_buffer }
}
}
pub struct SolidTileVertexArray<D>
where
D: Device,
{
pub vertex_array: D::VertexArray,
pub vertex_buffer: D::Buffer,
}
impl<D> SolidTileVertexArray<D>
where
D: Device,
{
pub fn new(
device: &D,
solid_tile_program: &SolidTileProgram<D>,
quads_vertex_indices_buffer: &D::Buffer,
) -> SolidTileVertexArray<D> {
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
let tile_position_attr =
device.get_vertex_attr(&solid_tile_program.program, "TilePosition").unwrap();
let color_tex_coord_attr =
device.get_vertex_attr(&solid_tile_program.program, "ColorTexCoord").unwrap();
// NB: The tile origin must be of type short, not unsigned short, to work around a macOS
// Radeon driver bug.
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
stride: SOLID_TILE_VERTEX_SIZE,
offset: 0,
divisor: 0,
buffer_index: 0,
});
device.configure_vertex_attr(&vertex_array,
&color_tex_coord_attr,
&VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U16,
stride: SOLID_TILE_VERTEX_SIZE,
offset: 4,
divisor: 0,
buffer_index: 0,
});
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
SolidTileVertexArray { vertex_array, vertex_buffer }
}
}
pub struct FillProgram<D>
where
D: Device,
{
pub program: D::Program,
pub framebuffer_size_uniform: D::Uniform,
pub tile_size_uniform: D::Uniform,
pub area_lut_uniform: D::Uniform,
}
impl<D> FillProgram<D>
where
D: Device,
{
pub fn new(device: &D, resources: &dyn ResourceLoader) -> FillProgram<D> {
let program = device.create_program(resources, "fill");
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
let tile_size_uniform = device.get_uniform(&program, "TileSize");
let area_lut_uniform = device.get_uniform(&program, "AreaLUT");
FillProgram {
program,
framebuffer_size_uniform,
tile_size_uniform,
area_lut_uniform,
}
}
}
pub struct SolidTileProgram<D> where D: Device {
pub program: D::Program,
pub transform_uniform: D::Uniform,
pub tile_size_uniform: D::Uniform,
pub paint_texture_uniform: D::Uniform,
pub paint_texture_size_uniform: D::Uniform,
}
impl<D> SolidTileProgram<D> where D: Device {
pub fn new(device: &D, resources: &dyn ResourceLoader) -> SolidTileProgram<D> {
let program = device.create_program(resources, "tile_solid");
let transform_uniform = device.get_uniform(&program, "Transform");
let tile_size_uniform = device.get_uniform(&program, "TileSize");
let paint_texture_uniform = device.get_uniform(&program, "PaintTexture");
let paint_texture_size_uniform = device.get_uniform(&program, "PaintTextureSize");
SolidTileProgram {
program,
transform_uniform,
tile_size_uniform,
paint_texture_uniform,
paint_texture_size_uniform,
}
}
}
pub struct AlphaTileProgram<D> where D: Device {
pub program: D::Program,
pub transform_uniform: D::Uniform,
pub tile_size_uniform: D::Uniform,
pub stencil_texture_uniform: D::Uniform,
pub stencil_texture_size_uniform: D::Uniform,
pub paint_texture_uniform: D::Uniform,
pub paint_texture_size_uniform: D::Uniform,
}
impl<D> AlphaTileProgram<D> where D: Device {
pub fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileProgram<D> {
let program = device.create_program(resources, "tile_alpha");
let transform_uniform = device.get_uniform(&program, "Transform");
let tile_size_uniform = device.get_uniform(&program, "TileSize");
let stencil_texture_uniform = device.get_uniform(&program, "StencilTexture");
let stencil_texture_size_uniform = device.get_uniform(&program, "StencilTextureSize");
let paint_texture_uniform = device.get_uniform(&program, "PaintTexture");
let paint_texture_size_uniform = device.get_uniform(&program, "PaintTextureSize");
AlphaTileProgram {
program,
transform_uniform,
tile_size_uniform,
stencil_texture_uniform,
stencil_texture_size_uniform,
paint_texture_uniform,
paint_texture_size_uniform,
}
}
}
pub struct PostprocessProgram<D>
where
D: Device,
{
pub program: D::Program,
pub source_uniform: D::Uniform,
pub source_size_uniform: D::Uniform,
pub framebuffer_size_uniform: D::Uniform,
pub kernel_uniform: D::Uniform,
pub gamma_lut_uniform: D::Uniform,
pub gamma_correction_enabled_uniform: D::Uniform,
pub fg_color_uniform: D::Uniform,
pub bg_color_uniform: D::Uniform,
}
impl<D> PostprocessProgram<D>
where
D: Device,
{
pub fn new(device: &D, resources: &dyn ResourceLoader) -> PostprocessProgram<D> {
let program = device.create_program(resources, "post");
let source_uniform = device.get_uniform(&program, "Source");
let source_size_uniform = device.get_uniform(&program, "SourceSize");
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
let kernel_uniform = device.get_uniform(&program, "Kernel");
let gamma_lut_uniform = device.get_uniform(&program, "GammaLUT");
let gamma_correction_enabled_uniform = device.get_uniform(&program,
"GammaCorrectionEnabled");
let fg_color_uniform = device.get_uniform(&program, "FGColor");
let bg_color_uniform = device.get_uniform(&program, "BGColor");
PostprocessProgram {
program,
source_uniform,
source_size_uniform,
framebuffer_size_uniform,
kernel_uniform,
gamma_lut_uniform,
gamma_correction_enabled_uniform,
fg_color_uniform,
bg_color_uniform,
}
}
}
pub struct PostprocessVertexArray<D>
where
D: Device,
{
pub vertex_array: D::VertexArray,
}
impl<D> PostprocessVertexArray<D>
where
D: Device,
{
pub fn new(
device: &D,
postprocess_program: &PostprocessProgram<D>,
quad_vertex_positions_buffer: &D::Buffer,
quad_vertex_indices_buffer: &D::Buffer,
) -> PostprocessVertexArray<D> {
let vertex_array = device.create_vertex_array();
let position_attr = device.get_vertex_attr(&postprocess_program.program, "Position")
.unwrap();
device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
stride: 4,
offset: 0,
divisor: 0,
buffer_index: 0,
});
device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index);
PostprocessVertexArray { vertex_array }
}
}
pub struct StencilProgram<D>
where
D: Device,
{
pub program: D::Program,
}
impl<D> StencilProgram<D>
where
D: Device,
{
pub fn new(device: &D, resources: &dyn ResourceLoader) -> StencilProgram<D> {
let program = device.create_program(resources, "stencil");
StencilProgram { program }
}
}
pub struct StencilVertexArray<D>
where
D: Device,
{
pub vertex_array: D::VertexArray,
pub vertex_buffer: D::Buffer,
pub index_buffer: D::Buffer,
}
impl<D> StencilVertexArray<D>
where
D: Device,
{
pub fn new(device: &D, stencil_program: &StencilProgram<D>) -> StencilVertexArray<D> {
let vertex_array = device.create_vertex_array();
let (vertex_buffer, index_buffer) = (device.create_buffer(), device.create_buffer());
let position_attr = device.get_vertex_attr(&stencil_program.program, "Position").unwrap();
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor {
size: 3,
class: VertexAttrClass::Float,
attr_type: VertexAttrType::F32,
stride: 4 * 4,
offset: 0,
divisor: 0,
buffer_index: 0,
});
device.bind_buffer(&vertex_array, &index_buffer, BufferTarget::Index);
StencilVertexArray { vertex_array, vertex_buffer, index_buffer }
}
}
pub struct ReprojectionProgram<D>
where
D: Device,
{
pub program: D::Program,
pub old_transform_uniform: D::Uniform,
pub new_transform_uniform: D::Uniform,
pub texture_uniform: D::Uniform,
}
impl<D> ReprojectionProgram<D>
where
D: Device,
{
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ReprojectionProgram<D> {
let program = device.create_program(resources, "reproject");
let old_transform_uniform = device.get_uniform(&program, "OldTransform");
let new_transform_uniform = device.get_uniform(&program, "NewTransform");
let texture_uniform = device.get_uniform(&program, "Texture");
ReprojectionProgram {
program,
old_transform_uniform,
new_transform_uniform,
texture_uniform,
}
}
}
pub struct ReprojectionVertexArray<D>
where
D: Device,
{
pub vertex_array: D::VertexArray,
}
impl<D> ReprojectionVertexArray<D>
where
D: Device,
{
pub fn new(
device: &D,
reprojection_program: &ReprojectionProgram<D>,
quad_vertex_positions_buffer: &D::Buffer,
quad_vertex_indices_buffer: &D::Buffer,
) -> ReprojectionVertexArray<D> {
let vertex_array = device.create_vertex_array();
let position_attr = device.get_vertex_attr(&reprojection_program.program, "Position")
.unwrap();
device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
stride: 4,
offset: 0,
divisor: 0,
buffer_index: 0,
});
device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index);
ReprojectionVertexArray { vertex_array }
}
}

View File

@ -93,10 +93,10 @@ pub struct AlphaTile {
pub struct AlphaTileVertex {
pub tile_x: i16,
pub tile_y: i16,
pub color_u: u16,
pub color_v: u16,
pub mask_u: u16,
pub mask_v: u16,
pub color_u: u16,
pub color_v: u16,
pub backdrop: i16,
pub object_index: u16,
}