pub enum Context {
Vulkan(VulkanContext),
Gles(GlesContext),
}Expand description
A device to render with.
Which backend is behind it is decided at creation and reported by
Context::backend. Callers branch on Context::capabilities rather than
on which backend it turned out to be: a device without fence export is the
same problem whether it is Vulkan or GLES.
Variants§
Vulkan(VulkanContext)
Gles(GlesContext)
Implementations§
Source§impl Context
impl Context
Sourcepub fn new(preference: BackendPreference) -> Result<Self>
pub fn new(preference: BackendPreference) -> Result<Self>
Create a context, choosing a backend.
pub fn backend(&self) -> Backend
pub fn capabilities(&self) -> &Capabilities
Sourcepub fn create_surface(
&mut self,
extent: Extent2D,
format: PixelFormat,
) -> Result<Surface>
pub fn create_surface( &mut self, extent: Extent2D, format: PixelFormat, ) -> Result<Surface>
Create a surface to draw into.
Sourcepub fn draw(
&mut self,
surface: &mut Surface,
recording: &Recording,
) -> Result<()>
pub fn draw( &mut self, surface: &mut Surface, recording: &Recording, ) -> Result<()>
Draw a recording into a surface.
Sourcepub fn draw_with_images(
&mut self,
surface: &mut Surface,
recording: &Recording,
images: &[&Image],
) -> Result<()>
pub fn draw_with_images( &mut self, surface: &mut Surface, recording: &Recording, images: &[&Image], ) -> Result<()>
Draw a recording whose paints sample images.
images is the table a Shader::Image slot indexes, in slot order.
A recording carries slots rather than images because it is produced
without touching a device; supplying the table here is what resolves
them.
The surface is borrowed mutably and the images immutably, so a recording cannot sample the surface it draws into. That restriction is real, and having the compiler state it beats discovering it as a picture that differs by driver.
Sourcepub fn register_program(&mut self, program: &RuntimeProgram) -> Result<u32>
pub fn register_program(&mut self, program: &RuntimeProgram) -> Result<u32>
Register a fragment program a caller’s own build produced.
Returns the index to name it by, which is what goes into the program
of Shader::RuntimeEffect. Indices are per context: a recording that
names one is bound to the context that registered it, in exactly the
way one naming a texture slot is bound to the textures supplied
beside it.
Nothing here compiles a shader. The payload for the backend in use has to be present – SPIR-V for Vulkan, GLSL ES for GLES – and one built for the other backend alone is refused rather than silently ignored. See the architecture document for why a single source translated on load was declined.
Sourcepub fn create_image(
&mut self,
extent: Extent2D,
format: PixelFormat,
) -> Result<Image>
pub fn create_image( &mut self, extent: Extent2D, format: PixelFormat, ) -> Result<Image>
Allocate an image this context can sample.
The format decides how the bytes written into it are read, and the
choice is not cosmetic – though it now points the other way. Color
inside the renderer is sRGB-encoded, and an sRGB format decodes on
sample. A picture’s bytes are sRGB-encoded,
because that is what every image file holds, and the pipeline wants them
encoded – so a picture wants a plain format, and
PixelFormat::Rgba8UnormSrgb would decode it into light that nothing
downstream is expecting and wash it pale. Plain is also right for data
that is not color at all: coverage, a mask, a lookup table, anything
whose numbers mean themselves.
This advice was the reverse of itself while the renderer worked in light, and neither choice is detectable afterwards, which is why it is stated here. Both produce an image; only one produces the right picture.
Sourcepub fn create_mipmapped_image(
&mut self,
extent: Extent2D,
format: PixelFormat,
) -> Result<Image>
pub fn create_mipmapped_image( &mut self, extent: Extent2D, format: PixelFormat, ) -> Result<Image>
An image with a full mip chain, for drawing smaller than its own size.
The levels are filled when the image is written, not here, and the caller supplies only the image itself: a chain built by any rule other than the backend’s own would sample differently on the two backends, which is the one thing this renderer’s tests exist to rule out.
A third again in memory, which is why it is a separate call rather than
what every image gets. Only Sampling::Mipmap reads past the first
level, so an image created this way and drawn at any other quality costs
the memory and nothing else.
Sourcepub fn write_image(&mut self, image: &mut Image, pixels: &[u8]) -> Result<()>
pub fn write_image(&mut self, image: &mut Image, pixels: &[u8]) -> Result<()>
Fill an image from host memory, tightly packed and top row first.
Decoding is out of scope for this crate; bring image or another
decoder and hand the pixels here.
Sourcepub fn destroy_image(&mut self, image: Image)
pub fn destroy_image(&mut self, image: Image)
Release an image.
Explicit for the same reason a surface is: the memory belongs to the
context, which an image cannot reach from its own Drop.
Sourcepub fn read(&mut self, surface: &mut Surface) -> Result<Vec<u8>>
pub fn read(&mut self, surface: &mut Surface) -> Result<Vec<u8>>
Read a surface back, tightly packed, in whatever its format holds.
Four bytes per pixel for the eight-bit formats, which is every surface a
caller is likely to ask for; eight for Rgba16Float, as four
half-floats. Nothing is converted on the way out – the bytes are what
the target holds, and a caller who chose a format wider than eight bits
did so in order to read what it kept.
Sourcepub fn destroy_surface(&mut self, surface: Surface)
pub fn destroy_surface(&mut self, surface: Surface)
Release a surface.
Explicit because the memory belongs to the context, which a surface
cannot reach from its own Drop.