mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 12:41:30 +11:00
Mostly working rendering
This exposes interfaces to render glyphs into a texture atlas. The main changes are: * Methods to plumb raw Metal GPU resources (device, texture, etc) into piet-gpu-hal objects. * A new glyph_render API specialized to rendering glyphs. This is basically the same as just painting to a canvas, but will allow better caching (and has more direct access to fonts, bypassing the Piet font type which is underdeveloped). * Ability to render to A8 target in addition to RGBA. WIP, there are some rough edges, not least of which is that the image format changes are only on mac and cause compile errors elsewhere.
This commit is contained in:
parent
833d993a4e
commit
0cf370f9c7
|
@ -16,7 +16,9 @@
|
||||||
|
|
||||||
//! The generic trait for backends to implement.
|
//! The generic trait for backends to implement.
|
||||||
|
|
||||||
use crate::{BindType, BufferUsage, Error, GpuInfo, ImageLayout, MapMode, SamplerParams};
|
use crate::{
|
||||||
|
BindType, BufferUsage, Error, GpuInfo, ImageFormat, ImageLayout, MapMode, SamplerParams,
|
||||||
|
};
|
||||||
|
|
||||||
pub trait Device: Sized {
|
pub trait Device: Sized {
|
||||||
type Buffer: 'static;
|
type Buffer: 'static;
|
||||||
|
@ -47,7 +49,12 @@ pub trait Device: Sized {
|
||||||
/// Maybe doesn't need result return?
|
/// Maybe doesn't need result return?
|
||||||
unsafe fn destroy_buffer(&self, buffer: &Self::Buffer) -> Result<(), Error>;
|
unsafe fn destroy_buffer(&self, buffer: &Self::Buffer) -> Result<(), Error>;
|
||||||
|
|
||||||
unsafe fn create_image2d(&self, width: u32, height: u32) -> Result<Self::Image, Error>;
|
unsafe fn create_image2d(
|
||||||
|
&self,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
format: ImageFormat,
|
||||||
|
) -> Result<Self::Image, Error>;
|
||||||
|
|
||||||
/// Destroy an image.
|
/// Destroy an image.
|
||||||
///
|
///
|
||||||
|
|
|
@ -13,7 +13,7 @@ use std::sync::{Arc, Mutex, Weak};
|
||||||
use bytemuck::Pod;
|
use bytemuck::Pod;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::{mux, BackendType, BufWrite, MapMode};
|
use crate::{mux, BackendType, BufWrite, ImageFormat, MapMode};
|
||||||
|
|
||||||
use crate::{BindType, BufferUsage, Error, GpuInfo, ImageLayout, SamplerParams};
|
use crate::{BindType, BufferUsage, Error, GpuInfo, ImageLayout, SamplerParams};
|
||||||
|
|
||||||
|
@ -312,8 +312,13 @@ impl Session {
|
||||||
///
|
///
|
||||||
/// Currently this creates only a 2D image in RGBA8 format, with usage
|
/// Currently this creates only a 2D image in RGBA8 format, with usage
|
||||||
/// so that it can be accessed by shaders and used for transfer.
|
/// so that it can be accessed by shaders and used for transfer.
|
||||||
pub unsafe fn create_image2d(&self, width: u32, height: u32) -> Result<Image, Error> {
|
pub unsafe fn create_image2d(
|
||||||
let image = self.0.device.create_image2d(width, height)?;
|
&self,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
format: ImageFormat,
|
||||||
|
) -> Result<Image, Error> {
|
||||||
|
let image = self.0.device.create_image2d(width, height, format)?;
|
||||||
Ok(Image(Arc::new(ImageInner {
|
Ok(Image(Arc::new(ImageInner {
|
||||||
image,
|
image,
|
||||||
session: Arc::downgrade(&self.0),
|
session: Arc::downgrade(&self.0),
|
||||||
|
|
|
@ -91,6 +91,15 @@ pub enum SamplerParams {
|
||||||
Linear,
|
Linear,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Image format.
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum ImageFormat {
|
||||||
|
// 8 bit grayscale / alpha
|
||||||
|
A8,
|
||||||
|
// 8 bit per pixel RGBA
|
||||||
|
Rgba8,
|
||||||
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
/// The intended usage for a buffer, specified on creation.
|
/// The intended usage for a buffer, specified on creation.
|
||||||
pub struct BufferUsage: u32 {
|
pub struct BufferUsage: u32 {
|
||||||
|
|
|
@ -30,7 +30,7 @@ use metal::{CGFloat, MTLFeatureSet};
|
||||||
|
|
||||||
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
|
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
|
||||||
|
|
||||||
use crate::{BufferUsage, Error, GpuInfo, MapMode, WorkgroupLimits};
|
use crate::{BufferUsage, Error, GpuInfo, ImageFormat, MapMode, WorkgroupLimits};
|
||||||
|
|
||||||
use util::*;
|
use util::*;
|
||||||
|
|
||||||
|
@ -279,14 +279,23 @@ impl crate::backend::Device for MtlDevice {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_image2d(&self, width: u32, height: u32) -> Result<Self::Image, Error> {
|
unsafe fn create_image2d(
|
||||||
|
&self,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
format: ImageFormat,
|
||||||
|
) -> Result<Self::Image, Error> {
|
||||||
let desc = metal::TextureDescriptor::new();
|
let desc = metal::TextureDescriptor::new();
|
||||||
desc.set_width(width as u64);
|
desc.set_width(width as u64);
|
||||||
desc.set_height(height as u64);
|
desc.set_height(height as u64);
|
||||||
// These are defaults so don't need to be explicitly set.
|
// These are defaults so don't need to be explicitly set.
|
||||||
//desc.set_depth(1);
|
//desc.set_depth(1);
|
||||||
//desc.set_mipmap_level_count(1);
|
//desc.set_mipmap_level_count(1);
|
||||||
//desc.set_pixel_format(metal::MTLPixelFormat::RGBA8Unorm);
|
let mtl_format = match format {
|
||||||
|
ImageFormat::A8 => metal::MTLPixelFormat::R8Unorm,
|
||||||
|
ImageFormat::Rgba8 => metal::MTLPixelFormat::RGBA8Unorm,
|
||||||
|
};
|
||||||
|
desc.set_pixel_format(mtl_format);
|
||||||
desc.set_usage(metal::MTLTextureUsage::ShaderRead | metal::MTLTextureUsage::ShaderWrite);
|
desc.set_usage(metal::MTLTextureUsage::ShaderRead | metal::MTLTextureUsage::ShaderWrite);
|
||||||
let texture = self.device.new_texture(&desc);
|
let texture = self.device.new_texture(&desc);
|
||||||
Ok(Image {
|
Ok(Image {
|
||||||
|
|
|
@ -35,6 +35,7 @@ use crate::backend::DescriptorSetBuilder as DescriptorSetBuilderTrait;
|
||||||
use crate::backend::Device as DeviceTrait;
|
use crate::backend::Device as DeviceTrait;
|
||||||
use crate::BackendType;
|
use crate::BackendType;
|
||||||
use crate::BindType;
|
use crate::BindType;
|
||||||
|
use crate::ImageFormat;
|
||||||
use crate::MapMode;
|
use crate::MapMode;
|
||||||
use crate::{BufferUsage, Error, GpuInfo, ImageLayout, InstanceFlags};
|
use crate::{BufferUsage, Error, GpuInfo, ImageLayout, InstanceFlags};
|
||||||
|
|
||||||
|
@ -264,11 +265,16 @@ impl Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn create_image2d(&self, width: u32, height: u32) -> Result<Image, Error> {
|
pub unsafe fn create_image2d(
|
||||||
|
&self,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
format: ImageFormat,
|
||||||
|
) -> Result<Image, Error> {
|
||||||
mux_match! { self;
|
mux_match! { self;
|
||||||
Device::Vk(d) => d.create_image2d(width, height).map(Image::Vk),
|
Device::Vk(d) => d.create_image2d(width, height, format).map(Image::Vk),
|
||||||
Device::Dx12(d) => d.create_image2d(width, height).map(Image::Dx12),
|
Device::Dx12(d) => d.create_image2d(width, height, format).map(Image::Dx12),
|
||||||
Device::Mtl(d) => d.create_image2d(width, height).map(Image::Mtl),
|
Device::Mtl(d) => d.create_image2d(width, height, format).map(Image::Mtl),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,12 @@ build gen/kernel4.hlsl: hlsl gen/kernel4.spv
|
||||||
build gen/kernel4.dxil: dxil gen/kernel4.hlsl
|
build gen/kernel4.dxil: dxil gen/kernel4.hlsl
|
||||||
build gen/kernel4.msl: msl gen/kernel4.spv
|
build gen/kernel4.msl: msl gen/kernel4.spv
|
||||||
|
|
||||||
|
build gen/kernel4_gray.spv: glsl kernel4.comp | ptcl.h setup.h
|
||||||
|
flags = -DGRAY
|
||||||
|
build gen/kernel4_gray.hlsl: hlsl gen/kernel4_gray.spv
|
||||||
|
build gen/kernel4_gray.dxil: dxil gen/kernel4_gray.hlsl
|
||||||
|
build gen/kernel4_gray.msl: msl gen/kernel4_gray.spv
|
||||||
|
|
||||||
# New element pipeline follows
|
# New element pipeline follows
|
||||||
|
|
||||||
build gen/transform_reduce.spv: glsl transform_reduce.comp | scene.h setup.h mem.h
|
build gen/transform_reduce.spv: glsl transform_reduce.comp | scene.h setup.h mem.h
|
||||||
|
|
BIN
piet-gpu/shader/gen/backdrop.dxil
generated
BIN
piet-gpu/shader/gen/backdrop.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/backdrop_lg.dxil
generated
BIN
piet-gpu/shader/gen/backdrop_lg.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/bbox_clear.dxil
generated
BIN
piet-gpu/shader/gen/bbox_clear.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/binning.dxil
generated
BIN
piet-gpu/shader/gen/binning.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/coarse.dxil
generated
BIN
piet-gpu/shader/gen/coarse.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/draw_leaf.dxil
generated
BIN
piet-gpu/shader/gen/draw_leaf.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/draw_reduce.dxil
generated
BIN
piet-gpu/shader/gen/draw_reduce.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/draw_root.dxil
generated
BIN
piet-gpu/shader/gen/draw_root.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/kernel4.dxil
generated
BIN
piet-gpu/shader/gen/kernel4.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/path_coarse.dxil
generated
BIN
piet-gpu/shader/gen/path_coarse.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/pathseg.dxil
generated
BIN
piet-gpu/shader/gen/pathseg.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/pathtag_reduce.dxil
generated
BIN
piet-gpu/shader/gen/pathtag_reduce.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/pathtag_root.dxil
generated
BIN
piet-gpu/shader/gen/pathtag_root.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/tile_alloc.dxil
generated
BIN
piet-gpu/shader/gen/tile_alloc.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/transform_leaf.dxil
generated
BIN
piet-gpu/shader/gen/transform_leaf.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/transform_reduce.dxil
generated
BIN
piet-gpu/shader/gen/transform_reduce.dxil
generated
Binary file not shown.
BIN
piet-gpu/shader/gen/transform_root.dxil
generated
BIN
piet-gpu/shader/gen/transform_root.dxil
generated
Binary file not shown.
|
@ -23,7 +23,11 @@ layout(set = 0, binding = 1) restrict readonly buffer ConfigBuf {
|
||||||
Config conf;
|
Config conf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef GRAY
|
||||||
|
layout(r8, set = 0, binding = 2) uniform restrict writeonly image2D image;
|
||||||
|
#else
|
||||||
layout(rgba8, set = 0, binding = 2) uniform restrict writeonly image2D image;
|
layout(rgba8, set = 0, binding = 2) uniform restrict writeonly image2D image;
|
||||||
|
#endif
|
||||||
|
|
||||||
layout(rgba8, set = 0, binding = 3) uniform restrict readonly image2D image_atlas;
|
layout(rgba8, set = 0, binding = 3) uniform restrict readonly image2D image_atlas;
|
||||||
|
|
||||||
|
@ -228,6 +232,12 @@ void main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint i = 0; i < CHUNK; i++) {
|
for (uint i = 0; i < CHUNK; i++) {
|
||||||
|
#ifdef GRAY
|
||||||
|
// Just store the alpha value; later we can specialize this kernel more to avoid
|
||||||
|
// computing unneeded RGB colors.
|
||||||
|
imageStore(image, ivec2(xy_uint + chunk_offset(i)), vec4(rgba[i].a));
|
||||||
|
#else
|
||||||
imageStore(image, ivec2(xy_uint + chunk_offset(i)), vec4(tosRGB(rgba[i].rgb), rgba[i].a));
|
imageStore(image, ivec2(xy_uint + chunk_offset(i)), vec4(tosRGB(rgba[i].rgb), rgba[i].a));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
|
|
||||||
//! An experimental API for glyph rendering.
|
//! An experimental API for glyph rendering.
|
||||||
|
|
||||||
use swash::{scale::ScaleContext, CacheKey, FontRef};
|
use piet::{kurbo::Affine, RenderContext};
|
||||||
|
use swash::{scale::ScaleContext, CacheKey, FontDataRef, FontRef};
|
||||||
|
|
||||||
use crate::{encoder::GlyphEncoder, PietGpuRenderContext};
|
use crate::{encoder::GlyphEncoder, PietGpuRenderContext};
|
||||||
|
|
||||||
|
@ -30,33 +31,56 @@ pub struct FontId(CacheKey);
|
||||||
|
|
||||||
impl GlyphRenderer {
|
impl GlyphRenderer {
|
||||||
pub fn new() -> GlyphRenderer {
|
pub fn new() -> GlyphRenderer {
|
||||||
|
let render_ctx = PietGpuRenderContext::new();
|
||||||
|
let scale_context = ScaleContext::new();
|
||||||
GlyphRenderer {
|
GlyphRenderer {
|
||||||
render_ctx: PietGpuRenderContext::new(),
|
render_ctx,
|
||||||
scale_context: ScaleContext::new(),
|
scale_context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn add_glyph(&mut self, font_data: &[u8], font_id: u64, glyph_id: u16) {
|
pub unsafe fn add_glyph(
|
||||||
|
&mut self,
|
||||||
|
font_data: &[u8],
|
||||||
|
font_id: u64,
|
||||||
|
glyph_id: u16,
|
||||||
|
transform: [f32; 6],
|
||||||
|
) {
|
||||||
// This transmute is dodgy because the definition in swash isn't repr(transparent).
|
// This transmute is dodgy because the definition in swash isn't repr(transparent).
|
||||||
// I think the best solution is to have a from_u64 method, but we'll work that out
|
// I think the best solution is to have a from_u64 method, but we'll work that out
|
||||||
// later.
|
// later.
|
||||||
let font_id = FontId(std::mem::transmute(font_id));
|
let font_id = FontId(std::mem::transmute(font_id));
|
||||||
let encoder = self.make_glyph(font_data, font_id, glyph_id);
|
let encoder = self.make_glyph(font_data, font_id, glyph_id);
|
||||||
|
const DEFAULT_UPEM: u16 = 2048;
|
||||||
|
let affine = Affine::new([
|
||||||
|
transform[0] as f64,
|
||||||
|
transform[1] as f64,
|
||||||
|
transform[2] as f64,
|
||||||
|
transform[3] as f64,
|
||||||
|
transform[4] as f64,
|
||||||
|
transform[5] as f64,
|
||||||
|
]) * Affine::scale(1.0 / DEFAULT_UPEM as f64);
|
||||||
|
self.render_ctx.transform(affine);
|
||||||
self.render_ctx.encode_glyph(&encoder);
|
self.render_ctx.encode_glyph(&encoder);
|
||||||
// TODO: don't fill glyph if RGBA
|
// TODO: don't fill glyph if RGBA
|
||||||
self.render_ctx.fill_glyph(0xff_ff_ff_ff);
|
self.render_ctx.fill_glyph(0xff_ff_ff_ff);
|
||||||
|
self.render_ctx.transform(affine.inverse());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.render_ctx = PietGpuRenderContext::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_glyph(&mut self, font_data: &[u8], font_id: FontId, glyph_id: u16) -> GlyphEncoder {
|
fn make_glyph(&mut self, font_data: &[u8], font_id: FontId, glyph_id: u16) -> GlyphEncoder {
|
||||||
let mut encoder = GlyphEncoder::default();
|
let mut encoder = GlyphEncoder::default();
|
||||||
let font_ref = FontRef {
|
let font_data = FontDataRef::new(font_data).expect("invalid font");
|
||||||
data: font_data,
|
let mut font_ref = font_data.get(0).expect("invalid font index");
|
||||||
offset: 0,
|
font_ref.key = font_id.0;
|
||||||
key: font_id.0,
|
|
||||||
};
|
|
||||||
let mut scaler = self.scale_context.builder(font_ref).size(2048.).build();
|
let mut scaler = self.scale_context.builder(font_ref).size(2048.).build();
|
||||||
if let Some(outline) = scaler.scale_outline(glyph_id) {
|
if let Some(outline) = scaler.scale_outline(glyph_id) {
|
||||||
crate::text::append_outline(&mut encoder, outline.verbs(), outline.points());
|
crate::text::append_outline(&mut encoder, outline.verbs(), outline.points());
|
||||||
|
} else {
|
||||||
|
println!("failed to scale");
|
||||||
}
|
}
|
||||||
encoder
|
encoder
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,18 @@ pub fn dump_k1_data(k1_buf: &[u32]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct RenderConfig {
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
format: PixelFormat,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should we just use the enum from piet-gpu-hal?
|
||||||
|
pub enum PixelFormat {
|
||||||
|
A8,
|
||||||
|
Rgba8,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Renderer {
|
pub struct Renderer {
|
||||||
// These sizes are aligned to tile boundaries, though at some point
|
// These sizes are aligned to tile boundaries, though at some point
|
||||||
// we'll want to have a good strategy for dealing with odd sizes.
|
// we'll want to have a good strategy for dealing with odd sizes.
|
||||||
|
@ -106,15 +118,41 @@ pub struct Renderer {
|
||||||
gradients: Image,
|
gradients: Image,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RenderConfig {
|
||||||
|
pub fn new(width: usize, height: usize) -> RenderConfig {
|
||||||
|
RenderConfig {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
format: PixelFormat::Rgba8,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pixel_format(mut self, format: PixelFormat) -> Self {
|
||||||
|
self.format = format;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
/// Create a new renderer.
|
|
||||||
pub unsafe fn new(
|
pub unsafe fn new(
|
||||||
session: &Session,
|
session: &Session,
|
||||||
width: usize,
|
width: usize,
|
||||||
height: usize,
|
height: usize,
|
||||||
n_bufs: usize,
|
n_bufs: usize,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let config = RenderConfig::new(width, height);
|
||||||
|
Self::new_from_config(session, config, n_bufs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new renderer.
|
||||||
|
pub unsafe fn new_from_config(
|
||||||
|
session: &Session,
|
||||||
|
config: RenderConfig,
|
||||||
|
n_bufs: usize,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
// For now, round up to tile alignment
|
// For now, round up to tile alignment
|
||||||
|
let width = config.width;
|
||||||
|
let height = config.height;
|
||||||
let width = width + (width.wrapping_neg() & (TILE_W - 1));
|
let width = width + (width.wrapping_neg() & (TILE_W - 1));
|
||||||
let height = height + (height.wrapping_neg() & (TILE_W - 1));
|
let height = height + (height.wrapping_neg() & (TILE_W - 1));
|
||||||
let dev = BufferUsage::STORAGE | BufferUsage::COPY_DST;
|
let dev = BufferUsage::STORAGE | BufferUsage::COPY_DST;
|
||||||
|
@ -126,7 +164,11 @@ impl Renderer {
|
||||||
.map(|_| session.create_buffer(8 * 1024 * 1024, host_upload).unwrap())
|
.map(|_| session.create_buffer(8 * 1024 * 1024, host_upload).unwrap())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let image_dev = session.create_image2d(width as u32, height as u32)?;
|
let image_format = match config.format {
|
||||||
|
PixelFormat::A8 => piet_gpu_hal::ImageFormat::A8,
|
||||||
|
PixelFormat::Rgba8 => piet_gpu_hal::ImageFormat::Rgba8,
|
||||||
|
};
|
||||||
|
let image_dev = session.create_image2d(width as u32, height as u32, image_format)?;
|
||||||
|
|
||||||
// Note: this must be updated when the config struct size changes.
|
// Note: this must be updated when the config struct size changes.
|
||||||
const CONFIG_BUFFER_SIZE: u64 = std::mem::size_of::<Config>() as u64;
|
const CONFIG_BUFFER_SIZE: u64 = std::mem::size_of::<Config>() as u64;
|
||||||
|
@ -211,7 +253,10 @@ impl Renderer {
|
||||||
.collect();
|
.collect();
|
||||||
let gradients = Self::make_gradient_image(&session);
|
let gradients = Self::make_gradient_image(&session);
|
||||||
|
|
||||||
let k4_code = include_shader!(session, "../shader/gen/kernel4");
|
let k4_code = match config.format {
|
||||||
|
PixelFormat::A8 => include_shader!(session, "../shader/gen/kernel4_gray"),
|
||||||
|
PixelFormat::Rgba8 => include_shader!(session, "../shader/gen/kernel4"),
|
||||||
|
};
|
||||||
let k4_pipeline = session.create_compute_pipeline(
|
let k4_pipeline = session.create_compute_pipeline(
|
||||||
k4_code,
|
k4_code,
|
||||||
&[
|
&[
|
||||||
|
@ -428,7 +473,8 @@ impl Renderer {
|
||||||
return Err("unsupported image format".into());
|
return Err("unsupported image format".into());
|
||||||
}
|
}
|
||||||
let buffer = session.create_buffer_init(&buf, BufferUsage::COPY_SRC)?;
|
let buffer = session.create_buffer_init(&buf, BufferUsage::COPY_SRC)?;
|
||||||
let image = session.create_image2d(width.try_into()?, height.try_into()?)?;
|
const RGBA: piet_gpu_hal::ImageFormat = piet_gpu_hal::ImageFormat::Rgba8;
|
||||||
|
let image = session.create_image2d(width.try_into()?, height.try_into()?, RGBA)?;
|
||||||
let mut cmd_buf = session.cmd_buf()?;
|
let mut cmd_buf = session.cmd_buf()?;
|
||||||
cmd_buf.begin();
|
cmd_buf.begin();
|
||||||
cmd_buf.image_barrier(&image, ImageLayout::Undefined, ImageLayout::BlitDst);
|
cmd_buf.image_barrier(&image, ImageLayout::Undefined, ImageLayout::BlitDst);
|
||||||
|
@ -464,8 +510,13 @@ impl Renderer {
|
||||||
|
|
||||||
fn make_gradient_image(session: &Session) -> Image {
|
fn make_gradient_image(session: &Session) -> Image {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
const RGBA: piet_gpu_hal::ImageFormat = piet_gpu_hal::ImageFormat::Rgba8;
|
||||||
session
|
session
|
||||||
.create_image2d(gradient::N_SAMPLES as u32, gradient::N_GRADIENTS as u32)
|
.create_image2d(
|
||||||
|
gradient::N_SAMPLES as u32,
|
||||||
|
gradient::N_GRADIENTS as u32,
|
||||||
|
RGBA,
|
||||||
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue