mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-21 22:34:43 +00:00
refine shaders proc macro api (#1091)
macro renamed from `vulkano_shader!` to `shader!` leave it up to the user to put it in a module
This commit is contained in:
parent
2153177210
commit
c57289f536
@ -4,11 +4,11 @@
|
|||||||
+ `instance::Features` -> `device::Features`
|
+ `instance::Features` -> `device::Features`
|
||||||
+ `instance::DeviceExtensions` -> `device::DeviceExtensions`
|
+ `instance::DeviceExtensions` -> `device::DeviceExtensions`
|
||||||
+ `instance::RawDeviceExtensions` -> `device::RawDeviceExtensions`
|
+ `instance::RawDeviceExtensions` -> `device::RawDeviceExtensions`
|
||||||
- Added `vulkano_shaders::vulkano_shader` proc macro, use this instead of `vulkano_shader_deriver::VulkanoShaders`.
|
- Added `vulkano_shaders::shader!` proc macro, use this instead of `vulkano_shader_deriver::VulkanoShaders`.
|
||||||
- The entire `vulkano_shader_derive` crate is deprecated.
|
- The entire `vulkano_shader_derive` crate is deprecated.
|
||||||
- `vulkano_shaders::{reflect, compile, Error}` are no longer public.
|
- `vulkano_shaders::{reflect, compile, Error}` are no longer public.
|
||||||
- Removed mir support, as it is being removed from the vulkan spec.
|
|
||||||
- Remove vulkano_shaders::build_glsl_shaders
|
- Remove vulkano_shaders::build_glsl_shaders
|
||||||
|
- Removed mir support, as it is being removed from the vulkan spec.
|
||||||
- Split `PersistentDescriptorSetError::MissingUsage` into `MissingImageUsage` and `MissingBufferUsage`
|
- Split `PersistentDescriptorSetError::MissingUsage` into `MissingImageUsage` and `MissingBufferUsage`
|
||||||
each with a matching enum indicating the usage that was missing.
|
each with a matching enum indicating the usage that was missing.
|
||||||
- Fix instance_count when using draw_index with instance buffers
|
- Fix instance_count when using draw_index with instance buffers
|
||||||
|
@ -150,7 +150,7 @@ If your change adds, removes or modifies a trait or a function, please add an en
|
|||||||
This repository contains six libraries:
|
This repository contains six libraries:
|
||||||
|
|
||||||
- `vulkano` is the main one.
|
- `vulkano` is the main one.
|
||||||
- `vulkano-shaders` Provides the `vulkano_shader!` macro for compiling glsl shaders.
|
- `vulkano-shaders` Provides the `shader!` macro for compiling glsl shaders.
|
||||||
- `vulkano-win` provides a safe link between vulkano and the `winit` library which can create
|
- `vulkano-win` provides a safe link between vulkano and the `winit` library which can create
|
||||||
a window to render to.
|
a window to render to.
|
||||||
- `vk-sys` contains raw bindings for Vulkan. You can use it even if you don't care about vulkano.
|
- `vk-sys` contains raw bindings for Vulkan. You can use it even if you don't care about vulkano.
|
||||||
|
@ -28,14 +28,13 @@ use vulkano::instance::InstanceExtensions;
|
|||||||
use vulkano::pipeline::ComputePipeline;
|
use vulkano::pipeline::ComputePipeline;
|
||||||
use vulkano::sync::now;
|
use vulkano::sync::now;
|
||||||
use vulkano::sync::GpuFuture;
|
use vulkano::sync::GpuFuture;
|
||||||
use vulkano_shaders::vulkano_shader;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
vulkano_shader!{
|
mod cs {
|
||||||
mod_name: cs,
|
vulkano_shaders::shader!{
|
||||||
ty: "compute",
|
ty: "compute",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
|
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
@ -48,6 +47,7 @@ void main() {
|
|||||||
uint idx = gl_GlobalInvocationID.x;
|
uint idx = gl_GlobalInvocationID.x;
|
||||||
data.data[idx] *= 12;
|
data.data[idx] *= 12;
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -23,7 +23,6 @@ use vulkano::pipeline::blend::BlendOp;
|
|||||||
use vulkano::pipeline::GraphicsPipeline;
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
use vulkano::pipeline::GraphicsPipelineAbstract;
|
use vulkano::pipeline::GraphicsPipelineAbstract;
|
||||||
use vulkano::pipeline::viewport::Viewport;
|
use vulkano::pipeline::viewport::Viewport;
|
||||||
use vulkano_shaders::vulkano_shader;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -143,10 +142,10 @@ struct Vertex {
|
|||||||
}
|
}
|
||||||
impl_vertex!(Vertex, position);
|
impl_vertex!(Vertex, position);
|
||||||
|
|
||||||
vulkano_shader!{
|
mod vs {
|
||||||
mod_name: vs,
|
vulkano_shaders::shader!{
|
||||||
ty: "vertex",
|
ty: "vertex",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec2 position;
|
layout(location = 0) in vec2 position;
|
||||||
@ -154,12 +153,13 @@ layout(location = 0) in vec2 position;
|
|||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(position, 0.0, 1.0);
|
gl_Position = vec4(position, 0.0, 1.0);
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkano_shader!{
|
mod fs {
|
||||||
mod_name: fs,
|
vulkano_shaders::shader!{
|
||||||
ty: "fragment",
|
ty: "fragment",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
// The `color_input` parameter of the `draw` method.
|
// The `color_input` parameter of the `draw` method.
|
||||||
@ -178,4 +178,5 @@ void main() {
|
|||||||
f_color.rgb = push_constants.color.rgb * in_diffuse;
|
f_color.rgb = push_constants.color.rgb * in_diffuse;
|
||||||
f_color.a = 1.0;
|
f_color.a = 1.0;
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ use vulkano::pipeline::blend::BlendOp;
|
|||||||
use vulkano::pipeline::GraphicsPipeline;
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
use vulkano::pipeline::GraphicsPipelineAbstract;
|
use vulkano::pipeline::GraphicsPipelineAbstract;
|
||||||
use vulkano::pipeline::viewport::Viewport;
|
use vulkano::pipeline::viewport::Viewport;
|
||||||
use vulkano_shaders::vulkano_shader;
|
|
||||||
use cgmath::Vector3;
|
use cgmath::Vector3;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -155,10 +154,10 @@ struct Vertex {
|
|||||||
}
|
}
|
||||||
impl_vertex!(Vertex, position);
|
impl_vertex!(Vertex, position);
|
||||||
|
|
||||||
vulkano_shader!{
|
mod vs {
|
||||||
mod_name: vs,
|
vulkano_shaders::shader!{
|
||||||
ty: "vertex",
|
ty: "vertex",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec2 position;
|
layout(location = 0) in vec2 position;
|
||||||
@ -166,12 +165,13 @@ layout(location = 0) in vec2 position;
|
|||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(position, 0.0, 1.0);
|
gl_Position = vec4(position, 0.0, 1.0);
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkano_shader!{
|
mod fs {
|
||||||
mod_name: fs,
|
vulkano_shaders::shader!{
|
||||||
ty: "fragment",
|
ty: "fragment",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
// The `color_input` parameter of the `draw` method.
|
// The `color_input` parameter of the `draw` method.
|
||||||
@ -201,4 +201,5 @@ void main() {
|
|||||||
f_color.rgb = light_percent * push_constants.color.rgb * in_diffuse;
|
f_color.rgb = light_percent * push_constants.color.rgb * in_diffuse;
|
||||||
f_color.a = 1.0;
|
f_color.a = 1.0;
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ use vulkano::pipeline::blend::BlendOp;
|
|||||||
use vulkano::pipeline::GraphicsPipeline;
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
use vulkano::pipeline::GraphicsPipelineAbstract;
|
use vulkano::pipeline::GraphicsPipelineAbstract;
|
||||||
use vulkano::pipeline::viewport::Viewport;
|
use vulkano::pipeline::viewport::Viewport;
|
||||||
use vulkano_shaders::vulkano_shader;
|
|
||||||
use cgmath::Matrix4;
|
use cgmath::Matrix4;
|
||||||
use cgmath::Vector3;
|
use cgmath::Vector3;
|
||||||
|
|
||||||
@ -169,10 +168,10 @@ struct Vertex {
|
|||||||
}
|
}
|
||||||
impl_vertex!(Vertex, position);
|
impl_vertex!(Vertex, position);
|
||||||
|
|
||||||
vulkano_shader!{
|
mod vs {
|
||||||
mod_name: vs,
|
vulkano_shaders::shader!{
|
||||||
ty: "vertex",
|
ty: "vertex",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec2 position;
|
layout(location = 0) in vec2 position;
|
||||||
@ -182,12 +181,13 @@ void main() {
|
|||||||
v_screen_coords = position;
|
v_screen_coords = position;
|
||||||
gl_Position = vec4(position, 0.0, 1.0);
|
gl_Position = vec4(position, 0.0, 1.0);
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkano_shader!{
|
mod fs {
|
||||||
mod_name: fs,
|
vulkano_shaders::shader!{
|
||||||
ty: "fragment",
|
ty: "fragment",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
// The `color_input` parameter of the `draw` method.
|
// The `color_input` parameter of the `draw` method.
|
||||||
@ -234,4 +234,5 @@ void main() {
|
|||||||
f_color.rgb = push_constants.color.rgb * light_percent * in_diffuse;
|
f_color.rgb = push_constants.color.rgb * light_percent * in_diffuse;
|
||||||
f_color.a = 1.0;
|
f_color.a = 1.0;
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ use vulkano::framebuffer::Subpass;
|
|||||||
use vulkano::pipeline::GraphicsPipeline;
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
use vulkano::pipeline::GraphicsPipelineAbstract;
|
use vulkano::pipeline::GraphicsPipelineAbstract;
|
||||||
use vulkano::pipeline::viewport::Viewport;
|
use vulkano::pipeline::viewport::Viewport;
|
||||||
use vulkano_shaders::vulkano_shader;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -95,10 +94,10 @@ struct Vertex {
|
|||||||
}
|
}
|
||||||
impl_vertex!(Vertex, position);
|
impl_vertex!(Vertex, position);
|
||||||
|
|
||||||
vulkano_shader!{
|
mod vs {
|
||||||
mod_name: vs,
|
vulkano_shaders::shader!{
|
||||||
ty: "vertex",
|
ty: "vertex",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec2 position;
|
layout(location = 0) in vec2 position;
|
||||||
@ -106,12 +105,13 @@ layout(location = 0) in vec2 position;
|
|||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(position, 0.0, 1.0);
|
gl_Position = vec4(position, 0.0, 1.0);
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkano_shader!{
|
mod fs {
|
||||||
mod_name: fs,
|
vulkano_shaders::shader!{
|
||||||
ty: "fragment",
|
ty: "fragment",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) out vec4 f_color;
|
layout(location = 0) out vec4 f_color;
|
||||||
@ -121,4 +121,5 @@ void main() {
|
|||||||
f_color = vec4(1.0, 1.0, 1.0, 1.0);
|
f_color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
f_normal = vec3(0.0, 0.0, 1.0);
|
f_normal = vec3(0.0, 0.0, 1.0);
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ extern crate vulkano_win;
|
|||||||
|
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use vulkano::sync::GpuFuture;
|
use vulkano::sync::GpuFuture;
|
||||||
use vulkano_shaders::vulkano_shader;
|
|
||||||
use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, RenderPassAbstract};
|
use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, RenderPassAbstract};
|
||||||
use vulkano::command_buffer::DynamicState;
|
use vulkano::command_buffer::DynamicState;
|
||||||
use vulkano::image::SwapchainImage;
|
use vulkano::image::SwapchainImage;
|
||||||
@ -253,10 +252,10 @@ fn window_size_dependent_setup(
|
|||||||
}).collect::<Vec<_>>()
|
}).collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkano_shader!{
|
mod vs {
|
||||||
mod_name: vs,
|
vulkano_shaders::shader!{
|
||||||
ty: "vertex",
|
ty: "vertex",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec2 position;
|
layout(location = 0) in vec2 position;
|
||||||
@ -266,12 +265,13 @@ void main() {
|
|||||||
gl_Position = vec4(position, 0.0, 1.0);
|
gl_Position = vec4(position, 0.0, 1.0);
|
||||||
tex_coords = position + vec2(0.5);
|
tex_coords = position + vec2(0.5);
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkano_shader!{
|
mod fs {
|
||||||
mod_name: fs,
|
vulkano_shaders::shader!{
|
||||||
ty: "fragment",
|
ty: "fragment",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec2 tex_coords;
|
layout(location = 0) in vec2 tex_coords;
|
||||||
@ -282,4 +282,5 @@ layout(set = 0, binding = 0) uniform sampler2D tex;
|
|||||||
void main() {
|
void main() {
|
||||||
f_color = texture(tex, tex_coords);
|
f_color = texture(tex, tex_coords);
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,12 +91,11 @@ use vulkano::instance::PhysicalDevice;
|
|||||||
use vulkano::pipeline::GraphicsPipeline;
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
use vulkano::pipeline::viewport::Viewport;
|
use vulkano::pipeline::viewport::Viewport;
|
||||||
use vulkano::sync::GpuFuture;
|
use vulkano::sync::GpuFuture;
|
||||||
use vulkano_shaders::vulkano_shader;
|
|
||||||
|
|
||||||
vulkano_shader!{
|
mod vs {
|
||||||
mod_name: vs,
|
vulkano_shaders::shader!{
|
||||||
ty: "vertex",
|
ty: "vertex",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec2 position;
|
layout(location = 0) in vec2 position;
|
||||||
@ -104,12 +103,13 @@ layout(location = 0) in vec2 position;
|
|||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(position, 0.0, 1.0);
|
gl_Position = vec4(position, 0.0, 1.0);
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkano_shader!{
|
mod fs {
|
||||||
mod_name: fs,
|
vulkano_shaders::shader!{
|
||||||
ty: "fragment",
|
ty: "fragment",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) out vec4 f_color;
|
layout(location = 0) out vec4 f_color;
|
||||||
@ -117,6 +117,7 @@ layout(location = 0) out vec4 f_color;
|
|||||||
void main() {
|
void main() {
|
||||||
f_color = vec4(1.0, 0.0, 0.0, 1.0);
|
f_color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -23,14 +23,12 @@ use vulkano::pipeline::ComputePipeline;
|
|||||||
use vulkano::sync::now;
|
use vulkano::sync::now;
|
||||||
use vulkano::sync::GpuFuture;
|
use vulkano::sync::GpuFuture;
|
||||||
|
|
||||||
use vulkano_shaders::vulkano_shader;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
vulkano_shader!{
|
mod cs {
|
||||||
mod_name: cs,
|
vulkano_shaders::shader!{
|
||||||
ty: "compute",
|
ty: "compute",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
|
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
@ -52,6 +50,7 @@ void main() {
|
|||||||
data.data[idx] += uint(pc.addend);
|
data.data[idx] += uint(pc.addend);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -22,14 +22,13 @@ use vulkano::instance::InstanceExtensions;
|
|||||||
use vulkano::pipeline::ComputePipeline;
|
use vulkano::pipeline::ComputePipeline;
|
||||||
use vulkano::sync::now;
|
use vulkano::sync::now;
|
||||||
use vulkano::sync::GpuFuture;
|
use vulkano::sync::GpuFuture;
|
||||||
use vulkano_shaders::vulkano_shader;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
vulkano_shader!{
|
mod cs {
|
||||||
mod_name: cs,
|
vulkano_shaders::shader!{
|
||||||
ty: "compute",
|
ty: "compute",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
|
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
@ -49,6 +48,7 @@ void main() {
|
|||||||
data.data[idx] += uint(addend);
|
data.data[idx] += uint(addend);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -14,7 +14,6 @@ extern crate time;
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate vulkano;
|
extern crate vulkano;
|
||||||
extern crate vulkano_shaders;
|
|
||||||
extern crate vulkano_win;
|
extern crate vulkano_win;
|
||||||
|
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
@ -36,8 +35,6 @@ use vulkano::swapchain::{AcquireError, PresentMode, SurfaceTransform, Swapchain,
|
|||||||
use vulkano::swapchain;
|
use vulkano::swapchain;
|
||||||
use vulkano::sync::GpuFuture;
|
use vulkano::sync::GpuFuture;
|
||||||
|
|
||||||
use vulkano_shaders::vulkano_shader;
|
|
||||||
|
|
||||||
use winit::Window;
|
use winit::Window;
|
||||||
|
|
||||||
use cgmath::{Matrix3, Matrix4, Point3, Vector3, Rad};
|
use cgmath::{Matrix3, Matrix4, Point3, Vector3, Rad};
|
||||||
@ -285,14 +282,16 @@ fn window_size_dependent_setup(
|
|||||||
(pipeline, framebuffers)
|
(pipeline, framebuffers)
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkano_shader!{
|
mod vs {
|
||||||
mod_name: vs,
|
vulkano_shaders::shader!{
|
||||||
ty: "vertex",
|
ty: "vertex",
|
||||||
path: "src/bin/teapot/vert.glsl"
|
path: "src/bin/teapot/vert.glsl"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkano_shader!{
|
mod fs {
|
||||||
mod_name: fs,
|
vulkano_shaders::shader!{
|
||||||
ty: "fragment",
|
ty: "fragment",
|
||||||
path: "src/bin/teapot/frag.glsl"
|
path: "src/bin/teapot/frag.glsl"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,16 +38,15 @@ use vulkano::swapchain;
|
|||||||
use vulkano::swapchain::{AcquireError, PresentMode, SurfaceTransform, Swapchain, SwapchainCreationError};
|
use vulkano::swapchain::{AcquireError, PresentMode, SurfaceTransform, Swapchain, SwapchainCreationError};
|
||||||
use vulkano::sync::now;
|
use vulkano::sync::now;
|
||||||
use vulkano::sync::GpuFuture;
|
use vulkano::sync::GpuFuture;
|
||||||
use vulkano_shaders::vulkano_shader;
|
|
||||||
|
|
||||||
use winit::Window;
|
use winit::Window;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
vulkano_shader!{
|
mod vs {
|
||||||
mod_name: vs,
|
vulkano_shaders::shader!{
|
||||||
ty: "vertex",
|
ty: "vertex",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec2 position;
|
layout(location = 0) in vec2 position;
|
||||||
@ -55,12 +54,13 @@ layout(location = 0) in vec2 position;
|
|||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(position, 0.0, 1.0);
|
gl_Position = vec4(position, 0.0, 1.0);
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkano_shader!{
|
mod tcs {
|
||||||
mod_name: tcs,
|
vulkano_shaders::shader!{
|
||||||
ty: "tess_ctrl",
|
ty: "tess_ctrl",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout (vertices = 3) out; // a value of 3 means a patch consists of a single triangle
|
layout (vertices = 3) out; // a value of 3 means a patch consists of a single triangle
|
||||||
@ -79,6 +79,7 @@ void main(void)
|
|||||||
// gl_TessLevelInner[1] = only used when tes uses layout(quads)
|
// gl_TessLevelInner[1] = only used when tes uses layout(quads)
|
||||||
// gl_TessLevelOuter[3] = only used when tes uses layout(quads)
|
// gl_TessLevelOuter[3] = only used when tes uses layout(quads)
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PG
|
// PG
|
||||||
@ -93,10 +94,10 @@ void main(void)
|
|||||||
// and the values x, y and z represent the distance from a vertex of the triangle.
|
// and the values x, y and z represent the distance from a vertex of the triangle.
|
||||||
// http://mathworld.wolfram.com/BarycentricCoordinates.html
|
// http://mathworld.wolfram.com/BarycentricCoordinates.html
|
||||||
|
|
||||||
vulkano_shader!{
|
mod tes {
|
||||||
mod_name: tes,
|
vulkano_shaders::shader!{
|
||||||
ty: "tess_eval",
|
ty: "tess_eval",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(triangles, equal_spacing, cw) in;
|
layout(triangles, equal_spacing, cw) in;
|
||||||
@ -116,12 +117,13 @@ void main(void)
|
|||||||
1.0
|
1.0
|
||||||
);
|
);
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkano_shader!{
|
mod fs {
|
||||||
mod_name: fs,
|
vulkano_shaders::shader!{
|
||||||
ty: "fragment",
|
ty: "fragment",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) out vec4 f_color;
|
layout(location = 0) out vec4 f_color;
|
||||||
@ -129,6 +131,7 @@ layout(location = 0) out vec4 f_color;
|
|||||||
void main() {
|
void main() {
|
||||||
f_color = vec4(1.0, 1.0, 1.0, 1.0);
|
f_color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
}"
|
}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
// The `vulkano` crate is the main crate that you must use to use Vulkan.
|
// The `vulkano` crate is the main crate that you must use to use Vulkan.
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate vulkano;
|
extern crate vulkano;
|
||||||
// Provides the `vulkano_shader` macro that is used to generate code for using shaders.
|
// Provides the `shader!` macro that is used to generate code for using shaders.
|
||||||
extern crate vulkano_shaders;
|
extern crate vulkano_shaders;
|
||||||
// The Vulkan library doesn't provide any functionality to create and handle windows, as
|
// The Vulkan library doesn't provide any functionality to create and handle windows, as
|
||||||
// this would be out of scope. In order to open a window, we are going to use the `winit` crate.
|
// this would be out of scope. In order to open a window, we are going to use the `winit` crate.
|
||||||
@ -46,8 +46,6 @@ use vulkano::swapchain;
|
|||||||
use vulkano::sync::GpuFuture;
|
use vulkano::sync::GpuFuture;
|
||||||
use vulkano::sync::now;
|
use vulkano::sync::now;
|
||||||
|
|
||||||
use vulkano_shaders::vulkano_shader;
|
|
||||||
|
|
||||||
use winit::Window;
|
use winit::Window;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -55,14 +53,14 @@ use std::sync::Arc;
|
|||||||
// TODO: Move this back to the middle of the example, it makes for a more coherent sequential explanation (check git history)
|
// TODO: Move this back to the middle of the example, it makes for a more coherent sequential explanation (check git history)
|
||||||
// The raw shader creation API provided by the vulkano library is unsafe, for various reasons.
|
// The raw shader creation API provided by the vulkano library is unsafe, for various reasons.
|
||||||
//
|
//
|
||||||
// An overview of what the `vulkano_shader` macro generates can be found in the
|
// An overview of what the `shader!` macro generates can be found in the
|
||||||
// `vulkano-shaders` crate docs. You can view them at https://docs.rs/vulkano-shaders/
|
// `vulkano-shaders` crate docs. You can view them at https://docs.rs/vulkano-shaders/
|
||||||
//
|
//
|
||||||
// TODO: explain this in details
|
// TODO: explain this in details
|
||||||
vulkano_shader!{
|
mod vs {
|
||||||
mod_name: vs,
|
vulkano_shaders::shader!{
|
||||||
ty: "vertex",
|
ty: "vertex",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec2 position;
|
layout(location = 0) in vec2 position;
|
||||||
@ -71,11 +69,12 @@ void main() {
|
|||||||
gl_Position = vec4(position, 0.0, 1.0);
|
gl_Position = vec4(position, 0.0, 1.0);
|
||||||
}"
|
}"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vulkano_shader!{
|
mod fs {
|
||||||
mod_name: fs,
|
vulkano_shaders::shader!{
|
||||||
ty: "fragment",
|
ty: "fragment",
|
||||||
src: "
|
src: "
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) out vec4 f_color;
|
layout(location = 0) out vec4 f_color;
|
||||||
@ -84,6 +83,7 @@ void main() {
|
|||||||
f_color = vec4(1.0, 0.0, 0.0, 1.0);
|
f_color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -36,7 +36,7 @@ pub fn compile(code: &str, ty: ShaderKind) -> Result<CompilationArtifact, String
|
|||||||
Ok(content)
|
Ok(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reflect(name: &str, spirv: &[u32], mod_name: &Ident, dump: bool) -> Result<TokenStream, Error> {
|
pub fn reflect(name: &str, spirv: &[u32], dump: bool) -> Result<TokenStream, Error> {
|
||||||
let struct_name = Ident::new(&name, Span::call_site());
|
let struct_name = Ident::new(&name, Span::call_site());
|
||||||
let doc = parse::parse_spirv(spirv)?;
|
let doc = parse::parse_spirv(spirv)?;
|
||||||
|
|
||||||
@ -71,90 +71,88 @@ pub fn reflect(name: &str, spirv: &[u32], mod_name: &Ident, dump: bool) -> Resul
|
|||||||
let descriptor_sets = descriptor_sets::write_descriptor_sets(&doc);
|
let descriptor_sets = descriptor_sets::write_descriptor_sets(&doc);
|
||||||
let specialization_constants = spec_consts::write_specialization_constants(&doc);
|
let specialization_constants = spec_consts::write_specialization_constants(&doc);
|
||||||
let ast = quote!{
|
let ast = quote!{
|
||||||
mod #mod_name {
|
#[allow(unused_imports)]
|
||||||
#[allow(unused_imports)]
|
use std::sync::Arc;
|
||||||
use std::sync::Arc;
|
#[allow(unused_imports)]
|
||||||
#[allow(unused_imports)]
|
use std::vec::IntoIter as VecIntoIter;
|
||||||
use std::vec::IntoIter as VecIntoIter;
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::device::Device;
|
use vulkano::device::Device;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::descriptor::descriptor::DescriptorDesc;
|
use vulkano::descriptor::descriptor::DescriptorDesc;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::descriptor::descriptor::DescriptorDescTy;
|
use vulkano::descriptor::descriptor::DescriptorDescTy;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::descriptor::descriptor::DescriptorBufferDesc;
|
use vulkano::descriptor::descriptor::DescriptorBufferDesc;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::descriptor::descriptor::DescriptorImageDesc;
|
use vulkano::descriptor::descriptor::DescriptorImageDesc;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::descriptor::descriptor::DescriptorImageDescDimensions;
|
use vulkano::descriptor::descriptor::DescriptorImageDescDimensions;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::descriptor::descriptor::DescriptorImageDescArray;
|
use vulkano::descriptor::descriptor::DescriptorImageDescArray;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::descriptor::descriptor::ShaderStages;
|
use vulkano::descriptor::descriptor::ShaderStages;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::descriptor::descriptor_set::DescriptorSet;
|
use vulkano::descriptor::descriptor_set::DescriptorSet;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::descriptor::descriptor_set::UnsafeDescriptorSet;
|
use vulkano::descriptor::descriptor_set::UnsafeDescriptorSet;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::descriptor::descriptor_set::UnsafeDescriptorSetLayout;
|
use vulkano::descriptor::descriptor_set::UnsafeDescriptorSetLayout;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::descriptor::pipeline_layout::PipelineLayout;
|
use vulkano::descriptor::pipeline_layout::PipelineLayout;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::descriptor::pipeline_layout::PipelineLayoutDesc;
|
use vulkano::descriptor::pipeline_layout::PipelineLayoutDesc;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::descriptor::pipeline_layout::PipelineLayoutDescPcRange;
|
use vulkano::descriptor::pipeline_layout::PipelineLayoutDescPcRange;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::pipeline::shader::SpecializationConstants as SpecConstsTrait;
|
use vulkano::pipeline::shader::SpecializationConstants as SpecConstsTrait;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use vulkano::pipeline::shader::SpecializationMapEntry;
|
use vulkano::pipeline::shader::SpecializationMapEntry;
|
||||||
|
|
||||||
pub struct #struct_name {
|
pub struct #struct_name {
|
||||||
shader: ::std::sync::Arc<::vulkano::pipeline::shader::ShaderModule>,
|
shader: ::std::sync::Arc<::vulkano::pipeline::shader::ShaderModule>,
|
||||||
}
|
|
||||||
|
|
||||||
impl #struct_name {
|
|
||||||
/// Loads the shader in Vulkan as a `ShaderModule`.
|
|
||||||
#[inline]
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
pub fn load(device: ::std::sync::Arc<::vulkano::device::Device>)
|
|
||||||
-> Result<#struct_name, ::vulkano::OomError>
|
|
||||||
{
|
|
||||||
#( #cap_checks )*
|
|
||||||
let words = [ #( #spirv ),* ];
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
Ok(#struct_name {
|
|
||||||
shader: try!(::vulkano::pipeline::shader::ShaderModule::from_words(device, &words))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the module that was created.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[inline]
|
|
||||||
pub fn module(&self) -> &::std::sync::Arc<::vulkano::pipeline::shader::ShaderModule> {
|
|
||||||
&self.shader
|
|
||||||
}
|
|
||||||
|
|
||||||
#( #entry_points_inside_impl )*
|
|
||||||
}
|
|
||||||
|
|
||||||
#( #entry_points_outside_impl )*
|
|
||||||
|
|
||||||
pub mod ty {
|
|
||||||
#structs
|
|
||||||
}
|
|
||||||
|
|
||||||
#descriptor_sets
|
|
||||||
#specialization_constants
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl #struct_name {
|
||||||
|
/// Loads the shader in Vulkan as a `ShaderModule`.
|
||||||
|
#[inline]
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
pub fn load(device: ::std::sync::Arc<::vulkano::device::Device>)
|
||||||
|
-> Result<#struct_name, ::vulkano::OomError>
|
||||||
|
{
|
||||||
|
#( #cap_checks )*
|
||||||
|
let words = [ #( #spirv ),* ];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
Ok(#struct_name {
|
||||||
|
shader: try!(::vulkano::pipeline::shader::ShaderModule::from_words(device, &words))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the module that was created.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[inline]
|
||||||
|
pub fn module(&self) -> &::std::sync::Arc<::vulkano::pipeline::shader::ShaderModule> {
|
||||||
|
&self.shader
|
||||||
|
}
|
||||||
|
|
||||||
|
#( #entry_points_inside_impl )*
|
||||||
|
}
|
||||||
|
|
||||||
|
#( #entry_points_outside_impl )*
|
||||||
|
|
||||||
|
pub mod ty {
|
||||||
|
#structs
|
||||||
|
}
|
||||||
|
|
||||||
|
#descriptor_sets
|
||||||
|
#specialization_constants
|
||||||
};
|
};
|
||||||
|
|
||||||
if dump {
|
if dump {
|
||||||
println!("{}", ast.to_string());
|
println!("{}", ast.to_string());
|
||||||
panic!("vulkano_shader! rust codegen dumped") // TODO: use span from dump
|
panic!("`shader!` rust codegen dumped") // TODO: use span from dump
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ast)
|
Ok(ast)
|
||||||
|
@ -4,15 +4,13 @@
|
|||||||
//! # Basic usage
|
//! # Basic usage
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! extern crate vulkano_shaders;
|
|
||||||
//! extern crate vulkano;
|
//! extern crate vulkano;
|
||||||
|
//! extern crate vulkano_shaders;
|
||||||
//!
|
//!
|
||||||
//! use vulkano_shaders::vulkano_shader;
|
//! mod vs {
|
||||||
//!
|
//! vulkano_shaders::shader!{
|
||||||
//! vulkano_shader!{
|
//! ty: "vertex",
|
||||||
//! mod_name: vertex_shader,
|
//! src: "
|
||||||
//! ty: "vertex",
|
|
||||||
//! src: "
|
|
||||||
//! #version 450
|
//! #version 450
|
||||||
//!
|
//!
|
||||||
//! layout(location = 0) in vec3 position;
|
//! layout(location = 0) in vec3 position;
|
||||||
@ -20,6 +18,7 @@
|
|||||||
//! void main() {
|
//! void main() {
|
||||||
//! gl_Position = vec4(position, 1.0);
|
//! gl_Position = vec4(position, 1.0);
|
||||||
//! }"
|
//! }"
|
||||||
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! # fn main() {}
|
//! # fn main() {}
|
||||||
//! ```
|
//! ```
|
||||||
@ -74,12 +73,11 @@
|
|||||||
//! # use std::sync::Arc;
|
//! # use std::sync::Arc;
|
||||||
//! # use vulkano::OomError;
|
//! # use vulkano::OomError;
|
||||||
//! # use vulkano::device::Device;
|
//! # use vulkano::device::Device;
|
||||||
//! # use vulkano_shaders::vulkano_shader;
|
|
||||||
//! #
|
//! #
|
||||||
//! # vulkano_shader!{
|
//! # mod vs {
|
||||||
//! # mod_name: vertex_shader,
|
//! # vulkano_shaders::shader!{
|
||||||
//! # ty: "vertex",
|
//! # ty: "vertex",
|
||||||
//! # src: "
|
//! # src: "
|
||||||
//! # #version 450
|
//! # #version 450
|
||||||
//! #
|
//! #
|
||||||
//! # layout(location = 0) in vec3 position;
|
//! # layout(location = 0) in vec3 position;
|
||||||
@ -87,18 +85,19 @@
|
|||||||
//! # void main() {
|
//! # void main() {
|
||||||
//! # gl_Position = vec4(position, 1.0);
|
//! # gl_Position = vec4(position, 1.0);
|
||||||
//! # }"
|
//! # }"
|
||||||
|
//! # }
|
||||||
//! # }
|
//! # }
|
||||||
//! // various use statements
|
//! // various use statements
|
||||||
//! // `vertex_shader` module with shader derive
|
//! // `vertex_shader` module with shader derive
|
||||||
//!
|
//!
|
||||||
//! pub struct Shaders {
|
//! pub struct Shaders {
|
||||||
//! pub vertex_shader: vertex_shader::Shader
|
//! pub vs: vs::Shader
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! impl Shaders {
|
//! impl Shaders {
|
||||||
//! pub fn load(device: Arc<Device>) -> Result<Self, OomError> {
|
//! pub fn load(device: Arc<Device>) -> Result<Self, OomError> {
|
||||||
//! Ok(Self {
|
//! Ok(Self {
|
||||||
//! vertex_shader: vertex_shader::Shader::load(device)?,
|
//! vs: vs::Shader::load(device)?,
|
||||||
//! })
|
//! })
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
@ -186,7 +185,6 @@ enum SourceKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct MacroInput {
|
struct MacroInput {
|
||||||
mod_ident: Ident,
|
|
||||||
shader_kind: ShaderKind,
|
shader_kind: ShaderKind,
|
||||||
source_kind: SourceKind,
|
source_kind: SourceKind,
|
||||||
dump: bool,
|
dump: bool,
|
||||||
@ -195,7 +193,6 @@ struct MacroInput {
|
|||||||
impl Parse for MacroInput {
|
impl Parse for MacroInput {
|
||||||
fn parse(input: ParseStream) -> Result<Self> {
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
let mut dump = None;
|
let mut dump = None;
|
||||||
let mut mod_ident = None;
|
|
||||||
let mut shader_kind = None;
|
let mut shader_kind = None;
|
||||||
let mut source_kind = None;
|
let mut source_kind = None;
|
||||||
|
|
||||||
@ -204,14 +201,6 @@ impl Parse for MacroInput {
|
|||||||
input.parse::<Token![:]>()?;
|
input.parse::<Token![:]>()?;
|
||||||
|
|
||||||
match name.to_string().as_ref() {
|
match name.to_string().as_ref() {
|
||||||
"mod_name" => {
|
|
||||||
if mod_ident.is_some() {
|
|
||||||
panic!("Only one `mod` can be defined")
|
|
||||||
}
|
|
||||||
|
|
||||||
let mod_name: Ident = input.parse()?;
|
|
||||||
mod_ident = Some(mod_name);
|
|
||||||
}
|
|
||||||
"ty" => {
|
"ty" => {
|
||||||
if shader_kind.is_some() {
|
if shader_kind.is_some() {
|
||||||
panic!("Only one `ty` can be defined")
|
panic!("Only one `ty` can be defined")
|
||||||
@ -270,19 +259,14 @@ impl Parse for MacroInput {
|
|||||||
None => panic!("Please provide a source e.g. `path: \"foo.glsl\"` or `src: \"glsl source code here ...\"`")
|
None => panic!("Please provide a source e.g. `path: \"foo.glsl\"` or `src: \"glsl source code here ...\"`")
|
||||||
};
|
};
|
||||||
|
|
||||||
let mod_ident = match mod_ident {
|
|
||||||
Some(mod_ident) => mod_ident,
|
|
||||||
None => panic!("Please provide a mod e.g. `mod: fs` ")
|
|
||||||
};
|
|
||||||
|
|
||||||
let dump = dump.unwrap_or(false);
|
let dump = dump.unwrap_or(false);
|
||||||
|
|
||||||
Ok(MacroInput { shader_kind, source_kind, mod_ident, dump })
|
Ok(MacroInput { shader_kind, source_kind, dump })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn vulkano_shader(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn shader(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
let input = parse_macro_input!(input as MacroInput);
|
let input = parse_macro_input!(input as MacroInput);
|
||||||
|
|
||||||
let source_code = match input.source_kind {
|
let source_code = match input.source_kind {
|
||||||
@ -304,5 +288,5 @@ pub fn vulkano_shader(input: proc_macro::TokenStream) -> proc_macro::TokenStream
|
|||||||
};
|
};
|
||||||
|
|
||||||
let content = codegen::compile(&source_code, input.shader_kind).unwrap();
|
let content = codegen::compile(&source_code, input.shader_kind).unwrap();
|
||||||
codegen::reflect("Shader", content.as_binary(), &input.mod_ident, input.dump).unwrap().into()
|
codegen::reflect("Shader", content.as_binary(), input.dump).unwrap().into()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user