mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
hal/dx12: compute pipelines, update naga
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1051,7 +1051,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/gfx-rs/naga?rev=0b9af95793e319817e74a30601cbcd4bad9bb3e6#0b9af95793e319817e74a30601cbcd4bad9bb3e6"
|
||||
source = "git+https://github.com/gfx-rs/naga?rev=458db0b#458db0b5228854dc417283f4b9742e03f25bc492"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bitflags",
|
||||
|
||||
@@ -36,7 +36,7 @@ thiserror = "1"
|
||||
|
||||
[dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "0b9af95793e319817e74a30601cbcd4bad9bb3e6"
|
||||
rev = "458db0b"
|
||||
features = ["wgsl-in"]
|
||||
|
||||
[dependencies.wgt]
|
||||
|
||||
@@ -59,11 +59,11 @@ core-graphics-types = "0.1"
|
||||
|
||||
[dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "0b9af95793e319817e74a30601cbcd4bad9bb3e6"
|
||||
rev = "458db0b"
|
||||
|
||||
[dev-dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "0b9af95793e319817e74a30601cbcd4bad9bb3e6"
|
||||
rev = "458db0b"
|
||||
features = ["wgsl-in"]
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -18,6 +18,7 @@ impl super::Adapter {
|
||||
pub(super) fn expose(
|
||||
adapter: native::WeakPtr<dxgi1_2::IDXGIAdapter2>,
|
||||
library: &Arc<native::D3D12Lib>,
|
||||
instance_flags: crate::InstanceFlags,
|
||||
) -> Option<crate::ExposedAdapter<super::Api>> {
|
||||
// Create the device so that we can get the capabilities.
|
||||
let device = match library.create_device(adapter, native::FeatureLevel::L11_0) {
|
||||
@@ -106,6 +107,7 @@ impl super::Adapter {
|
||||
} else {
|
||||
super::MemoryArchitecture::NonUnified
|
||||
},
|
||||
shader_debug_info: instance_flags.contains(crate::InstanceFlags::DEBUG),
|
||||
};
|
||||
|
||||
// Theoretically vram limited, but in practice 2^20 is the limit
|
||||
@@ -226,7 +228,7 @@ impl super::Adapter {
|
||||
impl crate::Adapter<super::Api> for super::Adapter {
|
||||
unsafe fn open(
|
||||
&self,
|
||||
_features: wgt::Features,
|
||||
features: wgt::Features,
|
||||
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
|
||||
let queue = self
|
||||
.device
|
||||
@@ -238,7 +240,13 @@ impl crate::Adapter<super::Api> for super::Adapter {
|
||||
)
|
||||
.into_device_result("Queue creation")?;
|
||||
|
||||
let device = super::Device::new(self.device, queue, self.private_caps, &self.library)?;
|
||||
let device = super::Device::new(
|
||||
self.device,
|
||||
queue,
|
||||
features,
|
||||
self.private_caps,
|
||||
&self.library,
|
||||
)?;
|
||||
Ok(crate::OpenDevice {
|
||||
device,
|
||||
queue: super::Queue { raw: queue },
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{conv, HResult as _, Resource};
|
||||
use super::{conv, HResult as _};
|
||||
use std::{mem, ops::Range, ptr};
|
||||
use winapi::um::d3d12;
|
||||
|
||||
@@ -637,7 +637,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
self.list.unwrap().EndEvent()
|
||||
}
|
||||
|
||||
unsafe fn set_render_pipeline(&mut self, pipeline: &Resource) {}
|
||||
unsafe fn set_render_pipeline(&mut self, pipeline: &super::RenderPipeline) {}
|
||||
|
||||
unsafe fn set_index_buffer<'a>(
|
||||
&mut self,
|
||||
@@ -795,7 +795,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
self.end_pass();
|
||||
}
|
||||
|
||||
unsafe fn set_compute_pipeline(&mut self, pipeline: &Resource) {}
|
||||
unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) {}
|
||||
|
||||
unsafe fn dispatch(&mut self, count: [u32; 3]) {
|
||||
self.list.unwrap().dispatch(count);
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
use super::{conv, descriptor, HResult as _};
|
||||
use parking_lot::Mutex;
|
||||
use std::{mem, ptr, slice, sync::Arc};
|
||||
use std::{ffi, mem, ptr, slice, sync::Arc};
|
||||
use winapi::{
|
||||
shared::{dxgiformat, dxgitype, winerror},
|
||||
um::{d3d12, d3d12sdklayers, synchapi, winbase},
|
||||
um::{d3d12, d3d12sdklayers, d3dcompiler, synchapi, winbase},
|
||||
Interface,
|
||||
};
|
||||
|
||||
//TODO: remove this
|
||||
use super::Resource;
|
||||
|
||||
const D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING: u32 = 0x1688;
|
||||
|
||||
impl super::Device {
|
||||
pub(super) fn new(
|
||||
raw: native::Device,
|
||||
present_queue: native::CommandQueue,
|
||||
features: wgt::Features,
|
||||
private_caps: super::PrivateCapabilities,
|
||||
library: &Arc<native::D3D12Lib>,
|
||||
) -> Result<Self, crate::DeviceError> {
|
||||
@@ -82,6 +80,7 @@ impl super::Device {
|
||||
let capacity_samplers = 2_048;
|
||||
|
||||
let shared = super::DeviceShared {
|
||||
features,
|
||||
zero_buffer,
|
||||
cmd_signatures: super::CommandSignatures {
|
||||
draw: raw
|
||||
@@ -508,6 +507,79 @@ impl super::Device {
|
||||
.CreateDepthStencilView(texture.resource.as_mut_ptr(), &raw_desc, handle.raw);
|
||||
handle
|
||||
}
|
||||
|
||||
fn load_shader(
|
||||
&self,
|
||||
stage: &crate::ProgrammableStage<super::Api>,
|
||||
layout: &super::PipelineLayout,
|
||||
naga_stage: naga::ShaderStage,
|
||||
) -> Result<native::Blob, crate::PipelineError> {
|
||||
use naga::back::hlsl;
|
||||
|
||||
let stage_bit = crate::util::map_naga_stage(naga_stage);
|
||||
let module = &stage.module.naga.module;
|
||||
//TODO: reuse the writer
|
||||
let mut source = String::new();
|
||||
let mut writer = hlsl::Writer::new(&mut source, &layout.naga_options);
|
||||
let reflection_info = writer
|
||||
.write(module, &stage.module.naga.info)
|
||||
.map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("HLSL: {:?}", e)))?;
|
||||
|
||||
let full_stage = format!(
|
||||
"{}_{}\0",
|
||||
naga_stage.to_hlsl_str(),
|
||||
layout.naga_options.shader_model.to_str()
|
||||
);
|
||||
let raw_ep = ffi::CString::new(stage.entry_point).unwrap();
|
||||
|
||||
let mut shader_data = native::Blob::null();
|
||||
let mut error = native::Blob::null();
|
||||
let mut compile_flags = d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS;
|
||||
if self.private_caps.shader_debug_info {
|
||||
compile_flags |= d3dcompiler::D3DCOMPILE_DEBUG;
|
||||
}
|
||||
if self
|
||||
.shared
|
||||
.features
|
||||
.contains(wgt::Features::UNSIZED_BINDING_ARRAY)
|
||||
{
|
||||
compile_flags |= d3dcompiler::D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES;
|
||||
}
|
||||
|
||||
let hr = unsafe {
|
||||
d3dcompiler::D3DCompile(
|
||||
source.as_ptr() as *const _,
|
||||
source.len(),
|
||||
ptr::null(),
|
||||
ptr::null(),
|
||||
ptr::null_mut(),
|
||||
raw_ep.as_ptr(),
|
||||
full_stage.as_ptr() as *const i8,
|
||||
compile_flags,
|
||||
0,
|
||||
shader_data.mut_void() as *mut *mut _,
|
||||
error.mut_void() as *mut *mut _,
|
||||
)
|
||||
};
|
||||
|
||||
match hr.into_result() {
|
||||
Ok(()) => Ok(shader_data),
|
||||
Err(e) => {
|
||||
let message = unsafe {
|
||||
let slice = slice::from_raw_parts(
|
||||
error.GetBufferPointer() as *const u8,
|
||||
error.GetBufferSize(),
|
||||
);
|
||||
String::from_utf8_lossy(slice)
|
||||
};
|
||||
let full_msg = format!("D3DCompile error ({}): {}", e, message);
|
||||
unsafe {
|
||||
error.destroy();
|
||||
}
|
||||
Err(crate::PipelineError::Linkage(stage_bit, full_msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::Device<super::Api> for super::Device {
|
||||
@@ -1087,6 +1159,9 @@ impl crate::Device<super::Api> for super::Device {
|
||||
Ok(super::PipelineLayout {
|
||||
raw,
|
||||
bind_group_infos,
|
||||
naga_options: naga::back::hlsl::Options {
|
||||
shader_model: naga::back::hlsl::ShaderModel::V5_1,
|
||||
},
|
||||
})
|
||||
}
|
||||
unsafe fn destroy_pipeline_layout(&self, pipeline_layout: super::PipelineLayout) {
|
||||
@@ -1247,24 +1322,58 @@ impl crate::Device<super::Api> for super::Device {
|
||||
&self,
|
||||
desc: &crate::ShaderModuleDescriptor,
|
||||
shader: crate::ShaderInput,
|
||||
) -> Result<Resource, crate::ShaderError> {
|
||||
Ok(Resource)
|
||||
) -> Result<super::ShaderModule, crate::ShaderError> {
|
||||
match shader {
|
||||
crate::ShaderInput::Naga(naga) => Ok(super::ShaderModule { naga }),
|
||||
crate::ShaderInput::SpirV(_) => {
|
||||
panic!("SPIRV_SHADER_PASSTHROUGH is not enabled for this backend")
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe fn destroy_shader_module(&self, module: Resource) {}
|
||||
unsafe fn destroy_shader_module(&self, _module: super::ShaderModule) {
|
||||
// just drop
|
||||
}
|
||||
|
||||
unsafe fn create_render_pipeline(
|
||||
&self,
|
||||
desc: &crate::RenderPipelineDescriptor<super::Api>,
|
||||
) -> Result<Resource, crate::PipelineError> {
|
||||
Ok(Resource)
|
||||
) -> Result<super::RenderPipeline, crate::PipelineError> {
|
||||
unimplemented!()
|
||||
}
|
||||
unsafe fn destroy_render_pipeline(&self, pipeline: Resource) {}
|
||||
unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
|
||||
pipeline.raw.destroy();
|
||||
}
|
||||
|
||||
unsafe fn create_compute_pipeline(
|
||||
&self,
|
||||
desc: &crate::ComputePipelineDescriptor<super::Api>,
|
||||
) -> Result<Resource, crate::PipelineError> {
|
||||
Ok(Resource)
|
||||
) -> Result<super::ComputePipeline, crate::PipelineError> {
|
||||
let cs = self.load_shader(&desc.stage, desc.layout, naga::ShaderStage::Compute)?;
|
||||
|
||||
let pair = self.raw.create_compute_pipeline_state(
|
||||
desc.layout.raw,
|
||||
native::Shader::from_blob(cs),
|
||||
0,
|
||||
native::CachedPSO::null(),
|
||||
native::PipelineStateFlags::empty(),
|
||||
);
|
||||
|
||||
cs.destroy();
|
||||
|
||||
let raw = pair.into_result().map_err(|err| {
|
||||
crate::PipelineError::Linkage(wgt::ShaderStages::COMPUTE, err.into_owned())
|
||||
})?;
|
||||
|
||||
if let Some(name) = desc.label {
|
||||
let cwstr = conv::map_label(name);
|
||||
raw.SetName(cwstr.as_ptr());
|
||||
}
|
||||
|
||||
Ok(super::ComputePipeline { raw })
|
||||
}
|
||||
unsafe fn destroy_compute_pipeline(&self, pipeline: super::ComputePipeline) {
|
||||
pipeline.raw.destroy();
|
||||
}
|
||||
unsafe fn destroy_compute_pipeline(&self, pipeline: Resource) {}
|
||||
|
||||
unsafe fn create_query_set(
|
||||
&self,
|
||||
|
||||
@@ -133,6 +133,7 @@ impl crate::Instance<super::Api> for super::Instance {
|
||||
factory,
|
||||
library: Arc::new(lib_main),
|
||||
lib_dxgi,
|
||||
flags: desc.flags,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -218,7 +219,7 @@ impl crate::Instance<super::Api> for super::Instance {
|
||||
}
|
||||
};
|
||||
|
||||
adapters.extend(super::Adapter::expose(raw, &self.library));
|
||||
adapters.extend(super::Adapter::expose(raw, &self.library, self.flags));
|
||||
}
|
||||
adapters
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ mod instance;
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use parking_lot::Mutex;
|
||||
use std::{borrow::Cow, mem, ptr, sync::Arc};
|
||||
use std::{borrow::Cow, mem, num::NonZeroU32, ptr, sync::Arc};
|
||||
use winapi::{
|
||||
shared::{dxgi, dxgi1_2, dxgi1_4, dxgiformat, dxgitype, windef, winerror},
|
||||
um::{d3d12, synchapi, winbase, winnt},
|
||||
@@ -25,9 +25,6 @@ use winapi::{
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Api;
|
||||
//TODO: remove these temporaries
|
||||
#[derive(Debug)]
|
||||
pub struct Resource;
|
||||
|
||||
impl crate::Api for Api {
|
||||
type Instance = Instance;
|
||||
@@ -50,9 +47,9 @@ impl crate::Api for Api {
|
||||
type BindGroupLayout = BindGroupLayout;
|
||||
type BindGroup = BindGroup;
|
||||
type PipelineLayout = PipelineLayout;
|
||||
type ShaderModule = Resource;
|
||||
type RenderPipeline = Resource;
|
||||
type ComputePipeline = Resource;
|
||||
type ShaderModule = ShaderModule;
|
||||
type RenderPipeline = RenderPipeline;
|
||||
type ComputePipeline = ComputePipeline;
|
||||
}
|
||||
|
||||
trait HResult<O> {
|
||||
@@ -100,6 +97,7 @@ pub struct Instance {
|
||||
factory: native::Factory4,
|
||||
library: Arc<native::D3D12Lib>,
|
||||
lib_dxgi: native::DxgiLib,
|
||||
flags: crate::InstanceFlags,
|
||||
}
|
||||
|
||||
unsafe impl Send for Instance {}
|
||||
@@ -133,6 +131,7 @@ enum MemoryArchitecture {
|
||||
struct PrivateCapabilities {
|
||||
heterogeneous_resource_heaps: bool,
|
||||
memory_architecture: MemoryArchitecture,
|
||||
shader_debug_info: bool,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -176,6 +175,7 @@ impl CommandSignatures {
|
||||
}
|
||||
|
||||
struct DeviceShared {
|
||||
features: wgt::Features,
|
||||
zero_buffer: native::Resource,
|
||||
cmd_signatures: CommandSignatures,
|
||||
heap_views: descriptor::GeneralHeap,
|
||||
@@ -420,11 +420,33 @@ pub struct PipelineLayout {
|
||||
// Storing for each associated bind group, which tables we created
|
||||
// in the root signature. This is required for binding descriptor sets.
|
||||
bind_group_infos: ArrayVec<BindGroupInfo, crate::MAX_BIND_GROUPS>,
|
||||
naga_options: naga::back::hlsl::Options,
|
||||
}
|
||||
|
||||
unsafe impl Send for PipelineLayout {}
|
||||
unsafe impl Sync for PipelineLayout {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ShaderModule {
|
||||
naga: crate::NagaShader,
|
||||
}
|
||||
|
||||
pub struct RenderPipeline {
|
||||
raw: native::PipelineState,
|
||||
topology: d3d12::D3D12_PRIMITIVE_TOPOLOGY,
|
||||
vertex_strides: [Option<NonZeroU32>; crate::MAX_VERTEX_BUFFERS],
|
||||
}
|
||||
|
||||
unsafe impl Send for RenderPipeline {}
|
||||
unsafe impl Sync for RenderPipeline {}
|
||||
|
||||
pub struct ComputePipeline {
|
||||
raw: native::PipelineState,
|
||||
}
|
||||
|
||||
unsafe impl Send for ComputePipeline {}
|
||||
unsafe impl Sync for ComputePipeline {}
|
||||
|
||||
impl SwapChain {
|
||||
unsafe fn release_resources(self) -> native::WeakPtr<dxgi1_4::IDXGISwapChain3> {
|
||||
for resource in self.resources {
|
||||
|
||||
@@ -676,7 +676,7 @@ impl crate::Device<super::Api> for super::Device {
|
||||
match shader {
|
||||
crate::ShaderInput::Naga(naga) => Ok(super::ShaderModule { naga }),
|
||||
crate::ShaderInput::SpirV(_) => {
|
||||
unreachable!("SPIRV_SHADER_PASSTHROUGH is not enabled for this backend")
|
||||
panic!("SPIRV_SHADER_PASSTHROUGH is not enabled for this backend")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,19 +73,19 @@ env_logger = "0.8"
|
||||
|
||||
[dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "0b9af95793e319817e74a30601cbcd4bad9bb3e6"
|
||||
rev = "458db0b"
|
||||
optional = true
|
||||
|
||||
# used to test all the example shaders
|
||||
[dev-dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "0b9af95793e319817e74a30601cbcd4bad9bb3e6"
|
||||
rev = "458db0b"
|
||||
features = ["wgsl-in"]
|
||||
|
||||
# used to generate SPIR-V for the Web target
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "0b9af95793e319817e74a30601cbcd4bad9bb3e6"
|
||||
rev = "458db0b"
|
||||
features = ["wgsl-in", "spv-out"]
|
||||
|
||||
[[example]]
|
||||
|
||||
Reference in New Issue
Block a user