Merge pull request #337 from pcwalton/macos-radeon
Associate texture parameters in shaders with specific texture units, to work around a macOS Radeon driver bug.
This commit is contained in:
commit
8808bfda63
192
gl/src/lib.rs
192
gl/src/lib.rs
|
@ -21,29 +21,43 @@ use pathfinder_geometry::vector::Vector2I;
|
||||||
use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, BufferUploadMode, ClearOps};
|
use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, BufferUploadMode, ClearOps};
|
||||||
use pathfinder_gpu::{ComputeDimensions, ComputeState, DepthFunc, Device, FeatureLevel};
|
use pathfinder_gpu::{ComputeDimensions, ComputeState, DepthFunc, Device, FeatureLevel};
|
||||||
use pathfinder_gpu::{ImageAccess, ImageBinding, Primitive, ProgramKind, RenderOptions};
|
use pathfinder_gpu::{ImageAccess, ImageBinding, Primitive, ProgramKind, RenderOptions};
|
||||||
use pathfinder_gpu::{RenderState, RenderTarget, ShaderKind, StencilFunc, TextureData};
|
use pathfinder_gpu::{RenderState, RenderTarget, ShaderKind, StencilFunc, TextureBinding, TextureData};
|
||||||
use pathfinder_gpu::{TextureDataRef, TextureFormat, TextureSamplingFlags, UniformData};
|
use pathfinder_gpu::{TextureDataRef, TextureFormat, TextureSamplingFlags, UniformData};
|
||||||
use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
|
use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
|
||||||
use pathfinder_resources::ResourceLoader;
|
use pathfinder_resources::ResourceLoader;
|
||||||
use pathfinder_simd::default::F32x4;
|
use pathfinder_simd::default::F32x4;
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
const DUMMY_TEXTURE_LENGTH: i32 = 16;
|
||||||
|
|
||||||
pub struct GLDevice {
|
pub struct GLDevice {
|
||||||
version: GLVersion,
|
version: GLVersion,
|
||||||
default_framebuffer: GLuint,
|
default_framebuffer: GLuint,
|
||||||
|
dummy_texture: GLTexture,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GLDevice {
|
impl GLDevice {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(version: GLVersion, default_framebuffer: GLuint) -> GLDevice {
|
pub fn new(version: GLVersion, default_framebuffer: GLuint) -> GLDevice {
|
||||||
GLDevice {
|
let dummy_texture = GLTexture {
|
||||||
version,
|
gl_texture: 0,
|
||||||
default_framebuffer,
|
size: Vector2I::zero(),
|
||||||
}
|
format: TextureFormat::RGBA8,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut device = GLDevice { version, default_framebuffer, dummy_texture };
|
||||||
|
let dummy_texture_data =
|
||||||
|
[0; DUMMY_TEXTURE_LENGTH as usize * DUMMY_TEXTURE_LENGTH as usize * 4];
|
||||||
|
device.dummy_texture =
|
||||||
|
device.create_texture_from_data(TextureFormat::RGBA8,
|
||||||
|
Vector2I::splat(DUMMY_TEXTURE_LENGTH),
|
||||||
|
TextureDataRef::U8(&dummy_texture_data));
|
||||||
|
device
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_default_framebuffer(&mut self, framebuffer: GLuint) {
|
pub fn set_default_framebuffer(&mut self, framebuffer: GLuint) {
|
||||||
|
@ -64,9 +78,10 @@ impl GLDevice {
|
||||||
|
|
||||||
self.use_program(render_state.program);
|
self.use_program(render_state.program);
|
||||||
self.bind_vertex_array(render_state.vertex_array);
|
self.bind_vertex_array(render_state.vertex_array);
|
||||||
for (texture_unit, texture) in render_state.textures.iter().enumerate() {
|
|
||||||
self.bind_texture(texture, texture_unit as u32);
|
self.bind_textures_and_images(&render_state.program,
|
||||||
}
|
&render_state.textures,
|
||||||
|
&render_state.images);
|
||||||
|
|
||||||
render_state.uniforms.iter().for_each(|(uniform, data)| self.set_uniform(uniform, data));
|
render_state.uniforms.iter().for_each(|(uniform, data)| self.set_uniform(uniform, data));
|
||||||
|
|
||||||
|
@ -75,12 +90,10 @@ impl GLDevice {
|
||||||
|
|
||||||
fn set_compute_state(&self, compute_state: &ComputeState<GLDevice>) {
|
fn set_compute_state(&self, compute_state: &ComputeState<GLDevice>) {
|
||||||
self.use_program(compute_state.program);
|
self.use_program(compute_state.program);
|
||||||
for (texture_unit, texture) in compute_state.textures.iter().enumerate() {
|
|
||||||
self.bind_texture(texture, texture_unit as u32);
|
self.bind_textures_and_images(&compute_state.program,
|
||||||
}
|
&compute_state.textures,
|
||||||
for (image_unit, image) in compute_state.images.iter().enumerate() {
|
&compute_state.images);
|
||||||
self.bind_image(image, image_unit as u32);
|
|
||||||
}
|
|
||||||
|
|
||||||
compute_state.uniforms.iter().for_each(|(uniform, data)| self.set_uniform(uniform, data));
|
compute_state.uniforms.iter().for_each(|(uniform, data)| self.set_uniform(uniform, data));
|
||||||
|
|
||||||
|
@ -89,6 +102,43 @@ impl GLDevice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bind_textures_and_images(&self,
|
||||||
|
program: &GLProgram,
|
||||||
|
texture_bindings: &[TextureBinding<GLTextureParameter, GLTexture>],
|
||||||
|
image_bindings: &[ImageBinding<GLImageParameter, GLTexture>]) {
|
||||||
|
let (mut textures_bound, mut images_bound) = (0, 0);
|
||||||
|
for &(texture_parameter, texture) in texture_bindings {
|
||||||
|
self.bind_texture(texture, texture_parameter.texture_unit);
|
||||||
|
textures_bound |= 1 << texture_parameter.texture_unit as u64;
|
||||||
|
}
|
||||||
|
for image_binding in image_bindings {
|
||||||
|
self.bind_image(image_binding);
|
||||||
|
images_bound |= 1 << image_binding.0.image_unit as u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let parameters = program.parameters.borrow();
|
||||||
|
for (texture_unit, uniform) in parameters.textures.iter().enumerate() {
|
||||||
|
if (textures_bound & (1 << texture_unit as u64)) == 0 {
|
||||||
|
self.bind_texture(&self.dummy_texture, texture_unit as GLuint);
|
||||||
|
}
|
||||||
|
gl::Uniform1i(uniform.location, texture_unit as GLint); ck();
|
||||||
|
}
|
||||||
|
for (image_unit, uniform) in parameters.images.iter().enumerate() {
|
||||||
|
if (images_bound & (1 << image_unit as u64)) == 0 {
|
||||||
|
gl::BindImageTexture(image_unit as GLuint,
|
||||||
|
self.dummy_texture.gl_texture,
|
||||||
|
0,
|
||||||
|
gl::FALSE,
|
||||||
|
0,
|
||||||
|
gl::READ_ONLY,
|
||||||
|
gl::RGBA8 as GLenum); ck();
|
||||||
|
}
|
||||||
|
gl::Uniform1i(uniform.location, image_unit as GLint); ck();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_render_options(&self, render_options: &RenderOptions) {
|
fn set_render_options(&self, render_options: &RenderOptions) {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Set blend.
|
// Set blend.
|
||||||
|
@ -183,21 +233,6 @@ impl GLDevice {
|
||||||
UniformData::Vec4(data) => {
|
UniformData::Vec4(data) => {
|
||||||
gl::Uniform4f(uniform.location, data.x(), data.y(), data.z(), data.w()); ck();
|
gl::Uniform4f(uniform.location, data.x(), data.y(), data.z(), data.w()); ck();
|
||||||
}
|
}
|
||||||
UniformData::TextureUnit(unit) | UniformData::ImageUnit(unit) => {
|
|
||||||
gl::Uniform1i(uniform.location, unit as GLint); ck();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Workaround for a macOS driver bug, it seems.
|
|
||||||
fn unset_uniform(&self, uniform: &GLUniform, data: &UniformData) {
|
|
||||||
unsafe {
|
|
||||||
match *data {
|
|
||||||
UniformData::TextureUnit(_) => {
|
|
||||||
gl::Uniform1i(uniform.location, 0); ck();
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,10 +253,18 @@ impl GLDevice {
|
||||||
|
|
||||||
fn reset_render_state(&self, render_state: &RenderState<GLDevice>) {
|
fn reset_render_state(&self, render_state: &RenderState<GLDevice>) {
|
||||||
self.reset_render_options(&render_state.options);
|
self.reset_render_options(&render_state.options);
|
||||||
for texture_unit in 0..(render_state.textures.len() as u32) {
|
|
||||||
self.unbind_texture(texture_unit);
|
unsafe {
|
||||||
|
for image_binding in render_state.images {
|
||||||
|
self.unbind_image(image_binding.0.image_unit);
|
||||||
|
gl::Uniform1i(image_binding.0.uniform.location, 0); ck();
|
||||||
|
}
|
||||||
|
for texture_binding in render_state.textures {
|
||||||
|
self.unbind_texture(texture_binding.0.texture_unit);
|
||||||
|
gl::Uniform1i(texture_binding.0.uniform.location, 0); ck();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
render_state.uniforms.iter().for_each(|(uniform, data)| self.unset_uniform(uniform, data));
|
|
||||||
self.unuse_program();
|
self.unuse_program();
|
||||||
self.unbind_vertex_array();
|
self.unbind_vertex_array();
|
||||||
}
|
}
|
||||||
|
@ -230,15 +273,18 @@ impl GLDevice {
|
||||||
for &(storage_buffer, _) in compute_state.storage_buffers {
|
for &(storage_buffer, _) in compute_state.storage_buffers {
|
||||||
self.unset_storage_buffer(storage_buffer);
|
self.unset_storage_buffer(storage_buffer);
|
||||||
}
|
}
|
||||||
for image_unit in 0..(compute_state.images.len() as u32) {
|
|
||||||
self.unbind_image(image_unit);
|
unsafe {
|
||||||
}
|
for image_binding in compute_state.images {
|
||||||
for texture_unit in 0..(compute_state.textures.len() as u32) {
|
self.unbind_image(image_binding.0.image_unit);
|
||||||
self.unbind_texture(texture_unit);
|
gl::Uniform1i(image_binding.0.uniform.location, 0); ck();
|
||||||
}
|
}
|
||||||
for (uniform, data) in compute_state.uniforms {
|
for texture_binding in compute_state.textures {
|
||||||
self.unset_uniform(uniform, data);
|
self.unbind_texture(texture_binding.0.texture_unit);
|
||||||
|
gl::Uniform1i(texture_binding.0.uniform.location, 0); ck();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.unuse_program();
|
self.unuse_program();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,11 +312,13 @@ impl Device for GLDevice {
|
||||||
type Buffer = GLBuffer;
|
type Buffer = GLBuffer;
|
||||||
type Fence = GLFence;
|
type Fence = GLFence;
|
||||||
type Framebuffer = GLFramebuffer;
|
type Framebuffer = GLFramebuffer;
|
||||||
|
type ImageParameter = GLImageParameter;
|
||||||
type Program = GLProgram;
|
type Program = GLProgram;
|
||||||
type Shader = GLShader;
|
type Shader = GLShader;
|
||||||
type StorageBuffer = GLStorageBuffer;
|
type StorageBuffer = GLStorageBuffer;
|
||||||
type Texture = GLTexture;
|
type Texture = GLTexture;
|
||||||
type TextureDataReceiver = GLTextureDataReceiver;
|
type TextureDataReceiver = GLTextureDataReceiver;
|
||||||
|
type TextureParameter = GLTextureParameter;
|
||||||
type TimerQuery = GLTimerQuery;
|
type TimerQuery = GLTimerQuery;
|
||||||
type Uniform = GLUniform;
|
type Uniform = GLUniform;
|
||||||
type VertexArray = GLVertexArray;
|
type VertexArray = GLVertexArray;
|
||||||
|
@ -402,7 +450,9 @@ impl Device for GLDevice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLProgram { gl_program, shaders }
|
let parameters = GLProgramParameters { textures: vec![], images: vec![] };
|
||||||
|
|
||||||
|
GLProgram { gl_program, shaders, parameters: RefCell::new(parameters) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -439,6 +489,34 @@ impl Device for GLDevice {
|
||||||
GLUniform { location }
|
GLUniform { location }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_texture_parameter(&self, program: &GLProgram, name: &str) -> GLTextureParameter {
|
||||||
|
let uniform = self.get_uniform(program, name);
|
||||||
|
let mut parameters = program.parameters.borrow_mut();
|
||||||
|
let index = match parameters.textures.iter().position(|u| *u == uniform) {
|
||||||
|
Some(index) => index,
|
||||||
|
None => {
|
||||||
|
let index = parameters.textures.len();
|
||||||
|
parameters.textures.push(uniform.clone());
|
||||||
|
index
|
||||||
|
}
|
||||||
|
};
|
||||||
|
GLTextureParameter { uniform, texture_unit: index as GLuint }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_image_parameter(&self, program: &GLProgram, name: &str) -> GLImageParameter {
|
||||||
|
let uniform = self.get_uniform(program, name);
|
||||||
|
let mut parameters = program.parameters.borrow_mut();
|
||||||
|
let index = match parameters.images.iter().position(|u| *u == uniform) {
|
||||||
|
Some(index) => index,
|
||||||
|
None => {
|
||||||
|
let index = parameters.images.len();
|
||||||
|
parameters.images.push(uniform.clone());
|
||||||
|
index
|
||||||
|
}
|
||||||
|
};
|
||||||
|
GLImageParameter { uniform, image_unit: index as GLuint }
|
||||||
|
}
|
||||||
|
|
||||||
fn get_storage_buffer(&self, _: &Self::Program, _: &str, binding: u32) -> GLStorageBuffer {
|
fn get_storage_buffer(&self, _: &Self::Program, _: &str, binding: u32) -> GLStorageBuffer {
|
||||||
GLStorageBuffer { location: binding as GLint }
|
GLStorageBuffer { location: binding as GLint }
|
||||||
}
|
}
|
||||||
|
@ -872,15 +950,15 @@ impl GLDevice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bind_image(&self, binding: &ImageBinding<GLDevice>, unit: u32) {
|
fn bind_image(&self, binding: &ImageBinding<GLImageParameter, GLTexture>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::BindImageTexture(unit,
|
gl::BindImageTexture(binding.0.image_unit,
|
||||||
binding.texture.gl_texture,
|
binding.1.gl_texture,
|
||||||
0,
|
0,
|
||||||
gl::FALSE,
|
gl::FALSE,
|
||||||
0,
|
0,
|
||||||
binding.access.to_gl_access(),
|
binding.2.to_gl_access(),
|
||||||
binding.texture.format.gl_internal_format() as GLenum); ck();
|
binding.1.format.gl_internal_format() as GLenum); ck();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1109,11 +1187,23 @@ impl Drop for GLBuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
pub struct GLUniform {
|
pub struct GLUniform {
|
||||||
location: GLint,
|
location: GLint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GLTextureParameter {
|
||||||
|
uniform: GLUniform,
|
||||||
|
texture_unit: GLuint,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GLImageParameter {
|
||||||
|
uniform: GLUniform,
|
||||||
|
image_unit: GLuint,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GLStorageBuffer {
|
pub struct GLStorageBuffer {
|
||||||
location: GLint,
|
location: GLint,
|
||||||
|
@ -1123,6 +1213,7 @@ pub struct GLProgram {
|
||||||
pub gl_program: GLuint,
|
pub gl_program: GLuint,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
shaders: ProgramKind<GLShader>,
|
shaders: ProgramKind<GLShader>,
|
||||||
|
parameters: RefCell<GLProgramParameters>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for GLProgram {
|
impl Drop for GLProgram {
|
||||||
|
@ -1133,6 +1224,13 @@ impl Drop for GLProgram {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct GLProgramParameters {
|
||||||
|
// Mapping from texture unit number to uniform location.
|
||||||
|
textures: Vec<GLUniform>,
|
||||||
|
// Mapping from image unit number to uniform location.
|
||||||
|
images: Vec<GLUniform>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct GLShader {
|
pub struct GLShader {
|
||||||
gl_shader: GLuint,
|
gl_shader: GLuint,
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,10 +28,12 @@ pub trait Device: Sized {
|
||||||
type Buffer;
|
type Buffer;
|
||||||
type Fence;
|
type Fence;
|
||||||
type Framebuffer;
|
type Framebuffer;
|
||||||
|
type ImageParameter;
|
||||||
type Program;
|
type Program;
|
||||||
type Shader;
|
type Shader;
|
||||||
type StorageBuffer;
|
type StorageBuffer;
|
||||||
type Texture;
|
type Texture;
|
||||||
|
type TextureParameter;
|
||||||
type TextureDataReceiver;
|
type TextureDataReceiver;
|
||||||
type TimerQuery;
|
type TimerQuery;
|
||||||
type Uniform;
|
type Uniform;
|
||||||
|
@ -57,6 +59,8 @@ pub trait Device: Sized {
|
||||||
local_size: ComputeDimensions);
|
local_size: ComputeDimensions);
|
||||||
fn get_vertex_attr(&self, program: &Self::Program, name: &str) -> Option<Self::VertexAttr>;
|
fn get_vertex_attr(&self, program: &Self::Program, name: &str) -> Option<Self::VertexAttr>;
|
||||||
fn get_uniform(&self, program: &Self::Program, name: &str) -> Self::Uniform;
|
fn get_uniform(&self, program: &Self::Program, name: &str) -> Self::Uniform;
|
||||||
|
fn get_texture_parameter(&self, program: &Self::Program, name: &str) -> Self::TextureParameter;
|
||||||
|
fn get_image_parameter(&self, program: &Self::Program, name: &str) -> Self::ImageParameter;
|
||||||
fn get_storage_buffer(&self, program: &Self::Program, name: &str, binding: u32)
|
fn get_storage_buffer(&self, program: &Self::Program, name: &str, binding: u32)
|
||||||
-> Self::StorageBuffer;
|
-> Self::StorageBuffer;
|
||||||
fn bind_buffer(&self,
|
fn bind_buffer(&self,
|
||||||
|
@ -237,8 +241,6 @@ pub enum UniformData {
|
||||||
Vec2(F32x2),
|
Vec2(F32x2),
|
||||||
Vec3([f32; 3]),
|
Vec3([f32; 3]),
|
||||||
Vec4(F32x4),
|
Vec4(F32x4),
|
||||||
TextureUnit(u32),
|
|
||||||
ImageUnit(u32),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
@ -253,9 +255,9 @@ pub struct RenderState<'a, D> where D: Device {
|
||||||
pub program: &'a D::Program,
|
pub program: &'a D::Program,
|
||||||
pub vertex_array: &'a D::VertexArray,
|
pub vertex_array: &'a D::VertexArray,
|
||||||
pub primitive: Primitive,
|
pub primitive: Primitive,
|
||||||
pub uniforms: &'a [(&'a D::Uniform, UniformData)],
|
pub uniforms: &'a [UniformBinding<'a, D::Uniform>],
|
||||||
pub textures: &'a [&'a D::Texture],
|
pub textures: &'a [TextureBinding<'a, D::TextureParameter, D::Texture>],
|
||||||
pub images: &'a [ImageBinding<'a, D>],
|
pub images: &'a [ImageBinding<'a, D::ImageParameter, D::Texture>],
|
||||||
pub viewport: RectI,
|
pub viewport: RectI,
|
||||||
pub options: RenderOptions,
|
pub options: RenderOptions,
|
||||||
}
|
}
|
||||||
|
@ -263,17 +265,17 @@ pub struct RenderState<'a, D> where D: Device {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ComputeState<'a, D> where D: Device {
|
pub struct ComputeState<'a, D> where D: Device {
|
||||||
pub program: &'a D::Program,
|
pub program: &'a D::Program,
|
||||||
pub uniforms: &'a [(&'a D::Uniform, UniformData)],
|
pub uniforms: &'a [UniformBinding<'a, D::Uniform>],
|
||||||
pub textures: &'a [&'a D::Texture],
|
pub textures: &'a [TextureBinding<'a, D::TextureParameter, D::Texture>],
|
||||||
pub images: &'a [ImageBinding<'a, D>],
|
pub images: &'a [ImageBinding<'a, D::ImageParameter, D::Texture>],
|
||||||
pub storage_buffers: &'a [(&'a D::StorageBuffer, &'a D::Buffer)],
|
pub storage_buffers: &'a [(&'a D::StorageBuffer, &'a D::Buffer)],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
pub type UniformBinding<'a, U> = (&'a U, UniformData);
|
||||||
pub struct ImageBinding<'a, D> where D: Device {
|
|
||||||
pub texture: &'a D::Texture,
|
pub type TextureBinding<'a, TP, T> = (&'a TP, &'a T);
|
||||||
pub access: ImageAccess,
|
|
||||||
}
|
pub type ImageBinding<'a, IP, T> = (&'a IP, &'a T, ImageAccess);
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct RenderOptions {
|
pub struct RenderOptions {
|
||||||
|
|
397
metal/src/lib.rs
397
metal/src/lib.rs
|
@ -221,6 +221,18 @@ pub struct MetalUniform {
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct MetalTextureParameter {
|
||||||
|
indices: RefCell<Option<MetalTextureIndices>>,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct MetalImageParameter {
|
||||||
|
indices: RefCell<Option<MetalImageIndices>>,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct MetalStorageBuffer {
|
pub struct MetalStorageBuffer {
|
||||||
indices: RefCell<Option<MetalStorageBufferIndices>>,
|
indices: RefCell<Option<MetalStorageBufferIndices>>,
|
||||||
|
@ -231,13 +243,28 @@ pub struct MetalStorageBuffer {
|
||||||
pub struct MetalUniformIndices(ProgramKind<Option<MetalUniformIndex>>);
|
pub struct MetalUniformIndices(ProgramKind<Option<MetalUniformIndex>>);
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct MetalUniformIndex {
|
pub struct MetalUniformIndex(u64);
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct MetalTextureIndices(ProgramKind<Option<MetalTextureIndex>>);
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct MetalTextureIndex {
|
||||||
main: u64,
|
main: u64,
|
||||||
sampler: Option<u64>,
|
sampler: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct MetalStorageBufferIndices(ProgramKind<Option<u64>>);
|
pub struct MetalImageIndices(ProgramKind<Option<MetalImageIndex>>);
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct MetalImageIndex(u64);
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct MetalStorageBufferIndices(ProgramKind<Option<MetalStorageBufferIndex>>);
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct MetalStorageBufferIndex(u64);
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct MetalFence(Arc<MetalFenceInfo>);
|
pub struct MetalFence(Arc<MetalFenceInfo>);
|
||||||
|
@ -263,11 +290,13 @@ impl Device for MetalDevice {
|
||||||
type Buffer = MetalBuffer;
|
type Buffer = MetalBuffer;
|
||||||
type Fence = MetalFence;
|
type Fence = MetalFence;
|
||||||
type Framebuffer = MetalFramebuffer;
|
type Framebuffer = MetalFramebuffer;
|
||||||
|
type ImageParameter = MetalImageParameter;
|
||||||
type Program = MetalProgram;
|
type Program = MetalProgram;
|
||||||
type Shader = MetalShader;
|
type Shader = MetalShader;
|
||||||
type StorageBuffer = MetalStorageBuffer;
|
type StorageBuffer = MetalStorageBuffer;
|
||||||
type Texture = MetalTexture;
|
type Texture = MetalTexture;
|
||||||
type TextureDataReceiver = MetalTextureDataReceiver;
|
type TextureDataReceiver = MetalTextureDataReceiver;
|
||||||
|
type TextureParameter = MetalTextureParameter;
|
||||||
type TimerQuery = MetalTimerQuery;
|
type TimerQuery = MetalTimerQuery;
|
||||||
type Uniform = MetalUniform;
|
type Uniform = MetalUniform;
|
||||||
type VertexArray = MetalVertexArray;
|
type VertexArray = MetalVertexArray;
|
||||||
|
@ -397,6 +426,14 @@ impl Device for MetalDevice {
|
||||||
MetalUniform { indices: RefCell::new(None), name: name.to_owned() }
|
MetalUniform { indices: RefCell::new(None), name: name.to_owned() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_texture_parameter(&self, _: &Self::Program, name: &str) -> MetalTextureParameter {
|
||||||
|
MetalTextureParameter { indices: RefCell::new(None), name: name.to_owned() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_image_parameter(&self, _: &Self::Program, name: &str) -> MetalImageParameter {
|
||||||
|
MetalImageParameter { indices: RefCell::new(None), name: name.to_owned() }
|
||||||
|
}
|
||||||
|
|
||||||
fn get_storage_buffer(&self, _: &Self::Program, name: &str, _: u32) -> MetalStorageBuffer {
|
fn get_storage_buffer(&self, _: &Self::Program, name: &str, _: u32) -> MetalStorageBuffer {
|
||||||
MetalStorageBuffer { indices: RefCell::new(None), name: name.to_owned() }
|
MetalStorageBuffer { indices: RefCell::new(None), name: name.to_owned() }
|
||||||
}
|
}
|
||||||
|
@ -848,6 +885,23 @@ impl MetalDevice {
|
||||||
None => panic!("get_uniform_index() called before reflection!"),
|
None => panic!("get_uniform_index() called before reflection!"),
|
||||||
Some(ref arguments) => arguments,
|
Some(ref arguments) => arguments,
|
||||||
};
|
};
|
||||||
|
let main_name = format!("u{}", name);
|
||||||
|
for argument_index in 0..arguments.len() {
|
||||||
|
let argument = arguments.object_at(argument_index);
|
||||||
|
let argument_name = argument.name();
|
||||||
|
if argument_name == &main_name {
|
||||||
|
return Some(MetalUniformIndex(argument.index()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_texture_index(&self, shader: &MetalShader, name: &str) -> Option<MetalTextureIndex> {
|
||||||
|
let arguments = shader.arguments.borrow();
|
||||||
|
let arguments = match *arguments {
|
||||||
|
None => panic!("get_texture_index() called before reflection!"),
|
||||||
|
Some(ref arguments) => arguments,
|
||||||
|
};
|
||||||
let (main_name, sampler_name) = (format!("u{}", name), format!("u{}Smplr", name));
|
let (main_name, sampler_name) = (format!("u{}", name), format!("u{}Smplr", name));
|
||||||
let (mut main_argument, mut sampler_argument) = (None, None);
|
let (mut main_argument, mut sampler_argument) = (None, None);
|
||||||
for argument_index in 0..arguments.len() {
|
for argument_index in 0..arguments.len() {
|
||||||
|
@ -859,14 +913,31 @@ impl MetalDevice {
|
||||||
sampler_argument = Some(argument.index());
|
sampler_argument = Some(argument.index());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let uniform_index = match main_argument {
|
match (main_argument, sampler_argument) {
|
||||||
None => None,
|
(Some(main), Some(sampler)) => Some(MetalTextureIndex { main, sampler }),
|
||||||
Some(main) => Some(MetalUniformIndex { main, sampler: sampler_argument }),
|
_ => None,
|
||||||
};
|
}
|
||||||
uniform_index
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_storage_buffer_index(&self, shader: &MetalShader, name: &str) -> Option<u64> {
|
fn get_image_index(&self, shader: &MetalShader, name: &str) -> Option<MetalImageIndex> {
|
||||||
|
let uniforms = shader.arguments.borrow();
|
||||||
|
let arguments = match *uniforms {
|
||||||
|
None => panic!("get_image_index() called before reflection!"),
|
||||||
|
Some(ref arguments) => arguments,
|
||||||
|
};
|
||||||
|
let main_name = format!("u{}", name);
|
||||||
|
for argument_index in 0..arguments.len() {
|
||||||
|
let argument = arguments.object_at(argument_index);
|
||||||
|
let argument_name = argument.name();
|
||||||
|
if argument_name == &main_name {
|
||||||
|
return Some(MetalImageIndex(argument.index()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_storage_buffer_index(&self, shader: &MetalShader, name: &str)
|
||||||
|
-> Option<MetalStorageBufferIndex> {
|
||||||
let uniforms = shader.arguments.borrow();
|
let uniforms = shader.arguments.borrow();
|
||||||
let arguments = match *uniforms {
|
let arguments = match *uniforms {
|
||||||
None => panic!("get_storage_buffer_index() called before reflection!"),
|
None => panic!("get_storage_buffer_index() called before reflection!"),
|
||||||
|
@ -889,11 +960,7 @@ impl MetalDevice {
|
||||||
main_argument = Some(argument.index());
|
main_argument = Some(argument.index());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let storage_buffer_index = match main_argument {
|
main_argument.map(MetalStorageBufferIndex)
|
||||||
None => None,
|
|
||||||
Some(main) => Some(main),
|
|
||||||
};
|
|
||||||
storage_buffer_index
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn populate_uniform_indices_if_necessary(&self,
|
fn populate_uniform_indices_if_necessary(&self,
|
||||||
|
@ -921,6 +988,56 @@ impl MetalDevice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn populate_texture_indices_if_necessary(&self,
|
||||||
|
texture_parameter: &MetalTextureParameter,
|
||||||
|
program: &MetalProgram) {
|
||||||
|
let mut indices = texture_parameter.indices.borrow_mut();
|
||||||
|
if indices.is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*indices = match program {
|
||||||
|
MetalProgram::Raster(MetalRasterProgram {
|
||||||
|
ref vertex_shader,
|
||||||
|
ref fragment_shader,
|
||||||
|
}) => {
|
||||||
|
Some(MetalTextureIndices(ProgramKind::Raster {
|
||||||
|
vertex: self.get_texture_index(vertex_shader, &texture_parameter.name),
|
||||||
|
fragment: self.get_texture_index(fragment_shader, &texture_parameter.name),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
MetalProgram::Compute(MetalComputeProgram { ref shader, .. }) => {
|
||||||
|
let image_index = self.get_texture_index(shader, &texture_parameter.name);
|
||||||
|
Some(MetalTextureIndices(ProgramKind::Compute(image_index)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn populate_image_indices_if_necessary(&self,
|
||||||
|
image_parameter: &MetalImageParameter,
|
||||||
|
program: &MetalProgram) {
|
||||||
|
let mut indices = image_parameter.indices.borrow_mut();
|
||||||
|
if indices.is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*indices = match program {
|
||||||
|
MetalProgram::Raster(MetalRasterProgram {
|
||||||
|
ref vertex_shader,
|
||||||
|
ref fragment_shader,
|
||||||
|
}) => {
|
||||||
|
Some(MetalImageIndices(ProgramKind::Raster {
|
||||||
|
vertex: self.get_image_index(vertex_shader, &image_parameter.name),
|
||||||
|
fragment: self.get_image_index(fragment_shader, &image_parameter.name),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
MetalProgram::Compute(MetalComputeProgram { ref shader, .. }) => {
|
||||||
|
let image_index = self.get_image_index(shader, &image_parameter.name);
|
||||||
|
Some(MetalImageIndices(ProgramKind::Compute(image_index)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn populate_storage_buffer_indices_if_necessary(&self,
|
fn populate_storage_buffer_indices_if_necessary(&self,
|
||||||
storage_buffer: &MetalStorageBuffer,
|
storage_buffer: &MetalStorageBuffer,
|
||||||
program: &MetalProgram) {
|
program: &MetalProgram) {
|
||||||
|
@ -976,7 +1093,7 @@ impl MetalDevice {
|
||||||
|
|
||||||
// FIXME(pcwalton): Is this necessary?
|
// FIXME(pcwalton): Is this necessary?
|
||||||
let mut blit_command_encoder = None;
|
let mut blit_command_encoder = None;
|
||||||
for texture in render_state.textures {
|
for &(_, texture) in render_state.textures {
|
||||||
if !texture.dirty.get() {
|
if !texture.dirty.get() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1078,8 +1195,9 @@ impl MetalDevice {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set uniforms.
|
||||||
let uniform_buffer = self.create_uniform_buffer(&render_state.uniforms);
|
let uniform_buffer = self.create_uniform_buffer(&render_state.uniforms);
|
||||||
for (&(uniform, ref uniform_data), buffer_range) in
|
for (&(uniform, _), buffer_range) in
|
||||||
render_state.uniforms.iter().zip(uniform_buffer.ranges.iter()) {
|
render_state.uniforms.iter().zip(uniform_buffer.ranges.iter()) {
|
||||||
self.populate_uniform_indices_if_necessary(uniform, &render_state.program);
|
self.populate_uniform_indices_if_necessary(uniform, &render_state.program);
|
||||||
|
|
||||||
|
@ -1092,19 +1210,58 @@ impl MetalDevice {
|
||||||
|
|
||||||
if let Some(vertex_index) = *vertex_indices {
|
if let Some(vertex_index) = *vertex_indices {
|
||||||
self.set_vertex_uniform(vertex_index,
|
self.set_vertex_uniform(vertex_index,
|
||||||
uniform_data,
|
|
||||||
&uniform_buffer.data,
|
&uniform_buffer.data,
|
||||||
buffer_range,
|
buffer_range,
|
||||||
render_command_encoder,
|
render_command_encoder);
|
||||||
render_state);
|
|
||||||
}
|
}
|
||||||
if let Some(fragment_index) = *fragment_indices {
|
if let Some(fragment_index) = *fragment_indices {
|
||||||
self.set_fragment_uniform(fragment_index,
|
self.set_fragment_uniform(fragment_index,
|
||||||
uniform_data,
|
|
||||||
&uniform_buffer.data,
|
&uniform_buffer.data,
|
||||||
buffer_range,
|
buffer_range,
|
||||||
render_command_encoder,
|
render_command_encoder);
|
||||||
render_state);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set textures.
|
||||||
|
for &(texture_param, texture) in render_state.textures {
|
||||||
|
self.populate_texture_indices_if_necessary(texture_param, &render_state.program);
|
||||||
|
|
||||||
|
let indices = texture_param.indices.borrow_mut();
|
||||||
|
let indices = indices.as_ref().unwrap();
|
||||||
|
let (vertex_indices, fragment_indices) = match indices.0 {
|
||||||
|
ProgramKind::Raster { ref vertex, ref fragment } => (vertex, fragment),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(vertex_index) = *vertex_indices {
|
||||||
|
self.encode_vertex_texture_parameter(vertex_index,
|
||||||
|
render_command_encoder,
|
||||||
|
texture);
|
||||||
|
}
|
||||||
|
if let Some(fragment_index) = *fragment_indices {
|
||||||
|
self.encode_fragment_texture_parameter(fragment_index,
|
||||||
|
render_command_encoder,
|
||||||
|
texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set images.
|
||||||
|
for &(image_param, image, _) in render_state.images {
|
||||||
|
self.populate_image_indices_if_necessary(image_param, &render_state.program);
|
||||||
|
|
||||||
|
let indices = image_param.indices.borrow_mut();
|
||||||
|
let indices = indices.as_ref().unwrap();
|
||||||
|
let (vertex_indices, fragment_indices) = match indices.0 {
|
||||||
|
ProgramKind::Raster { ref vertex, ref fragment } => (vertex, fragment),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(vertex_index) = *vertex_indices {
|
||||||
|
render_command_encoder.set_vertex_texture(vertex_index.0, Some(&image.texture));
|
||||||
|
}
|
||||||
|
if let Some(fragment_index) = *fragment_indices {
|
||||||
|
render_command_encoder.set_fragment_texture(fragment_index.0,
|
||||||
|
Some(&image.texture));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1112,8 +1269,9 @@ impl MetalDevice {
|
||||||
fn set_compute_uniforms(&self,
|
fn set_compute_uniforms(&self,
|
||||||
compute_command_encoder: &ComputeCommandEncoderRef,
|
compute_command_encoder: &ComputeCommandEncoderRef,
|
||||||
compute_state: &ComputeState<MetalDevice>) {
|
compute_state: &ComputeState<MetalDevice>) {
|
||||||
|
// Set uniforms.
|
||||||
let uniform_buffer = self.create_uniform_buffer(&compute_state.uniforms);
|
let uniform_buffer = self.create_uniform_buffer(&compute_state.uniforms);
|
||||||
for (&(uniform, ref uniform_data), buffer_range) in
|
for (&(uniform, _), buffer_range) in
|
||||||
compute_state.uniforms.iter().zip(uniform_buffer.ranges.iter()) {
|
compute_state.uniforms.iter().zip(uniform_buffer.ranges.iter()) {
|
||||||
self.populate_uniform_indices_if_necessary(uniform, &compute_state.program);
|
self.populate_uniform_indices_if_necessary(uniform, &compute_state.program);
|
||||||
|
|
||||||
|
@ -1124,13 +1282,43 @@ impl MetalDevice {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(index) = *indices {
|
if let Some(indices) = *indices {
|
||||||
self.set_compute_uniform(index,
|
self.set_compute_uniform(indices,
|
||||||
uniform_data,
|
|
||||||
&uniform_buffer.data,
|
&uniform_buffer.data,
|
||||||
buffer_range,
|
buffer_range,
|
||||||
compute_command_encoder,
|
compute_command_encoder);
|
||||||
compute_state);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set textures.
|
||||||
|
for &(texture_param, texture) in compute_state.textures {
|
||||||
|
self.populate_texture_indices_if_necessary(texture_param, &compute_state.program);
|
||||||
|
|
||||||
|
let indices = texture_param.indices.borrow_mut();
|
||||||
|
let indices = indices.as_ref().unwrap();
|
||||||
|
let indices = match indices.0 {
|
||||||
|
ProgramKind::Compute(ref indices) => indices,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(indices) = *indices {
|
||||||
|
self.encode_compute_texture_parameter(indices, compute_command_encoder, texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set images.
|
||||||
|
for &(image_param, image, _) in compute_state.images {
|
||||||
|
self.populate_image_indices_if_necessary(image_param, &compute_state.program);
|
||||||
|
|
||||||
|
let indices = image_param.indices.borrow_mut();
|
||||||
|
let indices = indices.as_ref().unwrap();
|
||||||
|
let indices = match indices.0 {
|
||||||
|
ProgramKind::Compute(ref indices) => indices,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(indices) = *indices {
|
||||||
|
compute_command_encoder.set_texture(indices.0, Some(&image.texture));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1148,7 +1336,7 @@ impl MetalDevice {
|
||||||
|
|
||||||
if let Some(index) = *indices {
|
if let Some(index) = *indices {
|
||||||
if let Some(ref buffer) = *storage_buffer_binding.buffer.borrow() {
|
if let Some(ref buffer) = *storage_buffer_binding.buffer.borrow() {
|
||||||
compute_command_encoder.set_buffer(index, Some(buffer), 0);
|
compute_command_encoder.set_buffer(index.0, Some(buffer), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1204,7 +1392,6 @@ impl MetalDevice {
|
||||||
uniform_buffer_data.write_f32::<NativeEndian>(vector.z()).unwrap();
|
uniform_buffer_data.write_f32::<NativeEndian>(vector.z()).unwrap();
|
||||||
uniform_buffer_data.write_f32::<NativeEndian>(vector.w()).unwrap();
|
uniform_buffer_data.write_f32::<NativeEndian>(vector.w()).unwrap();
|
||||||
}
|
}
|
||||||
UniformData::TextureUnit(_) | UniformData::ImageUnit(_) => {}
|
|
||||||
}
|
}
|
||||||
let end_index = uniform_buffer_data.len();
|
let end_index = uniform_buffer_data.len();
|
||||||
while uniform_buffer_data.len() % 256 != 0 {
|
while uniform_buffer_data.len() % 256 != 0 {
|
||||||
|
@ -1221,119 +1408,62 @@ impl MetalDevice {
|
||||||
|
|
||||||
fn set_vertex_uniform(&self,
|
fn set_vertex_uniform(&self,
|
||||||
argument_index: MetalUniformIndex,
|
argument_index: MetalUniformIndex,
|
||||||
uniform_data: &UniformData,
|
|
||||||
buffer: &[u8],
|
buffer: &[u8],
|
||||||
buffer_range: &Range<usize>,
|
buffer_range: &Range<usize>,
|
||||||
render_command_encoder: &RenderCommandEncoderRef,
|
render_command_encoder: &RenderCommandEncoderRef) {
|
||||||
render_state: &RenderState<MetalDevice>) {
|
render_command_encoder.set_vertex_bytes(
|
||||||
match *uniform_data {
|
argument_index.0,
|
||||||
UniformData::TextureUnit(unit) => {
|
(buffer_range.end - buffer_range.start) as u64,
|
||||||
let texture = render_state.textures[unit as usize];
|
&buffer[buffer_range.start as usize] as *const u8 as *const _)
|
||||||
self.encode_vertex_texture_uniform(argument_index,
|
|
||||||
render_command_encoder,
|
|
||||||
texture);
|
|
||||||
}
|
|
||||||
UniformData::ImageUnit(unit) => {
|
|
||||||
let image = &render_state.images[unit as usize];
|
|
||||||
render_command_encoder.set_vertex_texture(argument_index.main,
|
|
||||||
Some(&image.texture.texture));
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
render_command_encoder.set_vertex_bytes(
|
|
||||||
argument_index.main,
|
|
||||||
(buffer_range.end - buffer_range.start) as u64,
|
|
||||||
&buffer[buffer_range.start as usize] as *const u8 as *const _)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_fragment_uniform(&self,
|
fn set_fragment_uniform(&self,
|
||||||
argument_index: MetalUniformIndex,
|
argument_index: MetalUniformIndex,
|
||||||
uniform_data: &UniformData,
|
|
||||||
buffer: &[u8],
|
buffer: &[u8],
|
||||||
buffer_range: &Range<usize>,
|
buffer_range: &Range<usize>,
|
||||||
render_command_encoder: &RenderCommandEncoderRef,
|
render_command_encoder: &RenderCommandEncoderRef) {
|
||||||
render_state: &RenderState<MetalDevice>) {
|
render_command_encoder.set_fragment_bytes(
|
||||||
match *uniform_data {
|
argument_index.0,
|
||||||
UniformData::TextureUnit(unit) => {
|
(buffer_range.end - buffer_range.start) as u64,
|
||||||
let texture = render_state.textures[unit as usize];
|
&buffer[buffer_range.start as usize] as *const u8 as *const _)
|
||||||
self.encode_fragment_texture_uniform(argument_index,
|
|
||||||
render_command_encoder,
|
|
||||||
texture);
|
|
||||||
}
|
|
||||||
UniformData::ImageUnit(unit) => {
|
|
||||||
let image = &render_state.images[unit as usize];
|
|
||||||
render_command_encoder.set_fragment_texture(argument_index.main,
|
|
||||||
Some(&image.texture.texture));
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
render_command_encoder.set_fragment_bytes(
|
|
||||||
argument_index.main,
|
|
||||||
(buffer_range.end - buffer_range.start) as u64,
|
|
||||||
&buffer[buffer_range.start as usize] as *const u8 as *const _)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_compute_uniform(&self,
|
fn set_compute_uniform(&self,
|
||||||
argument_index: MetalUniformIndex,
|
argument_index: MetalUniformIndex,
|
||||||
uniform_data: &UniformData,
|
|
||||||
buffer: &[u8],
|
buffer: &[u8],
|
||||||
buffer_range: &Range<usize>,
|
buffer_range: &Range<usize>,
|
||||||
compute_command_encoder: &ComputeCommandEncoderRef,
|
compute_command_encoder: &ComputeCommandEncoderRef) {
|
||||||
compute_state: &ComputeState<MetalDevice>) {
|
compute_command_encoder.set_bytes(
|
||||||
match *uniform_data {
|
argument_index.0,
|
||||||
UniformData::TextureUnit(unit) => {
|
(buffer_range.end - buffer_range.start) as u64,
|
||||||
let texture = compute_state.textures[unit as usize];
|
&buffer[buffer_range.start as usize] as *const u8 as *const _)
|
||||||
self.encode_compute_texture_uniform(argument_index,
|
|
||||||
compute_command_encoder,
|
|
||||||
texture);
|
|
||||||
}
|
|
||||||
UniformData::ImageUnit(unit) => {
|
|
||||||
let image = &compute_state.images[unit as usize];
|
|
||||||
compute_command_encoder.set_texture(argument_index.main,
|
|
||||||
Some(&image.texture.texture));
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
compute_command_encoder.set_bytes(
|
|
||||||
argument_index.main,
|
|
||||||
(buffer_range.end - buffer_range.start) as u64,
|
|
||||||
&buffer[buffer_range.start as usize] as *const u8 as *const _)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_vertex_texture_uniform(&self,
|
fn encode_vertex_texture_parameter(&self,
|
||||||
argument_index: MetalUniformIndex,
|
argument_index: MetalTextureIndex,
|
||||||
render_command_encoder: &RenderCommandEncoderRef,
|
|
||||||
texture: &MetalTexture) {
|
|
||||||
render_command_encoder.set_vertex_texture(argument_index.main, Some(&texture.texture));
|
|
||||||
if let Some(sampler_index) = argument_index.sampler {
|
|
||||||
let sampler = &self.samplers[texture.sampling_flags.get().bits() as usize];
|
|
||||||
render_command_encoder.set_vertex_sampler_state(sampler_index, Some(sampler));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn encode_fragment_texture_uniform(&self,
|
|
||||||
argument_index: MetalUniformIndex,
|
|
||||||
render_command_encoder: &RenderCommandEncoderRef,
|
render_command_encoder: &RenderCommandEncoderRef,
|
||||||
texture: &MetalTexture) {
|
texture: &MetalTexture) {
|
||||||
render_command_encoder.set_fragment_texture(argument_index.main, Some(&texture.texture));
|
render_command_encoder.set_vertex_texture(argument_index.main, Some(&texture.texture));
|
||||||
if let Some(sampler_index) = argument_index.sampler {
|
let sampler = &self.samplers[texture.sampling_flags.get().bits() as usize];
|
||||||
let sampler = &self.samplers[texture.sampling_flags.get().bits() as usize];
|
render_command_encoder.set_vertex_sampler_state(argument_index.sampler, Some(sampler));
|
||||||
render_command_encoder.set_fragment_sampler_state(sampler_index, Some(sampler));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_compute_texture_uniform(&self,
|
fn encode_fragment_texture_parameter(&self,
|
||||||
argument_index: MetalUniformIndex,
|
argument_index: MetalTextureIndex,
|
||||||
compute_command_encoder: &ComputeCommandEncoderRef,
|
render_command_encoder: &RenderCommandEncoderRef,
|
||||||
texture: &MetalTexture) {
|
texture: &MetalTexture) {
|
||||||
|
render_command_encoder.set_fragment_texture(argument_index.main, Some(&texture.texture));
|
||||||
|
let sampler = &self.samplers[texture.sampling_flags.get().bits() as usize];
|
||||||
|
render_command_encoder.set_fragment_sampler_state(argument_index.sampler, Some(sampler));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_compute_texture_parameter(&self,
|
||||||
|
argument_index: MetalTextureIndex,
|
||||||
|
compute_command_encoder: &ComputeCommandEncoderRef,
|
||||||
|
texture: &MetalTexture) {
|
||||||
compute_command_encoder.set_texture(argument_index.main, Some(&texture.texture));
|
compute_command_encoder.set_texture(argument_index.main, Some(&texture.texture));
|
||||||
if let Some(sampler_index) = argument_index.sampler {
|
let sampler = &self.samplers[texture.sampling_flags.get().bits() as usize];
|
||||||
let sampler = &self.samplers[texture.sampling_flags.get().bits() as usize];
|
compute_command_encoder.set_sampler_state(argument_index.sampler, Some(sampler));
|
||||||
compute_command_encoder.set_sampler_state(sampler_index, Some(sampler));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_pipeline_color_attachment_for_render(
|
fn prepare_pipeline_color_attachment_for_render(
|
||||||
|
@ -1691,40 +1821,39 @@ impl StencilFuncExt for StencilFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
trait UniformDataExt {
|
trait UniformDataExt {
|
||||||
fn as_bytes(&self) -> Option<&[u8]>;
|
fn as_bytes(&self) -> &[u8];
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UniformDataExt for UniformData {
|
impl UniformDataExt for UniformData {
|
||||||
fn as_bytes(&self) -> Option<&[u8]> {
|
fn as_bytes(&self) -> &[u8] {
|
||||||
unsafe {
|
unsafe {
|
||||||
match *self {
|
match *self {
|
||||||
UniformData::TextureUnit(_) | UniformData::ImageUnit(_) => None,
|
|
||||||
UniformData::Float(ref data) => {
|
UniformData::Float(ref data) => {
|
||||||
Some(slice::from_raw_parts(data as *const f32 as *const u8, 4 * 1))
|
slice::from_raw_parts(data as *const f32 as *const u8, 4 * 1)
|
||||||
}
|
}
|
||||||
UniformData::IVec2(ref data) => {
|
UniformData::IVec2(ref data) => {
|
||||||
Some(slice::from_raw_parts(data as *const I32x2 as *const u8, 4 * 3))
|
slice::from_raw_parts(data as *const I32x2 as *const u8, 4 * 3)
|
||||||
}
|
}
|
||||||
UniformData::IVec3(ref data) => {
|
UniformData::IVec3(ref data) => {
|
||||||
Some(slice::from_raw_parts(data as *const i32 as *const u8, 4 * 3))
|
slice::from_raw_parts(data as *const i32 as *const u8, 4 * 3)
|
||||||
}
|
}
|
||||||
UniformData::Int(ref data) => {
|
UniformData::Int(ref data) => {
|
||||||
Some(slice::from_raw_parts(data as *const i32 as *const u8, 4 * 1))
|
slice::from_raw_parts(data as *const i32 as *const u8, 4 * 1)
|
||||||
}
|
}
|
||||||
UniformData::Mat2(ref data) => {
|
UniformData::Mat2(ref data) => {
|
||||||
Some(slice::from_raw_parts(data as *const F32x4 as *const u8, 4 * 4))
|
slice::from_raw_parts(data as *const F32x4 as *const u8, 4 * 4)
|
||||||
}
|
}
|
||||||
UniformData::Mat4(ref data) => {
|
UniformData::Mat4(ref data) => {
|
||||||
Some(slice::from_raw_parts(&data[0] as *const F32x4 as *const u8, 4 * 16))
|
slice::from_raw_parts(&data[0] as *const F32x4 as *const u8, 4 * 16)
|
||||||
}
|
}
|
||||||
UniformData::Vec2(ref data) => {
|
UniformData::Vec2(ref data) => {
|
||||||
Some(slice::from_raw_parts(data as *const F32x2 as *const u8, 4 * 2))
|
slice::from_raw_parts(data as *const F32x2 as *const u8, 4 * 2)
|
||||||
}
|
}
|
||||||
UniformData::Vec3(ref data) => {
|
UniformData::Vec3(ref data) => {
|
||||||
Some(slice::from_raw_parts(data as *const f32 as *const u8, 4 * 3))
|
slice::from_raw_parts(data as *const f32 as *const u8, 4 * 3)
|
||||||
}
|
}
|
||||||
UniformData::Vec4(ref data) => {
|
UniformData::Vec4(ref data) => {
|
||||||
Some(slice::from_raw_parts(data as *const F32x4 as *const u8, 4 * 4))
|
slice::from_raw_parts(data as *const F32x4 as *const u8, 4 * 4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
|
|
||||||
use crate::gpu::debug::DebugUIPresenter;
|
use crate::gpu::debug::DebugUIPresenter;
|
||||||
use crate::gpu::options::{DestFramebuffer, RendererOptions};
|
use crate::gpu::options::{DestFramebuffer, RendererOptions};
|
||||||
use crate::gpu::shaders::{BlitProgram, BlitVertexArray, ClearProgram, ClearVertexArray, ClipTileProgram, ClipTileVertexArray};
|
use crate::gpu::shaders::{BlitProgram, BlitVertexArray, ClearProgram, ClearVertexArray};
|
||||||
|
use crate::gpu::shaders::{ClipTileProgram, ClipTileVertexArray};
|
||||||
use crate::gpu::shaders::{CopyTileProgram, CopyTileVertexArray, FillProgram, FillVertexArray};
|
use crate::gpu::shaders::{CopyTileProgram, CopyTileVertexArray, FillProgram, FillVertexArray};
|
||||||
use crate::gpu::shaders::{MAX_FILLS_PER_BATCH, MAX_TILES_PER_BATCH, ReprojectionProgram};
|
use crate::gpu::shaders::{MAX_FILLS_PER_BATCH, MAX_TILES_PER_BATCH, ReprojectionProgram};
|
||||||
use crate::gpu::shaders::{ReprojectionVertexArray, StencilProgram, StencilVertexArray};
|
use crate::gpu::shaders::{ReprojectionVertexArray, StencilProgram, StencilVertexArray};
|
||||||
|
@ -34,9 +35,9 @@ use pathfinder_geometry::util;
|
||||||
use pathfinder_geometry::vector::{Vector2F, Vector2I, Vector4F, vec2f, vec2i};
|
use pathfinder_geometry::vector::{Vector2F, Vector2I, Vector4F, vec2f, vec2i};
|
||||||
use pathfinder_gpu::{BlendFactor, BlendOp, BlendState, BufferData, BufferTarget, BufferUploadMode};
|
use pathfinder_gpu::{BlendFactor, BlendOp, BlendState, BufferData, BufferTarget, BufferUploadMode};
|
||||||
use pathfinder_gpu::{ClearOps, ComputeDimensions, ComputeState, DepthFunc, DepthState, Device};
|
use pathfinder_gpu::{ClearOps, ComputeDimensions, ComputeState, DepthFunc, DepthState, Device};
|
||||||
use pathfinder_gpu::{ImageAccess, ImageBinding, Primitive, RenderOptions, RenderState};
|
use pathfinder_gpu::{ImageAccess, Primitive, RenderOptions, RenderState, RenderTarget};
|
||||||
use pathfinder_gpu::{RenderTarget, StencilFunc, StencilState, TextureDataRef};
|
use pathfinder_gpu::{StencilFunc, StencilState, TextureBinding, TextureDataRef, TextureFormat};
|
||||||
use pathfinder_gpu::{TextureFormat, UniformData};
|
use pathfinder_gpu::{UniformBinding, UniformData};
|
||||||
use pathfinder_resources::ResourceLoader;
|
use pathfinder_resources::ResourceLoader;
|
||||||
use pathfinder_simd::default::{F32x2, F32x4, I32x2};
|
use pathfinder_simd::default::{F32x2, F32x4, I32x2};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
@ -662,14 +663,13 @@ impl<D> Renderer<D> where D: Device {
|
||||||
program: &fill_raster_program.program,
|
program: &fill_raster_program.program,
|
||||||
vertex_array: &fill_vertex_array.vertex_array,
|
vertex_array: &fill_vertex_array.vertex_array,
|
||||||
primitive: Primitive::Triangles,
|
primitive: Primitive::Triangles,
|
||||||
textures: &[&self.area_lut_texture],
|
textures: &[(&fill_raster_program.area_lut_texture, &self.area_lut_texture)],
|
||||||
uniforms: &[
|
uniforms: &[
|
||||||
(&fill_raster_program.framebuffer_size_uniform,
|
(&fill_raster_program.framebuffer_size_uniform,
|
||||||
UniformData::Vec2(F32x2::new(MASK_FRAMEBUFFER_WIDTH as f32,
|
UniformData::Vec2(F32x2::new(MASK_FRAMEBUFFER_WIDTH as f32,
|
||||||
MASK_FRAMEBUFFER_HEIGHT as f32))),
|
MASK_FRAMEBUFFER_HEIGHT as f32))),
|
||||||
(&fill_raster_program.tile_size_uniform,
|
(&fill_raster_program.tile_size_uniform,
|
||||||
UniformData::Vec2(F32x2::new(TILE_WIDTH as f32, TILE_HEIGHT as f32))),
|
UniformData::Vec2(F32x2::new(TILE_WIDTH as f32, TILE_HEIGHT as f32))),
|
||||||
(&fill_raster_program.area_lut_uniform, UniformData::TextureUnit(0)),
|
|
||||||
],
|
],
|
||||||
images: &[],
|
images: &[],
|
||||||
viewport: mask_viewport,
|
viewport: mask_viewport,
|
||||||
|
@ -761,10 +761,7 @@ impl<D> Renderer<D> where D: Device {
|
||||||
&self.fill_tile_map,
|
&self.fill_tile_map,
|
||||||
BufferTarget::Storage);
|
BufferTarget::Storage);
|
||||||
|
|
||||||
let image_binding = ImageBinding {
|
let image_texture = self.device.framebuffer_texture(&alpha_tile_page.framebuffer);
|
||||||
texture: self.device.framebuffer_texture(&alpha_tile_page.framebuffer),
|
|
||||||
access: ImageAccess::Write,
|
|
||||||
};
|
|
||||||
|
|
||||||
let timer_query = self.timer_query_cache.alloc(&self.device);
|
let timer_query = self.timer_query_cache.alloc(&self.device);
|
||||||
self.device.begin_timer_query(&timer_query);
|
self.device.begin_timer_query(&timer_query);
|
||||||
|
@ -773,11 +770,9 @@ impl<D> Renderer<D> where D: Device {
|
||||||
let dimensions = ComputeDimensions { x: 1, y: 1, z: fill_tile_count as u32 };
|
let dimensions = ComputeDimensions { x: 1, y: 1, z: fill_tile_count as u32 };
|
||||||
self.device.dispatch_compute(dimensions, &ComputeState {
|
self.device.dispatch_compute(dimensions, &ComputeState {
|
||||||
program: &fill_compute_program.program,
|
program: &fill_compute_program.program,
|
||||||
textures: &[&self.area_lut_texture],
|
textures: &[(&fill_compute_program.area_lut_texture, &self.area_lut_texture)],
|
||||||
images: &[image_binding],
|
images: &[(&fill_compute_program.dest_image, image_texture, ImageAccess::Write)],
|
||||||
uniforms: &[
|
uniforms: &[
|
||||||
(&fill_compute_program.area_lut_uniform, UniformData::TextureUnit(0)),
|
|
||||||
(&fill_compute_program.dest_uniform, UniformData::ImageUnit(0)),
|
|
||||||
(&fill_compute_program.first_tile_index_uniform,
|
(&fill_compute_program.first_tile_index_uniform,
|
||||||
UniformData::Int(first_fill_tile as i32)),
|
UniformData::Int(first_fill_tile as i32)),
|
||||||
],
|
],
|
||||||
|
@ -845,9 +840,9 @@ impl<D> Renderer<D> where D: Device {
|
||||||
program: &self.tile_clip_program.program,
|
program: &self.tile_clip_program.program,
|
||||||
vertex_array: &self.back_frame.tile_clip_vertex_array.vertex_array,
|
vertex_array: &self.back_frame.tile_clip_vertex_array.vertex_array,
|
||||||
primitive: Primitive::Triangles,
|
primitive: Primitive::Triangles,
|
||||||
textures: &[src_texture],
|
textures: &[(&self.tile_clip_program.src_texture, src_texture)],
|
||||||
images: &[],
|
images: &[],
|
||||||
uniforms: &[(&self.tile_clip_program.src_uniform, UniformData::TextureUnit(0))],
|
uniforms: &[],
|
||||||
viewport: mask_viewport,
|
viewport: mask_viewport,
|
||||||
options: RenderOptions {
|
options: RenderOptions {
|
||||||
blend,
|
blend,
|
||||||
|
@ -893,7 +888,10 @@ impl<D> Renderer<D> where D: Device {
|
||||||
let timer_query = self.timer_query_cache.alloc(&self.device);
|
let timer_query = self.timer_query_cache.alloc(&self.device);
|
||||||
self.device.begin_timer_query(&timer_query);
|
self.device.begin_timer_query(&timer_query);
|
||||||
|
|
||||||
let mut textures = vec![&self.back_frame.texture_metadata_texture];
|
let mut textures = vec![
|
||||||
|
(&self.tile_program.texture_metadata_texture,
|
||||||
|
&self.back_frame.texture_metadata_texture),
|
||||||
|
];
|
||||||
let mut uniforms = vec![
|
let mut uniforms = vec![
|
||||||
(&self.tile_program.transform_uniform,
|
(&self.tile_program.transform_uniform,
|
||||||
UniformData::Mat4(self.tile_transform().to_columns())),
|
UniformData::Mat4(self.tile_transform().to_columns())),
|
||||||
|
@ -901,26 +899,23 @@ impl<D> Renderer<D> where D: Device {
|
||||||
UniformData::Vec2(F32x2::new(TILE_WIDTH as f32, TILE_HEIGHT as f32))),
|
UniformData::Vec2(F32x2::new(TILE_WIDTH as f32, TILE_HEIGHT as f32))),
|
||||||
(&self.tile_program.framebuffer_size_uniform,
|
(&self.tile_program.framebuffer_size_uniform,
|
||||||
UniformData::Vec2(draw_viewport.size().to_f32().0)),
|
UniformData::Vec2(draw_viewport.size().to_f32().0)),
|
||||||
(&self.tile_program.texture_metadata_uniform, UniformData::TextureUnit(0)),
|
|
||||||
(&self.tile_program.texture_metadata_size_uniform,
|
(&self.tile_program.texture_metadata_size_uniform,
|
||||||
UniformData::IVec2(I32x2::new(TEXTURE_METADATA_TEXTURE_WIDTH,
|
UniformData::IVec2(I32x2::new(TEXTURE_METADATA_TEXTURE_WIDTH,
|
||||||
TEXTURE_METADATA_TEXTURE_HEIGHT))),
|
TEXTURE_METADATA_TEXTURE_HEIGHT))),
|
||||||
];
|
];
|
||||||
|
|
||||||
if needs_readable_framebuffer {
|
if needs_readable_framebuffer {
|
||||||
uniforms.push((&self.tile_program.dest_texture_uniform,
|
textures.push((&self.tile_program.dest_texture,
|
||||||
UniformData::TextureUnit(textures.len() as u32)));
|
self.device
|
||||||
textures.push(self.device
|
.framebuffer_texture(&self.back_frame.dest_blend_framebuffer)));
|
||||||
.framebuffer_texture(&self.back_frame.dest_blend_framebuffer));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(alpha_tile_page) = self.back_frame.alpha_tile_pages.get(&tile_page) {
|
if let Some(alpha_tile_page) = self.back_frame.alpha_tile_pages.get(&tile_page) {
|
||||||
uniforms.push((&self.tile_program.mask_texture_0_uniform,
|
|
||||||
UniformData::TextureUnit(textures.len() as u32)));
|
|
||||||
uniforms.push((&self.tile_program.mask_texture_size_0_uniform,
|
uniforms.push((&self.tile_program.mask_texture_size_0_uniform,
|
||||||
UniformData::Vec2(F32x2::new(MASK_FRAMEBUFFER_WIDTH as f32,
|
UniformData::Vec2(F32x2::new(MASK_FRAMEBUFFER_WIDTH as f32,
|
||||||
MASK_FRAMEBUFFER_HEIGHT as f32))));
|
MASK_FRAMEBUFFER_HEIGHT as f32))));
|
||||||
textures.push(self.device.framebuffer_texture(&alpha_tile_page.framebuffer));
|
textures.push((&self.tile_program.mask_texture_0,
|
||||||
|
self.device.framebuffer_texture(&alpha_tile_page.framebuffer)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(pcwalton): Refactor.
|
// TODO(pcwalton): Refactor.
|
||||||
|
@ -930,12 +925,10 @@ impl<D> Renderer<D> where D: Device {
|
||||||
let color_texture_page = self.texture_page(color_texture.page);
|
let color_texture_page = self.texture_page(color_texture.page);
|
||||||
let color_texture_size = self.device.texture_size(color_texture_page).to_f32();
|
let color_texture_size = self.device.texture_size(color_texture_page).to_f32();
|
||||||
self.device.set_texture_sampling_mode(color_texture_page,
|
self.device.set_texture_sampling_mode(color_texture_page,
|
||||||
color_texture.sampling_flags);
|
color_texture.sampling_flags);
|
||||||
uniforms.push((&self.tile_program.color_texture_0_uniform,
|
textures.push((&self.tile_program.color_texture_0, color_texture_page));
|
||||||
UniformData::TextureUnit(textures.len() as u32)));
|
|
||||||
uniforms.push((&self.tile_program.color_texture_size_0_uniform,
|
uniforms.push((&self.tile_program.color_texture_size_0_uniform,
|
||||||
UniformData::Vec2(color_texture_size.0)));
|
UniformData::Vec2(color_texture_size.0)));
|
||||||
textures.push(color_texture_page);
|
|
||||||
|
|
||||||
ctrl |= color_texture.composite_op.to_combine_mode() <<
|
ctrl |= color_texture.composite_op.to_combine_mode() <<
|
||||||
COMBINER_CTRL_COLOR_COMBINE_SHIFT;
|
COMBINER_CTRL_COLOR_COMBINE_SHIFT;
|
||||||
|
@ -1022,9 +1015,7 @@ impl<D> Renderer<D> where D: Device {
|
||||||
};
|
};
|
||||||
let draw_texture = self.device.framebuffer_texture(&draw_framebuffer);
|
let draw_texture = self.device.framebuffer_texture(&draw_framebuffer);
|
||||||
|
|
||||||
uniforms.push((&self.tile_copy_program.src_uniform,
|
textures.push((&self.tile_copy_program.src_texture, draw_texture));
|
||||||
UniformData::TextureUnit(textures.len() as u32)));
|
|
||||||
textures.push(draw_texture);
|
|
||||||
uniforms.push((&self.tile_copy_program.framebuffer_size_uniform,
|
uniforms.push((&self.tile_copy_program.framebuffer_size_uniform,
|
||||||
UniformData::Vec2(draw_viewport.size().to_f32().0)));
|
UniformData::Vec2(draw_viewport.size().to_f32().0)));
|
||||||
|
|
||||||
|
@ -1106,14 +1097,13 @@ impl<D> Renderer<D> where D: Device {
|
||||||
program: &self.reprojection_program.program,
|
program: &self.reprojection_program.program,
|
||||||
vertex_array: &self.back_frame.reprojection_vertex_array.vertex_array,
|
vertex_array: &self.back_frame.reprojection_vertex_array.vertex_array,
|
||||||
primitive: Primitive::Triangles,
|
primitive: Primitive::Triangles,
|
||||||
textures: &[texture],
|
textures: &[(&self.reprojection_program.texture, texture)],
|
||||||
images: &[],
|
images: &[],
|
||||||
uniforms: &[
|
uniforms: &[
|
||||||
(&self.reprojection_program.old_transform_uniform,
|
(&self.reprojection_program.old_transform_uniform,
|
||||||
UniformData::from_transform_3d(old_transform)),
|
UniformData::from_transform_3d(old_transform)),
|
||||||
(&self.reprojection_program.new_transform_uniform,
|
(&self.reprojection_program.new_transform_uniform,
|
||||||
UniformData::from_transform_3d(new_transform)),
|
UniformData::from_transform_3d(new_transform)),
|
||||||
(&self.reprojection_program.texture_uniform, UniformData::TextureUnit(0)),
|
|
||||||
],
|
],
|
||||||
viewport: self.draw_viewport(),
|
viewport: self.draw_viewport(),
|
||||||
options: RenderOptions {
|
options: RenderOptions {
|
||||||
|
@ -1181,15 +1171,15 @@ impl<D> Renderer<D> where D: Device {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_uniforms_for_text_filter<'a>(&'a self,
|
fn set_uniforms_for_text_filter<'a>(
|
||||||
textures: &mut Vec<&'a D::Texture>,
|
&'a self,
|
||||||
uniforms: &mut Vec<(&'a D::Uniform, UniformData)>,
|
textures: &mut Vec<TextureBinding<'a, D::TextureParameter, D::Texture>>,
|
||||||
fg_color: ColorF,
|
uniforms: &mut Vec<UniformBinding<'a, D::Uniform>>,
|
||||||
bg_color: ColorF,
|
fg_color: ColorF,
|
||||||
defringing_kernel: Option<DefringingKernel>,
|
bg_color: ColorF,
|
||||||
gamma_correction: bool) {
|
defringing_kernel: Option<DefringingKernel>,
|
||||||
let gamma_lut_texture_unit = textures.len() as u32;
|
gamma_correction: bool) {
|
||||||
textures.push(&self.gamma_lut_texture);
|
textures.push((&self.tile_program.gamma_lut_texture, &self.gamma_lut_texture));
|
||||||
|
|
||||||
match defringing_kernel {
|
match defringing_kernel {
|
||||||
Some(ref kernel) => {
|
Some(ref kernel) => {
|
||||||
|
@ -1206,12 +1196,9 @@ impl<D> Renderer<D> where D: Device {
|
||||||
params_2.set_w(gamma_correction as i32 as f32);
|
params_2.set_w(gamma_correction as i32 as f32);
|
||||||
|
|
||||||
uniforms.extend_from_slice(&[
|
uniforms.extend_from_slice(&[
|
||||||
(&self.tile_program.gamma_lut_uniform,
|
|
||||||
UniformData::TextureUnit(gamma_lut_texture_unit)),
|
|
||||||
(&self.tile_program.filter_params_1_uniform, UniformData::Vec4(bg_color.0)),
|
(&self.tile_program.filter_params_1_uniform, UniformData::Vec4(bg_color.0)),
|
||||||
(&self.tile_program.filter_params_2_uniform, UniformData::Vec4(params_2)),
|
(&self.tile_program.filter_params_2_uniform, UniformData::Vec4(params_2)),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_uniforms_for_blur_filter<'a>(&'a self,
|
fn set_uniforms_for_blur_filter<'a>(&'a self,
|
||||||
|
@ -1279,9 +1266,9 @@ impl<D> Renderer<D> where D: Device {
|
||||||
|
|
||||||
let main_viewport = self.main_viewport();
|
let main_viewport = self.main_viewport();
|
||||||
|
|
||||||
let uniforms = [(&self.blit_program.src_uniform, UniformData::TextureUnit(0))];
|
|
||||||
let textures = [
|
let textures = [
|
||||||
(self.device.framebuffer_texture(&self.back_frame.intermediate_dest_framebuffer))
|
(&self.blit_program.src_texture,
|
||||||
|
self.device.framebuffer_texture(&self.back_frame.intermediate_dest_framebuffer))
|
||||||
];
|
];
|
||||||
|
|
||||||
self.device.draw_elements(6, &RenderState {
|
self.device.draw_elements(6, &RenderState {
|
||||||
|
@ -1291,7 +1278,7 @@ impl<D> Renderer<D> where D: Device {
|
||||||
primitive: Primitive::Triangles,
|
primitive: Primitive::Triangles,
|
||||||
textures: &textures[..],
|
textures: &textures[..],
|
||||||
images: &[],
|
images: &[],
|
||||||
uniforms: &uniforms[..],
|
uniforms: &[],
|
||||||
viewport: main_viewport,
|
viewport: main_viewport,
|
||||||
options: RenderOptions {
|
options: RenderOptions {
|
||||||
clear_ops: ClearOps {
|
clear_ops: ClearOps {
|
||||||
|
|
|
@ -355,14 +355,14 @@ impl<D> ClipTileVertexArray<D> where D: Device {
|
||||||
|
|
||||||
pub struct BlitProgram<D> where D: Device {
|
pub struct BlitProgram<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub program: D::Program,
|
||||||
pub src_uniform: D::Uniform,
|
pub src_texture: D::TextureParameter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> BlitProgram<D> where D: Device {
|
impl<D> BlitProgram<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> BlitProgram<D> {
|
pub fn new(device: &D, resources: &dyn ResourceLoader) -> BlitProgram<D> {
|
||||||
let program = device.create_raster_program(resources, "blit");
|
let program = device.create_raster_program(resources, "blit");
|
||||||
let src_uniform = device.get_uniform(&program, "Src");
|
let src_texture = device.get_texture_parameter(&program, "Src");
|
||||||
BlitProgram { program, src_uniform }
|
BlitProgram { program, src_texture }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,7 +406,7 @@ pub struct FillRasterProgram<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub program: D::Program,
|
||||||
pub framebuffer_size_uniform: D::Uniform,
|
pub framebuffer_size_uniform: D::Uniform,
|
||||||
pub tile_size_uniform: D::Uniform,
|
pub tile_size_uniform: D::Uniform,
|
||||||
pub area_lut_uniform: D::Uniform,
|
pub area_lut_texture: D::TextureParameter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> FillRasterProgram<D> where D: Device {
|
impl<D> FillRasterProgram<D> where D: Device {
|
||||||
|
@ -414,20 +414,20 @@ impl<D> FillRasterProgram<D> where D: Device {
|
||||||
let program = device.create_raster_program(resources, "fill");
|
let program = device.create_raster_program(resources, "fill");
|
||||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||||
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
||||||
let area_lut_uniform = device.get_uniform(&program, "AreaLUT");
|
let area_lut_texture = device.get_texture_parameter(&program, "AreaLUT");
|
||||||
FillRasterProgram {
|
FillRasterProgram {
|
||||||
program,
|
program,
|
||||||
framebuffer_size_uniform,
|
framebuffer_size_uniform,
|
||||||
tile_size_uniform,
|
tile_size_uniform,
|
||||||
area_lut_uniform,
|
area_lut_texture,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FillComputeProgram<D> where D: Device {
|
pub struct FillComputeProgram<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub program: D::Program,
|
||||||
pub dest_uniform: D::Uniform,
|
pub dest_image: D::ImageParameter,
|
||||||
pub area_lut_uniform: D::Uniform,
|
pub area_lut_texture: D::TextureParameter,
|
||||||
pub first_tile_index_uniform: D::Uniform,
|
pub first_tile_index_uniform: D::Uniform,
|
||||||
pub fills_storage_buffer: D::StorageBuffer,
|
pub fills_storage_buffer: D::StorageBuffer,
|
||||||
pub next_fills_storage_buffer: D::StorageBuffer,
|
pub next_fills_storage_buffer: D::StorageBuffer,
|
||||||
|
@ -440,8 +440,8 @@ impl<D> FillComputeProgram<D> where D: Device {
|
||||||
let local_size = ComputeDimensions { x: TILE_WIDTH, y: TILE_HEIGHT / 4, z: 1 };
|
let local_size = ComputeDimensions { x: TILE_WIDTH, y: TILE_HEIGHT / 4, z: 1 };
|
||||||
device.set_compute_program_local_size(&mut program, local_size);
|
device.set_compute_program_local_size(&mut program, local_size);
|
||||||
|
|
||||||
let dest_uniform = device.get_uniform(&program, "Dest");
|
let dest_image = device.get_image_parameter(&program, "Dest");
|
||||||
let area_lut_uniform = device.get_uniform(&program, "AreaLUT");
|
let area_lut_texture = device.get_texture_parameter(&program, "AreaLUT");
|
||||||
let first_tile_index_uniform = device.get_uniform(&program, "FirstTileIndex");
|
let first_tile_index_uniform = device.get_uniform(&program, "FirstTileIndex");
|
||||||
let fills_storage_buffer = device.get_storage_buffer(&program, "Fills", 0);
|
let fills_storage_buffer = device.get_storage_buffer(&program, "Fills", 0);
|
||||||
let next_fills_storage_buffer = device.get_storage_buffer(&program, "NextFills", 1);
|
let next_fills_storage_buffer = device.get_storage_buffer(&program, "NextFills", 1);
|
||||||
|
@ -449,8 +449,8 @@ impl<D> FillComputeProgram<D> where D: Device {
|
||||||
|
|
||||||
FillComputeProgram {
|
FillComputeProgram {
|
||||||
program,
|
program,
|
||||||
dest_uniform,
|
dest_image,
|
||||||
area_lut_uniform,
|
area_lut_texture,
|
||||||
first_tile_index_uniform,
|
first_tile_index_uniform,
|
||||||
fills_storage_buffer,
|
fills_storage_buffer,
|
||||||
next_fills_storage_buffer,
|
next_fills_storage_buffer,
|
||||||
|
@ -463,15 +463,15 @@ pub struct TileProgram<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub program: D::Program,
|
||||||
pub transform_uniform: D::Uniform,
|
pub transform_uniform: D::Uniform,
|
||||||
pub tile_size_uniform: D::Uniform,
|
pub tile_size_uniform: D::Uniform,
|
||||||
pub texture_metadata_uniform: D::Uniform,
|
pub texture_metadata_texture: D::TextureParameter,
|
||||||
pub texture_metadata_size_uniform: D::Uniform,
|
pub texture_metadata_size_uniform: D::Uniform,
|
||||||
pub dest_texture_uniform: D::Uniform,
|
pub dest_texture: D::TextureParameter,
|
||||||
pub color_texture_0_uniform: D::Uniform,
|
pub color_texture_0: D::TextureParameter,
|
||||||
pub color_texture_size_0_uniform: D::Uniform,
|
pub color_texture_size_0_uniform: D::Uniform,
|
||||||
pub color_texture_1_uniform: D::Uniform,
|
pub color_texture_1: D::TextureParameter,
|
||||||
pub mask_texture_0_uniform: D::Uniform,
|
pub mask_texture_0: D::TextureParameter,
|
||||||
pub mask_texture_size_0_uniform: D::Uniform,
|
pub mask_texture_size_0_uniform: D::Uniform,
|
||||||
pub gamma_lut_uniform: D::Uniform,
|
pub gamma_lut_texture: D::TextureParameter,
|
||||||
pub filter_params_0_uniform: D::Uniform,
|
pub filter_params_0_uniform: D::Uniform,
|
||||||
pub filter_params_1_uniform: D::Uniform,
|
pub filter_params_1_uniform: D::Uniform,
|
||||||
pub filter_params_2_uniform: D::Uniform,
|
pub filter_params_2_uniform: D::Uniform,
|
||||||
|
@ -484,15 +484,15 @@ impl<D> TileProgram<D> where D: Device {
|
||||||
let program = device.create_raster_program(resources, "tile");
|
let program = device.create_raster_program(resources, "tile");
|
||||||
let transform_uniform = device.get_uniform(&program, "Transform");
|
let transform_uniform = device.get_uniform(&program, "Transform");
|
||||||
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
||||||
let texture_metadata_uniform = device.get_uniform(&program, "TextureMetadata");
|
let texture_metadata_texture = device.get_texture_parameter(&program, "TextureMetadata");
|
||||||
let texture_metadata_size_uniform = device.get_uniform(&program, "TextureMetadataSize");
|
let texture_metadata_size_uniform = device.get_uniform(&program, "TextureMetadataSize");
|
||||||
let dest_texture_uniform = device.get_uniform(&program, "DestTexture");
|
let dest_texture = device.get_texture_parameter(&program, "DestTexture");
|
||||||
let color_texture_0_uniform = device.get_uniform(&program, "ColorTexture0");
|
let color_texture_0 = device.get_texture_parameter(&program, "ColorTexture0");
|
||||||
let color_texture_size_0_uniform = device.get_uniform(&program, "ColorTextureSize0");
|
let color_texture_size_0_uniform = device.get_uniform(&program, "ColorTextureSize0");
|
||||||
let color_texture_1_uniform = device.get_uniform(&program, "ColorTexture1");
|
let color_texture_1 = device.get_texture_parameter(&program, "ColorTexture1");
|
||||||
let mask_texture_0_uniform = device.get_uniform(&program, "MaskTexture0");
|
let mask_texture_0 = device.get_texture_parameter(&program, "MaskTexture0");
|
||||||
let mask_texture_size_0_uniform = device.get_uniform(&program, "MaskTextureSize0");
|
let mask_texture_size_0_uniform = device.get_uniform(&program, "MaskTextureSize0");
|
||||||
let gamma_lut_uniform = device.get_uniform(&program, "GammaLUT");
|
let gamma_lut_texture = device.get_texture_parameter(&program, "GammaLUT");
|
||||||
let filter_params_0_uniform = device.get_uniform(&program, "FilterParams0");
|
let filter_params_0_uniform = device.get_uniform(&program, "FilterParams0");
|
||||||
let filter_params_1_uniform = device.get_uniform(&program, "FilterParams1");
|
let filter_params_1_uniform = device.get_uniform(&program, "FilterParams1");
|
||||||
let filter_params_2_uniform = device.get_uniform(&program, "FilterParams2");
|
let filter_params_2_uniform = device.get_uniform(&program, "FilterParams2");
|
||||||
|
@ -502,15 +502,15 @@ impl<D> TileProgram<D> where D: Device {
|
||||||
program,
|
program,
|
||||||
transform_uniform,
|
transform_uniform,
|
||||||
tile_size_uniform,
|
tile_size_uniform,
|
||||||
texture_metadata_uniform,
|
texture_metadata_texture,
|
||||||
texture_metadata_size_uniform,
|
texture_metadata_size_uniform,
|
||||||
dest_texture_uniform,
|
dest_texture,
|
||||||
color_texture_0_uniform,
|
color_texture_0,
|
||||||
color_texture_size_0_uniform,
|
color_texture_size_0_uniform,
|
||||||
color_texture_1_uniform,
|
color_texture_1,
|
||||||
mask_texture_0_uniform,
|
mask_texture_0,
|
||||||
mask_texture_size_0_uniform,
|
mask_texture_size_0_uniform,
|
||||||
gamma_lut_uniform,
|
gamma_lut_texture,
|
||||||
filter_params_0_uniform,
|
filter_params_0_uniform,
|
||||||
filter_params_1_uniform,
|
filter_params_1_uniform,
|
||||||
filter_params_2_uniform,
|
filter_params_2_uniform,
|
||||||
|
@ -525,7 +525,7 @@ pub struct CopyTileProgram<D> where D: Device {
|
||||||
pub transform_uniform: D::Uniform,
|
pub transform_uniform: D::Uniform,
|
||||||
pub tile_size_uniform: D::Uniform,
|
pub tile_size_uniform: D::Uniform,
|
||||||
pub framebuffer_size_uniform: D::Uniform,
|
pub framebuffer_size_uniform: D::Uniform,
|
||||||
pub src_uniform: D::Uniform,
|
pub src_texture: D::TextureParameter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> CopyTileProgram<D> where D: Device {
|
impl<D> CopyTileProgram<D> where D: Device {
|
||||||
|
@ -534,27 +534,27 @@ impl<D> CopyTileProgram<D> where D: Device {
|
||||||
let transform_uniform = device.get_uniform(&program, "Transform");
|
let transform_uniform = device.get_uniform(&program, "Transform");
|
||||||
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
||||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||||
let src_uniform = device.get_uniform(&program, "Src");
|
let src_texture = device.get_texture_parameter(&program, "Src");
|
||||||
CopyTileProgram {
|
CopyTileProgram {
|
||||||
program,
|
program,
|
||||||
transform_uniform,
|
transform_uniform,
|
||||||
tile_size_uniform,
|
tile_size_uniform,
|
||||||
framebuffer_size_uniform,
|
framebuffer_size_uniform,
|
||||||
src_uniform,
|
src_texture,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ClipTileProgram<D> where D: Device {
|
pub struct ClipTileProgram<D> where D: Device {
|
||||||
pub program: D::Program,
|
pub program: D::Program,
|
||||||
pub src_uniform: D::Uniform,
|
pub src_texture: D::TextureParameter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ClipTileProgram<D> where D: Device {
|
impl<D> ClipTileProgram<D> where D: Device {
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ClipTileProgram<D> {
|
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ClipTileProgram<D> {
|
||||||
let program = device.create_raster_program(resources, "tile_clip");
|
let program = device.create_raster_program(resources, "tile_clip");
|
||||||
let src_uniform = device.get_uniform(&program, "Src");
|
let src_texture = device.get_texture_parameter(&program, "Src");
|
||||||
ClipTileProgram { program, src_uniform }
|
ClipTileProgram { program, src_texture }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,32 +611,20 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ReprojectionProgram<D>
|
pub struct ReprojectionProgram<D> where D: Device {
|
||||||
where
|
|
||||||
D: Device,
|
|
||||||
{
|
|
||||||
pub program: D::Program,
|
pub program: D::Program,
|
||||||
pub old_transform_uniform: D::Uniform,
|
pub old_transform_uniform: D::Uniform,
|
||||||
pub new_transform_uniform: D::Uniform,
|
pub new_transform_uniform: D::Uniform,
|
||||||
pub texture_uniform: D::Uniform,
|
pub texture: D::TextureParameter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ReprojectionProgram<D>
|
impl<D> ReprojectionProgram<D> where D: Device {
|
||||||
where
|
|
||||||
D: Device,
|
|
||||||
{
|
|
||||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ReprojectionProgram<D> {
|
pub fn new(device: &D, resources: &dyn ResourceLoader) -> ReprojectionProgram<D> {
|
||||||
let program = device.create_raster_program(resources, "reproject");
|
let program = device.create_raster_program(resources, "reproject");
|
||||||
let old_transform_uniform = device.get_uniform(&program, "OldTransform");
|
let old_transform_uniform = device.get_uniform(&program, "OldTransform");
|
||||||
let new_transform_uniform = device.get_uniform(&program, "NewTransform");
|
let new_transform_uniform = device.get_uniform(&program, "NewTransform");
|
||||||
let texture_uniform = device.get_uniform(&program, "Texture");
|
let texture = device.get_texture_parameter(&program, "Texture");
|
||||||
|
ReprojectionProgram { program, old_transform_uniform, new_transform_uniform, texture }
|
||||||
ReprojectionProgram {
|
|
||||||
program,
|
|
||||||
old_transform_uniform,
|
|
||||||
new_transform_uniform,
|
|
||||||
texture_uniform,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -412,13 +412,12 @@ impl<D> UIPresenter<D> where D: Device {
|
||||||
program: &self.texture_program.program,
|
program: &self.texture_program.program,
|
||||||
vertex_array: &self.texture_vertex_array.vertex_array,
|
vertex_array: &self.texture_vertex_array.vertex_array,
|
||||||
primitive: Primitive::Triangles,
|
primitive: Primitive::Triangles,
|
||||||
textures: &[&texture],
|
textures: &[(&self.texture_program.texture, &texture)],
|
||||||
images: &[],
|
images: &[],
|
||||||
uniforms: &[
|
uniforms: &[
|
||||||
(&self.texture_program.framebuffer_size_uniform,
|
(&self.texture_program.framebuffer_size_uniform,
|
||||||
UniformData::Vec2(self.framebuffer_size.0.to_f32x2())),
|
UniformData::Vec2(self.framebuffer_size.0.to_f32x2())),
|
||||||
(&self.texture_program.color_uniform, get_color_uniform(color)),
|
(&self.texture_program.color_uniform, get_color_uniform(color)),
|
||||||
(&self.texture_program.texture_uniform, UniformData::TextureUnit(0)),
|
|
||||||
(&self.texture_program.texture_size_uniform,
|
(&self.texture_program.texture_size_uniform,
|
||||||
UniformData::Vec2(device.texture_size(&texture).0.to_f32x2()))
|
UniformData::Vec2(device.texture_size(&texture).0.to_f32x2()))
|
||||||
],
|
],
|
||||||
|
@ -566,8 +565,8 @@ struct DebugTextureProgram<D> where D: Device {
|
||||||
program: D::Program,
|
program: D::Program,
|
||||||
framebuffer_size_uniform: D::Uniform,
|
framebuffer_size_uniform: D::Uniform,
|
||||||
texture_size_uniform: D::Uniform,
|
texture_size_uniform: D::Uniform,
|
||||||
texture_uniform: D::Uniform,
|
|
||||||
color_uniform: D::Uniform,
|
color_uniform: D::Uniform,
|
||||||
|
texture: D::TextureParameter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> DebugTextureProgram<D> where D: Device {
|
impl<D> DebugTextureProgram<D> where D: Device {
|
||||||
|
@ -575,14 +574,14 @@ impl<D> DebugTextureProgram<D> where D: Device {
|
||||||
let program = device.create_raster_program(resources, "debug_texture");
|
let program = device.create_raster_program(resources, "debug_texture");
|
||||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||||
let texture_size_uniform = device.get_uniform(&program, "TextureSize");
|
let texture_size_uniform = device.get_uniform(&program, "TextureSize");
|
||||||
let texture_uniform = device.get_uniform(&program, "Texture");
|
|
||||||
let color_uniform = device.get_uniform(&program, "Color");
|
let color_uniform = device.get_uniform(&program, "Color");
|
||||||
|
let texture = device.get_texture_parameter(&program, "Texture");
|
||||||
DebugTextureProgram {
|
DebugTextureProgram {
|
||||||
program,
|
program,
|
||||||
framebuffer_size_uniform,
|
framebuffer_size_uniform,
|
||||||
texture_size_uniform,
|
texture_size_uniform,
|
||||||
texture_uniform,
|
|
||||||
color_uniform,
|
color_uniform,
|
||||||
|
texture,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,13 @@ extern crate log;
|
||||||
use pathfinder_geometry::rect::RectI;
|
use pathfinder_geometry::rect::RectI;
|
||||||
use pathfinder_geometry::vector::Vector2I;
|
use pathfinder_geometry::vector::Vector2I;
|
||||||
use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, BufferUploadMode, ClearOps};
|
use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, BufferUploadMode, ClearOps};
|
||||||
use pathfinder_gpu::{ComputeDimensions, ComputeState, DepthFunc, Device, FeatureLevel, Primitive};
|
use pathfinder_gpu::{ComputeDimensions, ComputeState, DepthFunc, Device, FeatureLevel};
|
||||||
use pathfinder_gpu::{ProgramKind, RenderOptions, RenderState, RenderTarget, ShaderKind};
|
use pathfinder_gpu::{ImageBinding, Primitive, ProgramKind, RenderOptions, RenderState};
|
||||||
use pathfinder_gpu::{StencilFunc, TextureData, TextureDataRef, TextureFormat};
|
use pathfinder_gpu::{RenderTarget, ShaderKind, StencilFunc, TextureBinding, TextureData};
|
||||||
use pathfinder_gpu::{TextureSamplingFlags, UniformData, VertexAttrClass};
|
use pathfinder_gpu::{TextureDataRef, TextureFormat, TextureSamplingFlags, UniformData};
|
||||||
use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType};
|
use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
|
||||||
use pathfinder_resources::ResourceLoader;
|
use pathfinder_resources::ResourceLoader;
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -170,12 +171,9 @@ impl WebGlDevice {
|
||||||
self.context.uniform3i(location, data[0], data[1], data[2]);
|
self.context.uniform3i(location, data[0], data[1], data[2]);
|
||||||
self.ck();
|
self.ck();
|
||||||
}
|
}
|
||||||
UniformData::TextureUnit(unit) | UniformData::ImageUnit(unit) => {
|
|
||||||
self.context.uniform1i(location, unit as i32);
|
|
||||||
self.ck();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_render_state(&self, render_state: &RenderState<WebGlDevice>) {
|
fn set_render_state(&self, render_state: &RenderState<WebGlDevice>) {
|
||||||
self.bind_render_target(render_state.target);
|
self.bind_render_target(render_state.target);
|
||||||
|
|
||||||
|
@ -187,13 +185,12 @@ impl WebGlDevice {
|
||||||
self.clear(&render_state.options.clear_ops);
|
self.clear(&render_state.options.clear_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.context
|
self.context.use_program(Some(&render_state.program.gl_program));
|
||||||
.use_program(Some(&render_state.program.gl_program));
|
self.context.bind_vertex_array(Some(&render_state.vertex_array.gl_vertex_array));
|
||||||
self.context
|
|
||||||
.bind_vertex_array(Some(&render_state.vertex_array.gl_vertex_array));
|
self.bind_textures_and_images(&render_state.program,
|
||||||
for (texture_unit, texture) in render_state.textures.iter().enumerate() {
|
&render_state.textures,
|
||||||
self.bind_texture(texture, texture_unit as u32);
|
&render_state.images);
|
||||||
}
|
|
||||||
|
|
||||||
for (uniform, data) in render_state.uniforms {
|
for (uniform, data) in render_state.uniforms {
|
||||||
self.set_uniform(uniform, data);
|
self.set_uniform(uniform, data);
|
||||||
|
@ -201,6 +198,22 @@ impl WebGlDevice {
|
||||||
self.set_render_options(&render_state.options);
|
self.set_render_options(&render_state.options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bind_textures_and_images(
|
||||||
|
&self,
|
||||||
|
program: &WebGlProgram,
|
||||||
|
texture_bindings: &[TextureBinding<WebGlTextureParameter, WebGlTexture>],
|
||||||
|
_: &[ImageBinding<(), WebGlTexture>]) {
|
||||||
|
for &(texture_parameter, texture) in texture_bindings {
|
||||||
|
self.bind_texture(texture, texture_parameter.texture_unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
let parameters = program.parameters.borrow();
|
||||||
|
for (texture_unit, uniform) in parameters.textures.iter().enumerate() {
|
||||||
|
self.context.uniform1i(uniform.location.as_ref(), texture_unit as i32);
|
||||||
|
self.ck();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_render_options(&self, render_options: &RenderOptions) {
|
fn set_render_options(&self, render_options: &RenderOptions) {
|
||||||
match render_options.blend {
|
match render_options.blend {
|
||||||
None => {
|
None => {
|
||||||
|
@ -415,11 +428,13 @@ impl Device for WebGlDevice {
|
||||||
type Buffer = WebGlBuffer;
|
type Buffer = WebGlBuffer;
|
||||||
type Fence = ();
|
type Fence = ();
|
||||||
type Framebuffer = WebGlFramebuffer;
|
type Framebuffer = WebGlFramebuffer;
|
||||||
|
type ImageParameter = ();
|
||||||
type Program = WebGlProgram;
|
type Program = WebGlProgram;
|
||||||
type Shader = WebGlShader;
|
type Shader = WebGlShader;
|
||||||
type StorageBuffer = ();
|
type StorageBuffer = ();
|
||||||
type Texture = WebGlTexture;
|
type Texture = WebGlTexture;
|
||||||
type TextureDataReceiver = ();
|
type TextureDataReceiver = ();
|
||||||
|
type TextureParameter = WebGlTextureParameter;
|
||||||
type TimerQuery = WebGlTimerQuery;
|
type TimerQuery = WebGlTimerQuery;
|
||||||
type Uniform = WebGlUniform;
|
type Uniform = WebGlUniform;
|
||||||
type VertexArray = WebGlVertexArray;
|
type VertexArray = WebGlVertexArray;
|
||||||
|
@ -566,9 +581,12 @@ impl Device for WebGlDevice {
|
||||||
panic!("Program {:?} linking failed", name);
|
panic!("Program {:?} linking failed", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let parameters = WebGlProgramParameters { textures: vec![] };
|
||||||
|
|
||||||
WebGlProgram {
|
WebGlProgram {
|
||||||
context: self.context.clone(),
|
context: self.context.clone(),
|
||||||
gl_program,
|
gl_program,
|
||||||
|
parameters: RefCell::new(parameters),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,13 +614,29 @@ impl Device for WebGlDevice {
|
||||||
|
|
||||||
fn get_uniform(&self, program: &WebGlProgram, name: &str) -> WebGlUniform {
|
fn get_uniform(&self, program: &WebGlProgram, name: &str) -> WebGlUniform {
|
||||||
let name = format!("u{}", name);
|
let name = format!("u{}", name);
|
||||||
let location = self
|
let location = self.context.get_uniform_location(&program.gl_program, &name);
|
||||||
.context
|
|
||||||
.get_uniform_location(&program.gl_program, &name);
|
|
||||||
self.ck();
|
self.ck();
|
||||||
WebGlUniform { location: location }
|
WebGlUniform { location: location }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_texture_parameter(&self, program: &WebGlProgram, name: &str) -> WebGlTextureParameter {
|
||||||
|
let uniform = self.get_uniform(program, name);
|
||||||
|
let mut parameters = program.parameters.borrow_mut();
|
||||||
|
let index = match parameters.textures.iter().position(|u| *u == uniform) {
|
||||||
|
Some(index) => index,
|
||||||
|
None => {
|
||||||
|
let index = parameters.textures.len();
|
||||||
|
parameters.textures.push(uniform.clone());
|
||||||
|
index
|
||||||
|
}
|
||||||
|
};
|
||||||
|
WebGlTextureParameter { uniform, texture_unit: index as u32 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_image_parameter(&self, _: &WebGlProgram, _: &str) {
|
||||||
|
// TODO(pcwalton)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_storage_buffer(&self, _: &Self::Program, _: &str, _: u32) {
|
fn get_storage_buffer(&self, _: &Self::Program, _: &str, _: u32) {
|
||||||
// TODO(pcwalton)
|
// TODO(pcwalton)
|
||||||
}
|
}
|
||||||
|
@ -988,14 +1022,21 @@ impl Drop for WebGlBuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct WebGlUniform {
|
pub struct WebGlUniform {
|
||||||
location: Option<web_sys::WebGlUniformLocation>,
|
location: Option<web_sys::WebGlUniformLocation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct WebGlTextureParameter {
|
||||||
|
uniform: WebGlUniform,
|
||||||
|
texture_unit: u32,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct WebGlProgram {
|
pub struct WebGlProgram {
|
||||||
context: web_sys::WebGl2RenderingContext,
|
context: web_sys::WebGl2RenderingContext,
|
||||||
pub gl_program: web_sys::WebGlProgram,
|
pub gl_program: web_sys::WebGlProgram,
|
||||||
|
parameters: RefCell<WebGlProgramParameters>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for WebGlProgram {
|
impl Drop for WebGlProgram {
|
||||||
|
@ -1004,6 +1045,11 @@ impl Drop for WebGlProgram {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct WebGlProgramParameters {
|
||||||
|
// Mapping from texture unit number to uniform location.
|
||||||
|
textures: Vec<WebGlUniform>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct WebGlShader {
|
pub struct WebGlShader {
|
||||||
gl_shader: web_sys::WebGlShader,
|
gl_shader: web_sys::WebGlShader,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue