hal/dx12: compute pipelines, update naga

This commit is contained in:
Dzmitry Malyshau
2021-07-11 23:45:49 -04:00
parent 040a602b69
commit 0a609e74c0
10 changed files with 175 additions and 35 deletions

2
Cargo.lock generated
View File

@@ -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",

View File

@@ -36,7 +36,7 @@ thiserror = "1"
[dependencies.naga]
git = "https://github.com/gfx-rs/naga"
rev = "0b9af95793e319817e74a30601cbcd4bad9bb3e6"
rev = "458db0b"
features = ["wgsl-in"]
[dependencies.wgt]

View File

@@ -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]

View File

@@ -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 },

View File

@@ -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);

View File

@@ -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,

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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")
}
}
}

View File

@@ -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]]