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.
* Sampler objects are used rather than `glTexParameter`.
* 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
* 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
The core parts of librashader such as the preprocessor, the preset parser,

View file

@ -142,12 +142,15 @@ impl BindingStage {
#[derive(Debug)]
pub struct UboReflection {
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 stage_mask: BindingStage,
}
#[derive(Debug)]
pub struct PushReflection {
/// The size returned by reflection is always aligned to a 16 byte boundary.
pub size: u32,
pub stage_mask: BindingStage,
}

View file

@ -17,7 +17,7 @@ use windows::core::PCSTR;
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::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::util;
use crate::util::d3d11_compile_bound_shader;
@ -40,6 +40,7 @@ struct D3D11VertexLayout {
pub struct FilterChain {
pub common: FilterCommon,
pub passes: Vec<FilterPass>,
}
pub struct Direct3D11 {
@ -104,7 +105,7 @@ impl FilterChain {
}
fn create_constant_buffer(device: &ID3D11Device, size: u32) -> util::Result<ID3D11Buffer> {
eprintln!("{size}");
unsafe {
let buffer = device.CreateBuffer(&D3D11_BUFFER_DESC {
ByteWidth: size,
@ -123,7 +124,7 @@ impl FilterChain {
device: &ID3D11Device,
passes: Vec<ShaderPassMeta>,
semantics: &ReflectSemantics,
) -> util::Result<()>
) -> util::Result<Vec<FilterPass>>
{
// 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 size = (ubo.size + 0xf) & !0xf;
let buffer = FilterChain::create_constant_buffer(device, size)?;
Some(ConstantBuffer {
let buffer = FilterChain::create_constant_buffer(device, ubo.size)?;
Some(ConstantBufferBinding {
binding: ubo.binding,
size: ubo.size,
stage_mask: ubo.stage_mask,
buffer,
storage: vec![0u8; size as usize].into_boxed_slice(),
})
} else {
None
};
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, size)?;
Some(ConstantBuffer {
let buffer = FilterChain::create_constant_buffer(device, push.size)?;
Some(ConstantBufferBinding {
binding: if ubo_cbuffer.is_some() { 1 } else { 0 },
size: push.size,
stage_mask: push.stage_mask,
buffer,
storage: vec![0u8; size as usize].into_boxed_slice(),
})
} else {
None
@ -228,14 +225,14 @@ impl FilterChain {
vertex_layout: vertex_ia,
pixel_shader: ps,
uniform_bindings,
uniform_buffer: ubo_cbuffer,
push_buffer: push_cbuffer,
uniform_buffer: ConstantBuffer::new(ubo_cbuffer),
push_buffer: ConstantBuffer::new(push_cbuffer),
source,
config: config.clone(),
})
}
Ok(())
Ok(filters)
}
/// Load a filter chain from a pre-parsed `ShaderPreset`.
pub fn load_from_preset(device: &ID3D11Device, preset: ShaderPreset) -> util::Result<FilterChain> {
@ -244,7 +241,7 @@ impl FilterChain {
let samplers = SamplerSet::new(device)?;
// 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_wrap = filters
@ -271,7 +268,7 @@ impl FilterChain {
// FilterChain::init_history(&filters, default_filter, default_wrap);
Ok(FilterChain {
// passes: filters,
passes: filters,
// output_framebuffers: output_framebuffers.into_boxed_slice(),
// feedback_framebuffers: feedback_framebuffers.into_boxed_slice(),
// history_framebuffers,
@ -285,7 +282,6 @@ impl FilterChain {
// we don't need the reflect semantics once all locations have been bound per pass.
// semantics,
preset,
// luts,
// output_textures: output_textures.into_boxed_slice(),
// feedback_textures: feedback_textures.into_boxed_slice(),
// history_textures,

View file

@ -12,17 +12,32 @@ use librashader_reflect::reflect::semantics::{
use librashader_reflect::reflect::ShaderReflection;
use rustc_hash::FxHashMap;
use std::error::Error;
use windows::core::ConstBuffer;
use windows::Win32::Graphics::Direct3D::ID3DBlob;
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 size: u32,
pub stage_mask: BindingStage,
pub buffer: ID3D11Buffer,
}
pub struct ConstantBuffer {
pub binding: Option<ConstantBufferBinding>,
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
pub struct FilterPass {
pub reflection: ShaderReflection,
@ -33,8 +48,8 @@ pub struct FilterPass {
pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>,
pub uniform_buffer: Option<ConstantBuffer>,
pub push_buffer: Option<ConstantBuffer>,
pub uniform_buffer: ConstantBuffer,
pub push_buffer: ConstantBuffer,
pub source: ShaderSource,
pub config: ShaderPassConfig,
}

View file

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

View file

@ -29,7 +29,7 @@ mod tests {
fn triangle_gl() {
let (glfw, window, events, shader, vao) = hello_triangle::setup();
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();
hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter);
}