@ -3,6 +3,7 @@ use winit::{
event_loop ::{ EventLoop , ControlFlow } ,
window ::{ Window , WindowBuilder } ,
} ;
use wgpu ::util ::DeviceExt ;
mod texture ;
@ -219,22 +220,18 @@ struct State {
queue : wgpu ::Queue ,
sc_desc : wgpu ::SwapChainDescriptor ,
swap_chain : wgpu ::SwapChain ,
render_pipeline : wgpu ::RenderPipeline ,
vertex_buffer : wgpu ::Buffer ,
index_buffer : wgpu ::Buffer ,
num_indices : u32 ,
#[ allow(dead_code) ]
diffuse_texture : texture ::Texture ,
diffuse_bind_group : wgpu ::BindGroup ,
camera_controller : CameraController ,
uniforms : Uniforms ,
uniform_staging : UniformStaging ,
uniform_buffer : wgpu ::Buffer ,
uniform_bind_group : wgpu ::BindGroup ,
size : winit ::dpi ::PhysicalSize < u32 > ,
}
@ -242,22 +239,24 @@ impl State {
async fn new ( window : & Window ) -> Self {
let size = window . inner_size ( ) ;
let surface = wgpu ::Surface ::create ( window ) ;
let adapter = wgpu ::Adapter ::request (
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu ::Instance ::new ( wgpu ::BackendBit ::PRIMARY ) ;
let surface = unsafe { instance . create_surface ( window ) } ;
let adapter = instance . request_adapter (
& wgpu ::RequestAdapterOptions {
power_preference : wgpu ::PowerPreference ::Default ,
compatible_surface : Some ( & surface ) ,
} ,
wgpu ::BackendBit ::PRIMARY , // Vulkan + Metal + DX12 + Browser WebGPU
) . await . unwrap ( ) ;
let ( device , queue ) = adapter . request_device ( & wgpu ::DeviceDescriptor {
extensions : wgpu ::Extensions {
anisotropic_filtering : false ,
let ( device , queue ) = adapter . request_device (
& wgpu ::DeviceDescriptor {
features : wgpu ::Features ::empty ( ) ,
limits : wgpu ::Limits ::default ( ) ,
shader_validation : true ,
} ,
limits : Default ::default ( ) ,
} ). await ;
None , // Trace path
). await . unwrap ( ) ;
let sc_desc = wgpu ::SwapChainDescriptor {
usage : wgpu ::TextureUsage ::OUTPUT_ATTACHMENT ,
@ -269,45 +268,55 @@ impl State {
let swap_chain = device . create_swap_chain ( & surface , & sc_desc ) ;
let diffuse_bytes = include_bytes! ( "happy-tree.png" ) ;
let ( diffuse_texture , cmd_buffer ) = texture ::Texture ::from_bytes ( & device , diffuse_bytes , "diffuse" ) . unwrap ( ) ;
queue . submit ( & [ cmd_buffer ] ) ;
let texture_bind_group_layout = device . create_bind_group_layout ( & wgpu ::BindGroupLayoutDescriptor {
bindings : & [
wgpu ::BindGroupLayoutEntry {
binding : 0 ,
visibility : wgpu ::ShaderStage ::FRAGMENT ,
ty : wgpu ::BindingType ::SampledTexture {
multisampled : false ,
dimension : wgpu ::TextureViewDimension ::D2 ,
component_type : wgpu ::TextureComponentType ::Uint ,
let diffuse_texture = texture ::Texture ::from_bytes (
& device ,
& queue ,
diffuse_bytes ,
"happy-tree.png"
) . unwrap ( ) ;
let texture_bind_group_layout = device . create_bind_group_layout (
& wgpu ::BindGroupLayoutDescriptor {
entries : & [
wgpu ::BindGroupLayoutEntry {
binding : 0 ,
visibility : wgpu ::ShaderStage ::FRAGMENT ,
ty : wgpu ::BindingType ::SampledTexture {
multisampled : false ,
dimension : wgpu ::TextureViewDimension ::D2 ,
component_type : wgpu ::TextureComponentType ::Uint ,
} ,
count : None ,
} ,
} ,
wgpu ::BindGroupLayoutEntry {
binding : 1 ,
visibility : wgpu ::ShaderStage ::FRAGMENT ,
ty : wgpu ::BindingType ::Sampler {
comparison : false ,
wgpu ::BindGroupLayoutEntry {
binding : 1 ,
visibility : wgpu ::ShaderStage ::FRAGMENT ,
ty : wgpu ::BindingType ::Sampler {
comparison : false ,
} ,
count : None ,
} ,
} ,
] ,
label : Some ( "texture_bind_group_layout" ) ,
} );
] ,
label : Some ( "texture_bind_group_layout" ) ,
}
);
let diffuse_bind_group = device . create_bind_group ( & wgpu ::BindGroupDescriptor {
layout : & texture_bind_group_layout ,
bindings : & [
wgpu ::Binding {
binding : 0 ,
resource : wgpu ::BindingResource ::TextureView ( & diffuse_texture . view ) ,
} ,
wgpu ::Binding {
binding : 1 ,
resource : wgpu ::BindingResource ::Sampler ( & diffuse_texture . sampler ) ,
}
] ,
label : Some ( "diffuse_bind_group" ) ,
} ) ;
let diffuse_bind_group = device . create_bind_group (
& wgpu ::BindGroupDescriptor {
layout : & texture_bind_group_layout ,
entries : & [
wgpu ::BindGroupEntry {
binding : 0 ,
resource : wgpu ::BindingResource ::TextureView ( & diffuse_texture . view ) ,
} ,
wgpu ::BindGroupEntry {
binding : 1 ,
resource : wgpu ::BindingResource ::Sampler ( & diffuse_texture . sampler ) ,
}
] ,
label : Some ( "diffuse_bind_group" ) ,
}
) ;
let camera = Camera {
eye : ( 0.0 , 1.0 , 2.0 ) . into ( ) ,
@ -324,19 +333,24 @@ impl State {
let uniform_staging = UniformStaging ::new ( camera ) ;
uniform_staging . update_uniforms ( & mut uniforms ) ;
let uniform_buffer = device . create_buffer_with_data (
bytemuck ::cast_slice ( & [ uniforms ] ) ,
wgpu ::BufferUsage ::UNIFORM | wgpu ::BufferUsage ::COPY_DST ,
let uniform_buffer = device . create_buffer_init (
& wgpu ::util ::BufferInitDescriptor {
label : Some ( "Uniform Buffer" ) ,
contents : bytemuck ::cast_slice ( & [ uniforms ] ) ,
usage : wgpu ::BufferUsage ::UNIFORM | wgpu ::BufferUsage ::COPY_DST ,
}
) ;
let uniform_bind_group_layout = device . create_bind_group_layout ( & wgpu ::BindGroupLayoutDescriptor {
binding s: & [
entrie s: & [
wgpu ::BindGroupLayoutEntry {
binding : 0 ,
visibility : wgpu ::ShaderStage ::VERTEX ,
ty : wgpu ::BindingType ::UniformBuffer {
dynamic : false ,
min_binding_size : None ,
} ,
count : None ,
}
] ,
label : Some ( "uniform_bind_group_layout" ) ,
@ -344,77 +358,84 @@ impl State {
let uniform_bind_group = device . create_bind_group ( & wgpu ::BindGroupDescriptor {
layout : & uniform_bind_group_layout ,
binding s: & [
wgpu ::Bind ing {
entrie s: & [
wgpu ::Bind GroupEntry {
binding : 0 ,
resource : wgpu ::BindingResource ::Buffer {
buffer : & uniform_buffer ,
range : 0 .. std ::mem ::size_of_val ( & uniforms ) as wgpu ::BufferAddress ,
}
resource : wgpu ::BindingResource ::Buffer ( uniform_buffer . slice ( .. ) )
}
] ,
label : Some ( "uniform_bind_group" ) ,
} ) ;
let vs_src = include_str! ( "shader.vert" ) ;
let fs_src = include_str! ( "shader.frag" ) ;
let mut compiler = shaderc ::Compiler ::new ( ) . unwrap ( ) ;
let vs_spirv = compiler . compile_into_spirv ( vs_src , shaderc ::ShaderKind ::Vertex , "shader.vert" , "main" , None ) . unwrap ( ) ;
let fs_spirv = compiler . compile_into_spirv ( fs_src , shaderc ::ShaderKind ::Fragment , "shader.frag" , "main" , None ) . unwrap ( ) ;
let vs_data = wgpu ::read_spirv ( std ::io ::Cursor ::new ( vs_spirv . as_binary_u8 ( ) ) ) . unwrap ( ) ;
let fs_data = wgpu ::read_spirv ( std ::io ::Cursor ::new ( fs_spirv . as_binary_u8 ( ) ) ) . unwrap ( ) ;
let vs_module = device . create_shader_module ( & vs_data ) ;
let fs_module = device . create_shader_module ( & fs_data ) ;
let render_pipeline_layout = device . create_pipeline_layout ( & wgpu ::PipelineLayoutDescriptor {
bind_group_layouts : & [ & texture_bind_group_layout , & uniform_bind_group_layout ] ,
} ) ;
let vs_module = device . create_shader_module ( wgpu ::include_spirv ! ( "shader.vert.spv" ) ) ;
let fs_module = device . create_shader_module ( wgpu ::include_spirv ! ( "shader.frag.spv" ) ) ;
let render_pipeline = device . create_render_pipeline ( & wgpu ::RenderPipelineDescriptor {
layout : & render_pipeline_layout ,
vertex_stage : wgpu ::ProgrammableStageDescriptor {
module : & vs_module ,
entry_point : "main" ,
} ,
fragment_stage : Some ( wgpu ::ProgrammableStageDescriptor {
module : & fs_module ,
entry_point : "main" ,
} ) ,
rasterization_state : Some ( wgpu ::RasterizationStateDescriptor {
front_face : wgpu ::FrontFace ::Ccw ,
cull_mode : wgpu ::CullMode ::Back ,
depth_bias : 0 ,
depth_bias_slope_scale : 0.0 ,
depth_bias_clamp : 0.0 ,
} ) ,
primitive_topology : wgpu ::PrimitiveTopology ::TriangleList ,
color_states : & [
wgpu ::ColorStateDescriptor {
format : sc_desc . format ,
color_blend : wgpu ::BlendDescriptor ::REPLACE ,
alpha_blend : wgpu ::BlendDescriptor ::REPLACE ,
write_mask : wgpu ::ColorWrite ::ALL ,
let render_pipeline_layout = device . create_pipeline_layout (
& wgpu ::PipelineLayoutDescriptor {
label : Some ( "Render Pipeline Layout" ) ,
bind_group_layouts : & [
& texture_bind_group_layout ,
& uniform_bind_group_layout ,
] ,
push_constant_ranges : & [ ] ,
}
) ;
let render_pipeline = device . create_render_pipeline (
& wgpu ::RenderPipelineDescriptor {
label : Some ( "Render Pipeline" ) ,
layout : Some ( & render_pipeline_layout ) ,
vertex_stage : wgpu ::ProgrammableStageDescriptor {
module : & vs_module ,
entry_point : "main" ,
} ,
] ,
depth_stencil_state : None ,
vertex_state : wgpu ::VertexStateDescriptor {
index_format : wgpu ::IndexFormat ::Uint16 ,
vertex_buffers : & [
Vertex ::desc ( ) ,
fragment_stage : Some ( wgpu ::ProgrammableStageDescriptor {
module : & fs_module ,
entry_point : "main" ,
} ) ,
rasterization_state : Some (
wgpu ::RasterizationStateDescriptor {
front_face : wgpu ::FrontFace ::Ccw ,
cull_mode : wgpu ::CullMode ::Back ,
depth_bias : 0 ,
depth_bias_slope_scale : 0.0 ,
depth_bias_clamp : 0.0 ,
clamp_depth : false ,
}
) ,
primitive_topology : wgpu ::PrimitiveTopology ::TriangleList ,
color_states : & [
wgpu ::ColorStateDescriptor {
format : sc_desc . format ,
color_blend : wgpu ::BlendDescriptor ::REPLACE ,
alpha_blend : wgpu ::BlendDescriptor ::REPLACE ,
write_mask : wgpu ::ColorWrite ::ALL ,
} ,
] ,
} ,
sample_count : 1 ,
sample_mask : ! 0 ,
alpha_to_coverage_enabled : false ,
} ) ;
depth_stencil_state : None ,
vertex_state : wgpu ::VertexStateDescriptor {
index_format : wgpu ::IndexFormat ::Uint16 ,
vertex_buffers : & [ Vertex ::desc ( ) ] ,
} ,
sample_count : 1 ,
sample_mask : ! 0 ,
alpha_to_coverage_enabled : false ,
}
) ;
let vertex_buffer = device . create_buffer_with_data (
bytemuck ::cast_slice ( VERTICES ) ,
wgpu ::BufferUsage ::VERTEX ,
let vertex_buffer = device . create_buffer_init (
& wgpu ::util ::BufferInitDescriptor {
label : Some ( "Vertex Buffer" ) ,
contents : bytemuck ::cast_slice ( VERTICES ) ,
usage : wgpu ::BufferUsage ::VERTEX ,
}
) ;
let index_buffer = device . create_buffer_with_data (
bytemuck ::cast_slice ( INDICES ) ,
wgpu ::BufferUsage ::INDEX ,
let index_buffer = device . create_buffer_init (
& wgpu ::util ::BufferInitDescriptor {
label : Some ( "Index Buffer" ) ,
contents : bytemuck ::cast_slice ( INDICES ) ,
usage : wgpu ::BufferUsage ::INDEX ,
}
) ;
let num_indices = INDICES . len ( ) as u32 ;
@ -457,24 +478,13 @@ impl State {
self . camera_controller . update_camera ( & mut self . uniform_staging . camera ) ;
self . uniform_staging . model_rotation + = cgmath ::Deg ( 2.0 ) ;
self . uniform_staging . update_uniforms ( & mut self . uniforms ) ;
let mut encoder = self . device . create_command_encoder ( & wgpu ::CommandEncoderDescriptor {
label : Some ( "update encoder" ) ,
} ) ;
let staging_buffer = self . device . create_buffer_with_data (
bytemuck ::cast_slice ( & [ self . uniforms ] ) ,
wgpu ::BufferUsage ::COPY_SRC ,
) ;
encoder . copy_buffer_to_buffer ( & staging_buffer , 0 , & self . uniform_buffer , 0 , std ::mem ::size_of ::< Uniforms > ( ) as wgpu ::BufferAddress ) ;
self . queue . submit ( & [ encoder . finish ( ) ] ) ;
self . queue . write_buffer ( & self . uniform_buffer , 0 , & bytemuck ::cast_slice ( & [ self . uniforms ] ) ) ;
}
fn render ( & mut self ) {
let frame = self . swap_chain . get_next_texture ( )
. expect ( "Timeout getting texture" ) ;
let frame = self . swap_chain . get_current_frame ( )
. expect ( "Timeout getting texture" )
. output ;
let mut encoder = self . device . create_command_encoder ( & wgpu ::CommandEncoderDescriptor {
label : Some ( "Render Encoder" ) ,
@ -486,14 +496,17 @@ impl State {
wgpu ::RenderPassColorAttachmentDescriptor {
attachment : & frame . view ,
resolve_target : None ,
load_op : wgpu ::LoadOp ::Clear ,
store_op : wgpu ::StoreOp ::Store ,
clear_color : wgpu ::Color {
r : 0.1 ,
g : 0.2 ,
b : 0.3 ,
a : 1.0 ,
} ,
ops : wgpu ::Operations {
load : wgpu ::LoadOp ::Clear (
wgpu ::Color {
r : 0.1 ,
g : 0.2 ,
b : 0.3 ,
a : 1.0 ,
}
) ,
store : true ,
}
}
] ,
depth_stencil_attachment : None ,
@ -502,14 +515,12 @@ impl State {
render_pass . set_pipeline ( & self . render_pipeline ) ;
render_pass . set_bind_group ( 0 , & self . diffuse_bind_group , & [ ] ) ;
render_pass . set_bind_group ( 1 , & self . uniform_bind_group , & [ ] ) ;
render_pass . set_vertex_buffer ( 0 , & self . vertex_buffer , 0 , 0 ) ;
render_pass . set_index_buffer ( & self . index_buffer , 0 , 0 ) ;
render_pass . set_vertex_buffer ( 0 , self . vertex_buffer . slice ( .. ) ) ;
render_pass . set_index_buffer ( self . index_buffer . slice ( .. ) ) ;
render_pass . draw_indexed ( 0 .. self . num_indices , 0 , 0 .. 1 ) ;
}
self . queue . submit ( & [
encoder . finish ( )
] ) ;
self . queue . submit ( Some ( encoder . finish ( ) ) ) ;
}
}