d3d11: load shaders and buffers

This commit is contained in:
chyyran 2022-11-26 23:57:22 -05:00
parent 2e5c9c835a
commit f0bc2d92af
6 changed files with 39 additions and 28 deletions

View file

@ -53,8 +53,10 @@ Please report an issue if you run into a shader that works in RetroArch, but not
* Copying of in-flight framebuffer contents is done via `glBlitFramebuffer` rather than drawing a quad into an intermediate FBO. * Copying of in-flight framebuffer contents is done via `glBlitFramebuffer` rather than drawing a quad into an intermediate FBO.
* Sampler objects are used rather than `glTexParameter`. * Sampler objects are used rather than `glTexParameter`.
* Sampler inputs and outputs are not renamed. This is useful for debugging shaders in RenderDoc. * Sampler inputs and outputs are not renamed. This is useful for debugging shaders in RenderDoc.
* UBO and Push Constant Buffer sizes are padded to 16-byte boundaries.
* Direct3D 11 * Direct3D 11
* The staging buffer is not kept around when loading static textures (LUTs). * The staging buffer is not kept around when loading static textures (LUTs).
* HDR10 support is not part of the shader runtime and is not supported.
## License ## License
The core parts of librashader such as the preprocessor, the preset parser, The core parts of librashader such as the preprocessor, the preset parser,

View file

@ -142,12 +142,15 @@ impl BindingStage {
#[derive(Debug)] #[derive(Debug)]
pub struct UboReflection { pub struct UboReflection {
pub binding: u32, pub binding: u32,
/// Get this size of this UBO buffer.
/// The size returned by reflection is always aligned to a 16 byte boundary.
pub size: u32, pub size: u32,
pub stage_mask: BindingStage, pub stage_mask: BindingStage,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct PushReflection { pub struct PushReflection {
/// The size returned by reflection is always aligned to a 16 byte boundary.
pub size: u32, pub size: u32,
pub stage_mask: BindingStage, pub stage_mask: BindingStage,
} }

View file

@ -17,7 +17,7 @@ use windows::core::PCSTR;
use windows::s; use windows::s;
use windows::Win32::Graphics::Direct3D11::{D3D11_BIND_CONSTANT_BUFFER, D3D11_BIND_SHADER_RESOURCE, D3D11_BUFFER_DESC, D3D11_CPU_ACCESS_WRITE, D3D11_INPUT_ELEMENT_DESC, D3D11_INPUT_PER_VERTEX_DATA, D3D11_RESOURCE_MISC_FLAG, D3D11_RESOURCE_MISC_GENERATE_MIPS, D3D11_SAMPLER_DESC, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, D3D11_USAGE_DYNAMIC, ID3D11Buffer, ID3D11Device, ID3D11DeviceContext}; use windows::Win32::Graphics::Direct3D11::{D3D11_BIND_CONSTANT_BUFFER, D3D11_BIND_SHADER_RESOURCE, D3D11_BUFFER_DESC, D3D11_CPU_ACCESS_WRITE, D3D11_INPUT_ELEMENT_DESC, D3D11_INPUT_PER_VERTEX_DATA, D3D11_RESOURCE_MISC_FLAG, D3D11_RESOURCE_MISC_GENERATE_MIPS, D3D11_SAMPLER_DESC, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, D3D11_USAGE_DYNAMIC, ID3D11Buffer, ID3D11Device, ID3D11DeviceContext};
use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SAMPLE_DESC}; use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SAMPLE_DESC};
use crate::filter_pass::{ConstantBuffer, FilterPass}; use crate::filter_pass::{ConstantBuffer, ConstantBufferBinding, FilterPass};
use crate::samplers::SamplerSet; use crate::samplers::SamplerSet;
use crate::util; use crate::util;
use crate::util::d3d11_compile_bound_shader; use crate::util::d3d11_compile_bound_shader;
@ -40,6 +40,7 @@ struct D3D11VertexLayout {
pub struct FilterChain { pub struct FilterChain {
pub common: FilterCommon, pub common: FilterCommon,
pub passes: Vec<FilterPass>,
} }
pub struct Direct3D11 { pub struct Direct3D11 {
@ -104,7 +105,7 @@ impl FilterChain {
} }
fn create_constant_buffer(device: &ID3D11Device, size: u32) -> util::Result<ID3D11Buffer> { fn create_constant_buffer(device: &ID3D11Device, size: u32) -> util::Result<ID3D11Buffer> {
eprintln!("{size}");
unsafe { unsafe {
let buffer = device.CreateBuffer(&D3D11_BUFFER_DESC { let buffer = device.CreateBuffer(&D3D11_BUFFER_DESC {
ByteWidth: size, ByteWidth: size,
@ -123,7 +124,7 @@ impl FilterChain {
device: &ID3D11Device, device: &ID3D11Device,
passes: Vec<ShaderPassMeta>, passes: Vec<ShaderPassMeta>,
semantics: &ReflectSemantics, semantics: &ReflectSemantics,
) -> util::Result<()> ) -> util::Result<Vec<FilterPass>>
{ {
// let mut filters = Vec::new(); // let mut filters = Vec::new();
let mut filters = Vec::new(); let mut filters = Vec::new();
@ -172,28 +173,24 @@ impl FilterChain {
let ubo_cbuffer = if let Some(ubo) = &reflection.ubo && ubo.size != 0 { let ubo_cbuffer = if let Some(ubo) = &reflection.ubo && ubo.size != 0 {
let size = (ubo.size + 0xf) & !0xf; let buffer = FilterChain::create_constant_buffer(device, ubo.size)?;
let buffer = FilterChain::create_constant_buffer(device, size)?; Some(ConstantBufferBinding {
Some(ConstantBuffer {
binding: ubo.binding, binding: ubo.binding,
size: ubo.size, size: ubo.size,
stage_mask: ubo.stage_mask, stage_mask: ubo.stage_mask,
buffer, buffer,
storage: vec![0u8; size as usize].into_boxed_slice(),
}) })
} else { } else {
None None
}; };
let push_cbuffer = if let Some(push) = &reflection.push_constant && push.size != 0 { let push_cbuffer = if let Some(push) = &reflection.push_constant && push.size != 0 {
let size = (push.size + 0xf) & !0xf; let buffer = FilterChain::create_constant_buffer(device, push.size)?;
let buffer = FilterChain::create_constant_buffer(device, size)?; Some(ConstantBufferBinding {
Some(ConstantBuffer {
binding: if ubo_cbuffer.is_some() { 1 } else { 0 }, binding: if ubo_cbuffer.is_some() { 1 } else { 0 },
size: push.size, size: push.size,
stage_mask: push.stage_mask, stage_mask: push.stage_mask,
buffer, buffer,
storage: vec![0u8; size as usize].into_boxed_slice(),
}) })
} else { } else {
None None
@ -228,14 +225,14 @@ impl FilterChain {
vertex_layout: vertex_ia, vertex_layout: vertex_ia,
pixel_shader: ps, pixel_shader: ps,
uniform_bindings, uniform_bindings,
uniform_buffer: ubo_cbuffer, uniform_buffer: ConstantBuffer::new(ubo_cbuffer),
push_buffer: push_cbuffer, push_buffer: ConstantBuffer::new(push_cbuffer),
source, source,
config: config.clone(), config: config.clone(),
}) })
} }
Ok(()) Ok(filters)
} }
/// Load a filter chain from a pre-parsed `ShaderPreset`. /// Load a filter chain from a pre-parsed `ShaderPreset`.
pub fn load_from_preset(device: &ID3D11Device, preset: ShaderPreset) -> util::Result<FilterChain> { pub fn load_from_preset(device: &ID3D11Device, preset: ShaderPreset) -> util::Result<FilterChain> {
@ -244,7 +241,7 @@ impl FilterChain {
let samplers = SamplerSet::new(device)?; let samplers = SamplerSet::new(device)?;
// initialize passes // initialize passes
let filters = FilterChain::init_passes(device, passes, &semantics)?; let filters = FilterChain::init_passes(device, passes, &semantics).unwrap();
// let default_filter = filters.first().map(|f| f.config.filter).unwrap_or_default(); // let default_filter = filters.first().map(|f| f.config.filter).unwrap_or_default();
// let default_wrap = filters // let default_wrap = filters
@ -271,7 +268,7 @@ impl FilterChain {
// FilterChain::init_history(&filters, default_filter, default_wrap); // FilterChain::init_history(&filters, default_filter, default_wrap);
Ok(FilterChain { Ok(FilterChain {
// passes: filters, passes: filters,
// output_framebuffers: output_framebuffers.into_boxed_slice(), // output_framebuffers: output_framebuffers.into_boxed_slice(),
// feedback_framebuffers: feedback_framebuffers.into_boxed_slice(), // feedback_framebuffers: feedback_framebuffers.into_boxed_slice(),
// history_framebuffers, // history_framebuffers,
@ -285,7 +282,6 @@ impl FilterChain {
// we don't need the reflect semantics once all locations have been bound per pass. // we don't need the reflect semantics once all locations have been bound per pass.
// semantics, // semantics,
preset, preset,
// luts,
// output_textures: output_textures.into_boxed_slice(), // output_textures: output_textures.into_boxed_slice(),
// feedback_textures: feedback_textures.into_boxed_slice(), // feedback_textures: feedback_textures.into_boxed_slice(),
// history_textures, // history_textures,

View file

@ -12,17 +12,32 @@ use librashader_reflect::reflect::semantics::{
use librashader_reflect::reflect::ShaderReflection; use librashader_reflect::reflect::ShaderReflection;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::error::Error; use std::error::Error;
use windows::core::ConstBuffer;
use windows::Win32::Graphics::Direct3D::ID3DBlob; use windows::Win32::Graphics::Direct3D::ID3DBlob;
use windows::Win32::Graphics::Direct3D11::{ID3D11Buffer, ID3D11PixelShader, ID3D11SamplerState, ID3D11ShaderResourceView, ID3D11VertexShader, D3D11_MAP_WRITE_DISCARD, ID3D11InputLayout}; use windows::Win32::Graphics::Direct3D11::{ID3D11Buffer, ID3D11PixelShader, ID3D11SamplerState, ID3D11ShaderResourceView, ID3D11VertexShader, D3D11_MAP_WRITE_DISCARD, ID3D11InputLayout};
pub struct ConstantBuffer { pub struct ConstantBufferBinding {
pub binding: u32, pub binding: u32,
pub size: u32, pub size: u32,
pub stage_mask: BindingStage, pub stage_mask: BindingStage,
pub buffer: ID3D11Buffer, pub buffer: ID3D11Buffer,
}
pub struct ConstantBuffer {
pub binding: Option<ConstantBufferBinding>,
pub storage: Box<[u8]>, pub storage: Box<[u8]>,
} }
impl ConstantBuffer {
pub fn new(binding: Option<ConstantBufferBinding>) -> Self {
let storage = vec![0u8; binding.as_ref().map(|c| c.size as usize).unwrap_or(0)].into_boxed_slice();
Self {
binding,
storage
}
}
}
// slang_process.cpp 141 // slang_process.cpp 141
pub struct FilterPass { pub struct FilterPass {
pub reflection: ShaderReflection, pub reflection: ShaderReflection,
@ -33,8 +48,8 @@ pub struct FilterPass {
pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>, pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>,
pub uniform_buffer: Option<ConstantBuffer>, pub uniform_buffer: ConstantBuffer,
pub push_buffer: Option<ConstantBuffer>, pub push_buffer: ConstantBuffer,
pub source: ShaderSource, pub source: ShaderSource,
pub config: ShaderPassConfig, pub config: ShaderPassConfig,
} }

View file

@ -70,14 +70,9 @@ impl OwnedTexture {
format_support |= D3D11_FORMAT_SUPPORT_RENDER_TARGET.0; format_support |= D3D11_FORMAT_SUPPORT_RENDER_TARGET.0;
} }
eprintln!("s {:?}, p {:?}, l {:?}", source.size, source.pitch, source.bytes.len()); // eprintln!("s {:?}, p {:?}, l {:?}", source.size, source.pitch, source.bytes.len());
eprintln!("{:#?}", desc); // eprintln!("{:#?}", desc);
// let data = Some(&D3D11_SUBRESOURCE_DATA {
// pSysMem: source.bytes.as_ptr().cast(),
// SysMemPitch: source.pitch as u32,
// SysMemSlicePitch: 0
// });
unsafe { unsafe {
let handle = device.CreateTexture2D(&desc, None).unwrap(); let handle = device.CreateTexture2D(&desc, None).unwrap();

View file

@ -29,7 +29,7 @@ mod tests {
fn triangle_gl() { fn triangle_gl() {
let (glfw, window, events, shader, vao) = hello_triangle::setup(); let (glfw, window, events, shader, vao) = hello_triangle::setup();
let mut filter = let mut filter =
FilterChain::load_from_path("../test/slang-shaders/vhs/VHSPro.slangp") FilterChain::load_from_path("../test/slang-shaders/crt/crt-royale.slangp")
.unwrap(); .unwrap();
hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter); hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter);
} }