diff options
author | Kunal Mohan <kunalmohan99@gmail.com> | 2020-05-23 22:04:09 +0530 |
---|---|---|
committer | Kunal Mohan <kunalmohan99@gmail.com> | 2020-05-26 00:00:35 +0530 |
commit | dd04716b852471ba75e4bf44ced0e2d481e99ab2 (patch) | |
tree | 31262d46335d21ef23bc50faab54522f6b902253 /components/script/dom/gpudevice.rs | |
parent | 43f29fe0cefe2e7ce42e4172d6cb2a4ebe72ab0f (diff) | |
download | servo-dd04716b852471ba75e4bf44ced0e2d481e99ab2.tar.gz servo-dd04716b852471ba75e4bf44ced0e2d481e99ab2.zip |
Add GPUSampler to WebGPU implementation
Add dom_struct and webidl for GPUSampler, implement GPUDevice.createSampler() method.
Diffstat (limited to 'components/script/dom/gpudevice.rs')
-rw-r--r-- | components/script/dom/gpudevice.rs | 110 |
1 files changed, 89 insertions, 21 deletions
diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index fa773a74694..2a5c84e99af 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -16,6 +16,9 @@ use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{ GPUCommandEncoderDescriptor, GPUDeviceMethods, }; use crate::dom::bindings::codegen::Bindings::GPUPipelineLayoutBinding::GPUPipelineLayoutDescriptor; +use crate::dom::bindings::codegen::Bindings::GPUSamplerBinding::{ + GPUAddressMode, GPUCompareFunction, GPUFilterMode, GPUSamplerDescriptor, +}; use crate::dom::bindings::codegen::Bindings::GPUShaderModuleBinding::GPUShaderModuleDescriptor; use crate::dom::bindings::codegen::UnionTypes::Uint32ArrayOrString::{String, Uint32Array}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; @@ -32,6 +35,7 @@ use crate::dom::gpucommandencoder::GPUCommandEncoder; use crate::dom::gpucomputepipeline::GPUComputePipeline; use crate::dom::gpupipelinelayout::GPUPipelineLayout; use crate::dom::gpuqueue::GPUQueue; +use crate::dom::gpusampler::GPUSampler; use crate::dom::gpushadermodule::GPUShaderModule; use crate::script_runtime::JSContext as SafeJSContext; use dom_struct::dom_struct; @@ -44,11 +48,7 @@ use std::ptr::{self, NonNull}; use webgpu::wgpu::binding_model::{ BindGroupEntry, BindGroupLayoutEntry, BindingResource, BindingType, BufferBinding, }; -use webgpu::wgt::{ - BufferDescriptor, BufferUsage, ShaderStage, TextureComponentType, TextureFormat, - TextureViewDimension, -}; -use webgpu::{WebGPU, WebGPUDevice, WebGPUQueue, WebGPURequest}; +use webgpu::{wgt, WebGPU, WebGPUDevice, WebGPUQueue, WebGPURequest, WebGPUSampler}; #[dom_struct] pub struct GPUDevice { @@ -110,15 +110,15 @@ impl GPUDevice { fn validate_buffer_descriptor( &self, descriptor: &GPUBufferDescriptor, - ) -> (bool, BufferDescriptor<std::string::String>) { + ) -> (bool, wgt::BufferDescriptor<std::string::String>) { // TODO: Record a validation error in the current scope if the descriptor is invalid. - let wgpu_usage = BufferUsage::from_bits(descriptor.usage); + let wgpu_usage = wgt::BufferUsage::from_bits(descriptor.usage); let valid = wgpu_usage.is_some() && descriptor.size > 0; if valid { ( true, - BufferDescriptor { + wgt::BufferDescriptor { size: descriptor.size, usage: wgpu_usage.unwrap(), label: Default::default(), @@ -127,9 +127,9 @@ impl GPUDevice { } else { ( false, - BufferDescriptor { + wgt::BufferDescriptor { size: 0, - usage: BufferUsage::STORAGE, + usage: wgt::BufferUsage::empty(), label: Default::default(), }, ) @@ -280,9 +280,9 @@ impl GPUDeviceMethods for GPUDevice { max_storage_textures_per_shader_stage: limits.maxStorageTexturesPerShaderStage as i32, max_samplers_per_shader_stage: limits.maxSamplersPerShaderStage as i32, }; - validation_map.insert(ShaderStage::VERTEX, maxLimits.clone()); - validation_map.insert(ShaderStage::FRAGMENT, maxLimits.clone()); - validation_map.insert(ShaderStage::COMPUTE, maxLimits.clone()); + validation_map.insert(wgt::ShaderStage::VERTEX, maxLimits.clone()); + validation_map.insert(wgt::ShaderStage::FRAGMENT, maxLimits.clone()); + validation_map.insert(wgt::ShaderStage::COMPUTE, maxLimits.clone()); let mut max_dynamic_uniform_buffers_per_pipeline_layout = limits.maxDynamicUniformBuffersPerPipelineLayout as i32; let mut max_dynamic_storage_buffers_per_pipeline_layout = @@ -295,11 +295,11 @@ impl GPUDeviceMethods for GPUDevice { .map(|bind| { // TODO: binding must be >= 0 storeBindings.insert(bind.binding); - let visibility = match ShaderStage::from_bits(bind.visibility) { + let visibility = match wgt::ShaderStage::from_bits(bind.visibility) { Some(visibility) => visibility, None => { valid = false; - ShaderStage::from_bits(0).unwrap() + wgt::ShaderStage::from_bits(0).unwrap() }, }; let ty = match bind.type_ { @@ -375,9 +375,9 @@ impl GPUDeviceMethods for GPUDevice { has_dynamic_offset: bind.hasDynamicOffset, multisampled: bind.multisampled, // Use as default for now - texture_component_type: TextureComponentType::Float, - storage_texture_format: TextureFormat::Rgba8UnormSrgb, - view_dimension: TextureViewDimension::D2, + texture_component_type: wgt::TextureComponentType::Float, + storage_texture_format: wgt::TextureFormat::Rgba8UnormSrgb, + view_dimension: wgt::TextureViewDimension::D2, } }) .collect::<Vec<BindGroupLayoutEntry>>(); @@ -507,7 +507,7 @@ impl GPUDeviceMethods for GPUDevice { let buffer_size = bind.resource.buffer.size(); let resource_size = bind.resource.size.unwrap_or(buffer_size); let length = bind.resource.offset.checked_add(resource_size); - let usage = BufferUsage::from_bits(bind.resource.buffer.usage()).unwrap(); + let usage = wgt::BufferUsage::from_bits(bind.resource.buffer.usage()).unwrap(); length.is_some() && buffer_size >= length.unwrap() && // check buffer OOB @@ -515,9 +515,9 @@ impl GPUDeviceMethods for GPUDevice { bind.resource.offset < buffer_size && // on Vulkan offset must be less than size of buffer descriptor.layout.bindings().iter().any(|layout_bind| { let ty = match layout_bind.type_ { - GPUBindingType::Storage_buffer => BufferUsage::STORAGE, + GPUBindingType::Storage_buffer => wgt::BufferUsage::STORAGE, // GPUBindingType::Readonly_storage_buffer => BufferUsage::STORAGE_READ, - GPUBindingType::Uniform_buffer => BufferUsage::UNIFORM, + GPUBindingType::Uniform_buffer => wgt::BufferUsage::UNIFORM, _ => unimplemented!(), }; // binding must be present in layout @@ -641,4 +641,72 @@ impl GPUDeviceMethods for GPUDevice { GPUCommandEncoder::new(&self.global(), self.channel.clone(), encoder, true) } + /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createsampler + fn CreateSampler(&self, descriptor: &GPUSamplerDescriptor) -> DomRoot<GPUSampler> { + let sampler_id = self + .global() + .wgpu_id_hub() + .lock() + .create_sampler_id(self.device.0.backend()); + let compare_enable = descriptor.compare.is_some(); + let desc = wgt::SamplerDescriptor { + label: Default::default(), + address_mode_u: assign_address_mode(descriptor.addressModeU), + address_mode_v: assign_address_mode(descriptor.addressModeV), + address_mode_w: assign_address_mode(descriptor.addressModeW), + mag_filter: assign_filter_mode(descriptor.magFilter), + min_filter: assign_filter_mode(descriptor.minFilter), + mipmap_filter: assign_filter_mode(descriptor.mipmapFilter), + lod_min_clamp: *descriptor.lodMinClamp, + lod_max_clamp: *descriptor.lodMaxClamp, + compare: if let Some(c) = descriptor.compare { + match c { + GPUCompareFunction::Never => wgt::CompareFunction::Never, + GPUCompareFunction::Less => wgt::CompareFunction::Less, + GPUCompareFunction::Equal => wgt::CompareFunction::Equal, + GPUCompareFunction::Less_equal => wgt::CompareFunction::LessEqual, + GPUCompareFunction::Greater => wgt::CompareFunction::Greater, + GPUCompareFunction::Not_equal => wgt::CompareFunction::NotEqual, + GPUCompareFunction::Greater_equal => wgt::CompareFunction::GreaterEqual, + GPUCompareFunction::Always => wgt::CompareFunction::Always, + } + } else { + wgt::CompareFunction::Undefined + }, + }; + self.channel + .0 + .send(WebGPURequest::CreateSampler { + device_id: self.device.0, + sampler_id, + descriptor: desc, + }) + .expect("Failed to create WebGPU sampler"); + + let sampler = WebGPUSampler(sampler_id); + + GPUSampler::new( + &self.global(), + self.channel.clone(), + self.device, + compare_enable, + sampler, + true, + ) + } +} + +fn assign_address_mode(address_mode: GPUAddressMode) -> wgt::AddressMode { + match address_mode { + GPUAddressMode::Clamp_to_edge => wgt::AddressMode::ClampToEdge, + GPUAddressMode::Repeat => wgt::AddressMode::Repeat, + GPUAddressMode::Mirror_repeat => wgt::AddressMode::MirrorRepeat, + } +} + +fn assign_filter_mode(filter_mode: GPUFilterMode) -> wgt::FilterMode { + match filter_mode { + GPUFilterMode::Nearest => wgt::FilterMode::Nearest, + GPUFilterMode::Linear => wgt::FilterMode::Linear, + } } |