Starting to mess with promises
Going to want async IO, I think. And it's a fun detail that I guess I'm in charge of deciding when to run promise completion functions. :D
This commit is contained in:
parent
c1d86676c3
commit
5be0ffa08f
7 changed files with 251 additions and 74 deletions
42
src/lib.rs
42
src/lib.rs
|
|
@ -178,22 +178,6 @@ impl State {
|
|||
label: Some("sprite_bind_group_layout"),
|
||||
});
|
||||
|
||||
// TODO: DELETE THIS
|
||||
// let sprite_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
// layout: &sprite_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 screen_uniform = ScreenUniforms::new(size.width, size.height);
|
||||
let screen_uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Screen Uniform Buffer"),
|
||||
|
|
@ -205,7 +189,7 @@ impl State {
|
|||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::VERTEX,
|
||||
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
|
|
@ -225,28 +209,28 @@ impl State {
|
|||
label: Some("camera_bind_group"),
|
||||
});
|
||||
|
||||
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: Some("Shader"),
|
||||
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
|
||||
let sprite_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: Some("Sprite Shader"),
|
||||
source: wgpu::ShaderSource::Wgsl(include_str!("sprite_shader.wgsl").into()),
|
||||
});
|
||||
|
||||
let render_pipeline_layout =
|
||||
let sprite_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Render Pipeline Layout"),
|
||||
label: Some("Sprite Pipeline Layout"),
|
||||
bind_group_layouts: &[&sprite_bind_group_layout, &screen_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),
|
||||
let sprite_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Sprite Pipeline"),
|
||||
layout: Some(&sprite_pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &shader,
|
||||
module: &sprite_shader,
|
||||
entry_point: "vs_main",
|
||||
buffers: &[Vertex::desc()],
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
module: &sprite_shader,
|
||||
entry_point: "fs_main",
|
||||
targets: &[Some(wgpu::ColorTargetState {
|
||||
format: config.format,
|
||||
|
|
@ -292,7 +276,7 @@ impl State {
|
|||
queue,
|
||||
config,
|
||||
size,
|
||||
render_pipeline,
|
||||
render_pipeline: sprite_pipeline,
|
||||
vertex_buffer,
|
||||
max_vertices,
|
||||
sprite_bind_group_layout,
|
||||
|
|
@ -529,7 +513,7 @@ pub async fn run() {
|
|||
|
||||
let mut state = State::new(window).await;
|
||||
|
||||
let context = script::ScriptContext::new();
|
||||
let mut context = script::ScriptContext::new();
|
||||
context.init();
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
use oden_js::{
|
||||
module::loader::{ModuleLoader, ModuleSource},
|
||||
Context, ContextRef, Result, Runtime, Value,
|
||||
Context, ContextRef, Promise, Result, Runtime, Value, ValueResult,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::mpsc::{channel, Receiver};
|
||||
|
||||
pub mod graphics;
|
||||
|
|
@ -37,6 +39,21 @@ impl ModuleLoader for Loader {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Debug, Clone, Copy)]
|
||||
pub struct PromiseHandle(u64);
|
||||
|
||||
impl PromiseHandle {
|
||||
pub fn new() -> Self {
|
||||
static NEXT_ID: AtomicU64 = AtomicU64::new(0);
|
||||
PromiseHandle(NEXT_ID.fetch_add(1, Ordering::SeqCst))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ScriptEvent {
|
||||
AddPromise(PromiseHandle, Promise),
|
||||
CompletePromise(PromiseHandle, Box<dyn FnOnce(&ContextRef) -> ValueResult>),
|
||||
}
|
||||
|
||||
pub struct ScriptContext {
|
||||
context: Context,
|
||||
init: Value,
|
||||
|
|
@ -46,6 +63,9 @@ pub struct ScriptContext {
|
|||
gfx: graphics::GraphicsAPI,
|
||||
_assets: assets::AssetsAPI,
|
||||
gfx_receive: Receiver<graphics::GraphicsCommand>,
|
||||
|
||||
script_receive: Receiver<ScriptEvent>,
|
||||
promises: HashMap<PromiseHandle, Promise>,
|
||||
}
|
||||
|
||||
impl ScriptContext {
|
||||
|
|
@ -58,6 +78,7 @@ impl ScriptContext {
|
|||
context.add_intrinsic_operators();
|
||||
|
||||
let (gfx_send, gfx_receive) = channel();
|
||||
let (script_send, script_receive) = channel();
|
||||
|
||||
let gfx = graphics::GraphicsAPI::define(&context, gfx_send.clone())
|
||||
.expect("Graphics module should load without error");
|
||||
|
|
@ -89,6 +110,9 @@ impl ScriptContext {
|
|||
gfx_receive,
|
||||
|
||||
_assets: assets,
|
||||
|
||||
script_receive,
|
||||
promises: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,18 +120,52 @@ impl ScriptContext {
|
|||
// We would want a bi-directional gate for frames to not let the
|
||||
// game thread go to fast probably? And to discard whole frames &c.
|
||||
|
||||
pub fn init(&self) {
|
||||
self.init.call(&self.context).expect("Exception in init");
|
||||
pub fn init(&mut self) {
|
||||
self.init
|
||||
.call(&self.context, &[])
|
||||
.expect("Exception in init");
|
||||
}
|
||||
|
||||
pub fn update(&self) {
|
||||
pub fn update(&mut self) {
|
||||
// Handle any promises that have completed before calling update.
|
||||
while let Ok(event) = self.script_receive.try_recv() {
|
||||
match event {
|
||||
// TODO: Capture debugging information.
|
||||
ScriptEvent::AddPromise(handle, promise) => {
|
||||
self.promises.insert(handle, promise);
|
||||
}
|
||||
ScriptEvent::CompletePromise(handle, value_producer) => {
|
||||
if let Some(promise) = self.promises.remove(&handle) {
|
||||
let result = value_producer(&self.context);
|
||||
match result {
|
||||
Ok(v) => {
|
||||
promise.resolve(&self.context, &v);
|
||||
}
|
||||
Err(e) => {
|
||||
let error = e.to_js_error(&self.context);
|
||||
promise.reject(&self.context, &error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tell the runtime to process all pending "jobs".
|
||||
self.context
|
||||
.process_all_jobs()
|
||||
.expect("Error processing async jobs");
|
||||
|
||||
// Now run the update function.
|
||||
self.update
|
||||
.call(&self.context)
|
||||
.call(&self.context, &[])
|
||||
.expect("Exception in update");
|
||||
}
|
||||
|
||||
pub fn render(&self) -> Vec<graphics::GraphicsCommand> {
|
||||
self.draw.call(&self.context).expect("Exception in draw");
|
||||
pub fn render(&mut self) -> Vec<graphics::GraphicsCommand> {
|
||||
self.draw
|
||||
.call(&self.context, &[])
|
||||
.expect("Exception in draw");
|
||||
self.gfx.end_frame();
|
||||
|
||||
let mut commands = Vec::new();
|
||||
|
|
|
|||
|
|
@ -48,13 +48,30 @@ const RES = vec2f(320.0, 240.0); // The logical resolution of the screen.
|
|||
return out;
|
||||
}
|
||||
|
||||
// Fragment shader
|
||||
// Fragment shader....
|
||||
|
||||
@group(0) @binding(0) var t_diffuse : texture_2d<f32>;
|
||||
@group(0) @binding(1) var s_diffuse : sampler;
|
||||
|
||||
@fragment fn fs_main(in : VertexOutput)->@location(0) vec4<f32> {
|
||||
// The "screen" is centered in the window, so anything outside of the
|
||||
// screen borders should be black. But *where are they*?
|
||||
let RES_AR = RES.x / RES.y; // The aspect ratio of the logical screen.
|
||||
let screen_ar = screen.resolution.x / screen.resolution.y;
|
||||
var black_mod = 1.0;
|
||||
if (screen_ar > RES_AR) {
|
||||
// Wider than tall, bars are on the left and right.
|
||||
let active_width = screen.resolution.y * RES_AR;
|
||||
let half_delta = (screen.resolution.x - active_width) / 2.0;
|
||||
if (in.clip_position.x < half_delta ||
|
||||
in.clip_position.x > half_delta + active_width) {
|
||||
black_mod = 0.0;
|
||||
}
|
||||
} else {
|
||||
// Taller than wide, bars are on top and bottom.
|
||||
}
|
||||
|
||||
let dims = vec2f(textureDimensions(t_diffuse));
|
||||
|
||||
return textureSample(t_diffuse, s_diffuse, in.tex_coords / dims);
|
||||
return black_mod * textureSample(t_diffuse, s_diffuse, in.tex_coords / dims);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue