d3d12: use hlsl as a fallback pipeline
This commit is contained in:
parent
d6ac2c665d
commit
72c9548c7a
4 changed files with 167 additions and 53 deletions
|
@ -1,21 +1,22 @@
|
|||
use std::collections::VecDeque;
|
||||
use crate::{error, util};
|
||||
use crate::{error, graphics_pipeline, util};
|
||||
use crate::descriptor_heap::{D3D12DescriptorHeap, CpuStagingHeap, ResourceWorkHeap, SamplerWorkHeap, RenderTargetHeap};
|
||||
use crate::samplers::SamplerSet;
|
||||
use crate::luts::LutTexture;
|
||||
use librashader_presets::{ShaderPreset, TextureConfig};
|
||||
use librashader_reflect::back::targets::DXIL;
|
||||
use librashader_reflect::back::targets::{DXIL, HLSL};
|
||||
use librashader_reflect::front::GlslangCompilation;
|
||||
use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact};
|
||||
use librashader_runtime::image::{Image, UVDirection};
|
||||
use rustc_hash::FxHashMap;
|
||||
use std::error::Error;
|
||||
use std::path::Path;
|
||||
use spirv_cross::hlsl::ShaderModel;
|
||||
use windows::core::Interface;
|
||||
use windows::w;
|
||||
use windows::Win32::Foundation::CloseHandle;
|
||||
use windows::Win32::Graphics::Direct3D12::{ID3D12CommandAllocator, ID3D12CommandQueue, ID3D12Device, ID3D12Fence, ID3D12GraphicsCommandList, D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_DESC, D3D12_COMMAND_QUEUE_FLAG_NONE, D3D12_FENCE_FLAG_NONE, ID3D12DescriptorHeap, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET};
|
||||
use windows::Win32::Graphics::Direct3D::Dxc::{CLSID_DxcLibrary, CLSID_DxcValidator, DxcCreateInstance, IDxcLibrary, IDxcValidator};
|
||||
use windows::Win32::Graphics::Direct3D::Dxc::{CLSID_DxcCompiler, CLSID_DxcLibrary, CLSID_DxcValidator, DxcCreateInstance, IDxcCompiler, IDxcLibrary, IDxcUtils, IDxcValidator};
|
||||
use windows::Win32::System::Threading::{CreateEventA, ResetEvent, WaitForSingleObject};
|
||||
use windows::Win32::System::WindowsProgramming::INFINITE;
|
||||
use librashader_common::{ImageFormat, Size, Viewport};
|
||||
|
@ -34,7 +35,8 @@ use crate::quad_render::DrawQuad;
|
|||
use crate::render_target::RenderTarget;
|
||||
use crate::texture::{InputTexture, OutputDescriptor, OutputTexture};
|
||||
|
||||
type ShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<DXIL, GlslangCompilation>>;
|
||||
type DxilShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<DXIL, GlslangCompilation>>;
|
||||
type HlslShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<HLSL, GlslangCompilation>>;
|
||||
|
||||
pub struct FilterMutable {
|
||||
pub(crate) passes_enabled: usize,
|
||||
|
@ -90,11 +92,19 @@ impl FilterChainD3D12 {
|
|||
) -> error::Result<FilterChainD3D12> {
|
||||
let shader_count = preset.shaders.len();
|
||||
let lut_count = preset.textures.len();
|
||||
|
||||
let shader_copy = preset.shaders.clone();
|
||||
|
||||
let (passes, semantics) = DXIL::compile_preset_passes::<GlslangCompilation, Box<dyn Error>>(
|
||||
preset.shaders,
|
||||
&preset.textures,
|
||||
).unwrap();
|
||||
|
||||
let (hlsl_passes, _) = HLSL::compile_preset_passes::<GlslangCompilation, Box<dyn Error>>(
|
||||
shader_copy,
|
||||
&preset.textures,
|
||||
).unwrap();
|
||||
|
||||
let samplers = SamplerSet::new(device)?;
|
||||
let mipmap_gen = D3D12MipmapGen::new(device).unwrap();
|
||||
|
||||
|
@ -115,7 +125,7 @@ impl FilterChainD3D12 {
|
|||
let root_signature = D3D12RootSignature::new(device)?;
|
||||
|
||||
let (texture_heap, sampler_heap, filters)
|
||||
= FilterChainD3D12::init_passes(device, &root_signature, passes, &semantics).unwrap();
|
||||
= FilterChainD3D12::init_passes(device, &root_signature, passes, hlsl_passes, &semantics).unwrap();
|
||||
|
||||
|
||||
|
||||
|
@ -342,17 +352,22 @@ impl FilterChainD3D12 {
|
|||
|
||||
fn init_passes(device: &ID3D12Device,
|
||||
root_signature: &D3D12RootSignature,
|
||||
passes: Vec<ShaderPassMeta>,
|
||||
passes: Vec<DxilShaderPassMeta>,
|
||||
hlsl_passes: Vec<HlslShaderPassMeta>,
|
||||
semantics: &ShaderSemantics,)
|
||||
-> error::Result<(ID3D12DescriptorHeap, ID3D12DescriptorHeap, Vec<FilterPass>)> {
|
||||
-> error::Result<(ID3D12DescriptorHeap, ID3D12DescriptorHeap, Vec<FilterPass>)> {
|
||||
let validator: IDxcValidator = unsafe {
|
||||
DxcCreateInstance(&CLSID_DxcValidator)?
|
||||
};
|
||||
|
||||
let dxc: IDxcLibrary = unsafe {
|
||||
let library: IDxcUtils = unsafe {
|
||||
DxcCreateInstance(&CLSID_DxcLibrary)?
|
||||
};
|
||||
|
||||
let compiler: IDxcCompiler = unsafe {
|
||||
DxcCreateInstance(&CLSID_DxcCompiler)?
|
||||
};
|
||||
|
||||
let mut filters = Vec::new();
|
||||
let shader_count = passes.len();
|
||||
let work_heap =
|
||||
|
@ -372,32 +387,51 @@ impl FilterChainD3D12 {
|
|||
sampler_work_heap.suballocate(MAX_BINDINGS_COUNT as usize)
|
||||
};
|
||||
|
||||
for (index, (((config, source, mut reflect),
|
||||
for (index, ((((config, source, mut dxil), (_, _, mut hlsl)),
|
||||
mut texture_heap), mut sampler_heap))
|
||||
in passes.into_iter()
|
||||
.zip(hlsl_passes)
|
||||
.zip(work_heaps)
|
||||
.zip(sampler_work_heaps)
|
||||
.enumerate() {
|
||||
|
||||
let reflection = reflect.reflect(index, semantics)?;
|
||||
let dxil = reflect.compile(None)?;
|
||||
let dxil_reflection = dxil.reflect(index, semantics)?;
|
||||
let dxil = dxil.compile(Some(librashader_reflect::back::dxil::ShaderModel::ShaderModel6_0))?;
|
||||
|
||||
|
||||
let hlsl_reflection = hlsl.reflect(index, semantics)?;
|
||||
let hlsl = hlsl.compile(Some(ShaderModel::V6_0))?;
|
||||
|
||||
let render_format = if let Some(format) = config.get_format_override() {
|
||||
format
|
||||
} else if source.format != ImageFormat::Unknown {
|
||||
source.format
|
||||
} else {
|
||||
ImageFormat::R8G8B8A8Unorm
|
||||
}.into();
|
||||
|
||||
eprintln!("building pipeline for pass {:?}", index);
|
||||
|
||||
let graphics_pipeline = D3D12GraphicsPipeline::new(device,
|
||||
&dxc,
|
||||
&validator,
|
||||
&dxil,
|
||||
root_signature,
|
||||
if let Some(format) = config.get_format_override() {
|
||||
format
|
||||
} else if source.format != ImageFormat::Unknown {
|
||||
source.format
|
||||
} else {
|
||||
ImageFormat::R8G8B8A8Unorm
|
||||
}.into(),
|
||||
&source
|
||||
)?;
|
||||
/// incredibly cursed.
|
||||
let (reflection, graphics_pipeline) = if let Ok(graphics_pipeline) =
|
||||
D3D12GraphicsPipeline::new_from_dxil(device,
|
||||
&library,
|
||||
&validator,
|
||||
&dxil,
|
||||
root_signature,
|
||||
render_format
|
||||
) {
|
||||
(dxil_reflection, graphics_pipeline)
|
||||
} else {
|
||||
let graphics_pipeline = D3D12GraphicsPipeline::new_from_hlsl(device,
|
||||
&library,
|
||||
&compiler,
|
||||
&hlsl,
|
||||
root_signature,
|
||||
render_format
|
||||
)?;
|
||||
(hlsl_reflection, graphics_pipeline)
|
||||
};
|
||||
|
||||
let uniform_storage = UniformStorage::new(
|
||||
reflection
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
|
||||
use windows::Win32::Foundation::BOOL;
|
||||
use windows::Win32::Graphics::Direct3D12::{D3D12_BLEND_DESC, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, D3D12_BLEND_SRC_ALPHA, D3D12_COLOR_WRITE_ENABLE_ALL, D3D12_CULL_MODE_NONE, D3D12_DESCRIPTOR_RANGE, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, D3D12_FILL_MODE_SOLID, D3D12_GRAPHICS_PIPELINE_STATE_DESC, D3D12_INPUT_LAYOUT_DESC, D3D12_LOGIC_OP_NOOP, D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, D3D12_RASTERIZER_DESC, D3D12_RENDER_TARGET_BLEND_DESC, D3D12_ROOT_DESCRIPTOR, D3D12_ROOT_DESCRIPTOR_TABLE, D3D12_ROOT_PARAMETER, D3D12_ROOT_PARAMETER_0, D3D12_ROOT_PARAMETER_TYPE_CBV, D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, D3D12_ROOT_SIGNATURE_DESC, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT, D3D12_SHADER_BYTECODE, D3D12_SHADER_VISIBILITY_ALL, D3D12_SHADER_VISIBILITY_PIXEL, D3D12SerializeRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, ID3D12Device, ID3D12PipelineState, ID3D12RootSignature};
|
||||
use windows::Win32::Graphics::Direct3D::Dxc::{IDxcBlob, IDxcCompiler, IDxcLibrary, IDxcUtils, IDxcValidator};
|
||||
use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_FORMAT_UNKNOWN, DXGI_SAMPLE_DESC};
|
||||
use librashader_reflect::back::cross::CrossHlslContext;
|
||||
use librashader_reflect::back::dxil::DxilObject;
|
||||
use librashader_reflect::back::ShaderCompilerOutput;
|
||||
use librashader_reflect::reflect::semantics::BindingStage;
|
||||
use crate::{error, util};
|
||||
use crate::quad_render::DrawQuad;
|
||||
|
||||
|
@ -112,25 +115,13 @@ impl D3D12RootSignature {
|
|||
}
|
||||
}
|
||||
impl D3D12GraphicsPipeline {
|
||||
pub fn new(device: &ID3D12Device,
|
||||
library: &IDxcLibrary,
|
||||
validator: &IDxcValidator,
|
||||
shader_assembly: &ShaderCompilerOutput<DxilObject, (Vec<u32>, Vec<u32>)>,
|
||||
root_signature: &D3D12RootSignature,
|
||||
render_format: DXGI_FORMAT,
|
||||
source: &ShaderSource,
|
||||
fn new_from_blobs(
|
||||
device: &ID3D12Device,
|
||||
vertex_dxil: IDxcBlob,
|
||||
fragment_dxil: IDxcBlob,
|
||||
root_signature: &D3D12RootSignature,
|
||||
render_format: DXGI_FORMAT,
|
||||
) -> error::Result<D3D12GraphicsPipeline> {
|
||||
if shader_assembly.vertex.requires_runtime_data() {
|
||||
panic!("vertex needs rt data??")
|
||||
}
|
||||
if shader_assembly.fragment.requires_runtime_data() {
|
||||
panic!("fragment needs rt data??")
|
||||
}
|
||||
let vertex_dxil =
|
||||
util::dxc_validate_shader(library, validator, &shader_assembly.vertex)?;
|
||||
let fragment_dxil =
|
||||
util::dxc_validate_shader(library, validator, &shader_assembly.fragment)?;
|
||||
|
||||
let input_element = DrawQuad::get_spirv_cross_vbo_desc();
|
||||
|
||||
let pipeline_state: ID3D12PipelineState = unsafe {
|
||||
|
@ -207,4 +198,43 @@ impl D3D12GraphicsPipeline {
|
|||
handle: pipeline_state,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_from_dxil(device: &ID3D12Device,
|
||||
library: &IDxcUtils,
|
||||
validator: &IDxcValidator,
|
||||
shader_assembly: &ShaderCompilerOutput<DxilObject, ()>,
|
||||
root_signature: &D3D12RootSignature,
|
||||
render_format: DXGI_FORMAT,
|
||||
) -> error::Result<D3D12GraphicsPipeline> {
|
||||
if shader_assembly.vertex.requires_runtime_data() {
|
||||
panic!("vertex needs rt data??")
|
||||
}
|
||||
if shader_assembly.fragment.requires_runtime_data() {
|
||||
panic!("fragment needs rt data??")
|
||||
}
|
||||
let vertex_dxil =
|
||||
util::dxc_validate_shader(library, validator, &shader_assembly.vertex)?;
|
||||
let fragment_dxil =
|
||||
util::dxc_validate_shader(library, validator, &shader_assembly.fragment)?;
|
||||
|
||||
Self::new_from_blobs(device, vertex_dxil, fragment_dxil, root_signature, render_format)
|
||||
}
|
||||
|
||||
pub fn new_from_hlsl(device: &ID3D12Device,
|
||||
library: &IDxcUtils,
|
||||
dxc: &IDxcCompiler,
|
||||
shader_assembly: &ShaderCompilerOutput<String, CrossHlslContext>,
|
||||
root_signature: &D3D12RootSignature,
|
||||
render_format: DXGI_FORMAT,
|
||||
) -> error::Result<D3D12GraphicsPipeline> {
|
||||
unsafe {
|
||||
|
||||
let vertex_dxil = util::dxc_compile_shader(library, dxc, &shader_assembly.vertex, BindingStage::VERTEX)?;
|
||||
let fragment_dxil =
|
||||
util::dxc_compile_shader(library, dxc,&shader_assembly.fragment, BindingStage::FRAGMENT)?;
|
||||
|
||||
Self::new_from_blobs(device, vertex_dxil, fragment_dxil, root_signature, render_format)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -25,8 +25,8 @@ mod tests {
|
|||
#[test]
|
||||
fn triangle_d3d12() {
|
||||
let sample = hello_triangle::d3d12_hello_triangle::Sample::new(
|
||||
"../test/slang-shaders/crt/crt-royale.slangp",
|
||||
// "../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
|
||||
// "../test/slang-shaders/crt/crt-royale.slangp",
|
||||
"../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
|
||||
&SampleCommandLine {
|
||||
use_warp_device: false,
|
||||
},
|
||||
|
|
|
@ -2,12 +2,13 @@ use std::ffi::CStr;
|
|||
use std::mem::ManuallyDrop;
|
||||
use std::u64;
|
||||
use crate::error;
|
||||
use windows::core::{Interface, PCSTR};
|
||||
use windows::core::{Interface, PCSTR, PCWSTR};
|
||||
use windows::Win32::Graphics::Direct3D::Fxc::{D3DCompile, D3DCOMPILE_DEBUG, D3DCOMPILE_SKIP_OPTIMIZATION};
|
||||
use windows::Win32::Graphics::Direct3D::ID3DBlob;
|
||||
use windows::Win32::Graphics::Direct3D12::{ID3D12Device, D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FEATURE_FORMAT_SUPPORT, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_RESOURCE_BARRIER, D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, D3D12_RESOURCE_BARRIER_FLAG_NONE, D3D12_RESOURCE_BARRIER_0, D3D12_RESOURCE_TRANSITION_BARRIER, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_STATES, D3D12_PLACED_SUBRESOURCE_FOOTPRINT, D3D12_MEMCPY_DEST, D3D12_SUBRESOURCE_DATA, D3D12_RESOURCE_DIMENSION_BUFFER, D3D12_TEXTURE_COPY_LOCATION, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, D3D12_TEXTURE_COPY_LOCATION_0, D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT};
|
||||
use windows::Win32::Graphics::Direct3D::Dxc::{DXC_CP, DxcValidatorFlags_Default, DxcValidatorFlags_InPlaceEdit, DxcValidatorFlags_ModuleOnly, DxcValidatorFlags_ValidMask, IDxcBlob, IDxcBlobUtf8, IDxcLibrary, IDxcValidator};
|
||||
use windows::Win32::Graphics::Direct3D::Dxc::{DXC_CP, DXC_CP_UTF8, DxcValidatorFlags_Default, DxcValidatorFlags_InPlaceEdit, DxcValidatorFlags_ModuleOnly, DxcValidatorFlags_ValidMask, IDxcBlob, IDxcBlobUtf8, IDxcCompiler, IDxcLibrary, IDxcUtils, IDxcValidator};
|
||||
use windows::Win32::Graphics::Dxgi::Common::*;
|
||||
use librashader_reflect::reflect::semantics::BindingStage;
|
||||
use crate::error::assume_d3d12_init;
|
||||
|
||||
/// wtf retroarch?
|
||||
|
@ -145,16 +146,65 @@ pub fn fxc_compile_shader(source: &[u8], entry: &[u8], version: &[u8]) -> error:
|
|||
}
|
||||
}
|
||||
|
||||
pub fn dxc_validate_shader(library: &IDxcLibrary, validator: &IDxcValidator, source: &[u8]) -> error::Result<IDxcBlob> {
|
||||
|
||||
pub fn dxc_compile_shader(library: &IDxcUtils, compiler: &IDxcCompiler, source: &String, profile: BindingStage) -> error::Result<IDxcBlob> {
|
||||
// todo: compile with dxc
|
||||
// let mut source = source.to_vec();
|
||||
|
||||
let include = unsafe {
|
||||
library.CreateDefaultIncludeHandler()?
|
||||
};
|
||||
|
||||
let blob = unsafe {
|
||||
library.CreateBlobFromPinned(
|
||||
source.as_ptr().cast(),
|
||||
source.as_bytes().len() as u32,
|
||||
DXC_CP_UTF8
|
||||
)?
|
||||
};
|
||||
|
||||
let profile = if profile == BindingStage::FRAGMENT {
|
||||
windows::w!("ps_6_0")
|
||||
} else {
|
||||
windows::w!("vs_6_0")
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let result = compiler.Compile(&blob,
|
||||
PCWSTR::null(),
|
||||
windows::w!("main"),
|
||||
profile,
|
||||
None,
|
||||
&[],
|
||||
&include
|
||||
)?;
|
||||
|
||||
if let Ok(buf) = result.GetErrorBuffer() {
|
||||
unsafe {
|
||||
let buf: IDxcBlobUtf8 = buf.cast().unwrap();
|
||||
let buf = std::slice::from_raw_parts(buf.GetBufferPointer()
|
||||
.cast(), buf.GetBufferSize());
|
||||
let str = std::str::from_utf8_unchecked(buf);
|
||||
if str.len() != 0 {
|
||||
eprintln!("{}", str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let result = result.GetResult()?;
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn dxc_validate_shader(library: &IDxcUtils, validator: &IDxcValidator, source: &[u8]) -> error::Result<IDxcBlob> {
|
||||
// todo: compile with dxc
|
||||
// let mut source = source.to_vec();
|
||||
|
||||
let blob = unsafe {
|
||||
library.CreateBlobWithEncodingOnHeapCopy(
|
||||
source.as_ptr().cast(),
|
||||
source.len() as u32,
|
||||
DXC_CP(0)
|
||||
)?
|
||||
library.CreateBlob(source.as_ptr().cast(),
|
||||
source.len() as u32,
|
||||
DXC_CP(0))?
|
||||
};
|
||||
|
||||
unsafe {
|
||||
|
|
Loading…
Add table
Reference in a new issue