d3d11: create buffers
[ci broken]
This commit is contained in:
parent
085f3a6444
commit
f327040729
|
@ -62,7 +62,6 @@ pub enum FilterMode {
|
|||
#[default]
|
||||
Linear = 0,
|
||||
Nearest,
|
||||
Unspecified,
|
||||
}
|
||||
|
||||
impl FromStr for WrapMode {
|
||||
|
|
|
@ -7,16 +7,20 @@ use librashader_reflect::back::cross::GlslangHlslContext;
|
|||
use librashader_reflect::back::targets::HLSL;
|
||||
use librashader_reflect::back::{CompilerBackend, CompileShader, FromCompilation};
|
||||
use librashader_reflect::front::shaderc::GlslangCompilation;
|
||||
use librashader_reflect::reflect::semantics::{
|
||||
ReflectSemantics, SemanticMap, TextureSemantics, UniformSemantic, VariableSemantics,
|
||||
};
|
||||
use librashader_reflect::reflect::semantics::{ReflectSemantics, SemanticMap, TextureSemantics, UniformBinding, UniformSemantic, VariableSemantics};
|
||||
use librashader_reflect::reflect::ReflectShader;
|
||||
use rustc_hash::FxHashMap;
|
||||
use std::error::Error;
|
||||
use std::path::Path;
|
||||
use windows::Win32::Graphics::Direct3D11::{D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_FLAG, D3D11_RESOURCE_MISC_GENERATE_MIPS, D3D11_SAMPLER_DESC, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, ID3D11Device, ID3D11DeviceContext};
|
||||
use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SAMPLE_DESC};
|
||||
use bytemuck::offset_of;
|
||||
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::samplers::SamplerSet;
|
||||
use crate::util;
|
||||
use crate::util::d3d11_compile_bound_shader;
|
||||
|
||||
type ShaderPassMeta<'a> = (
|
||||
&'a ShaderPassConfig,
|
||||
|
@ -26,18 +30,27 @@ type ShaderPassMeta<'a> = (
|
|||
>,
|
||||
);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Default)]
|
||||
struct D3D11VertexLayout {
|
||||
position: [f32; 2],
|
||||
texcoord: [f32; 2],
|
||||
color: [f32; 4],
|
||||
}
|
||||
|
||||
pub struct FilterChain {
|
||||
pub luts: FxHashMap<usize, OwnedTexture>,
|
||||
pub common: FilterCommon,
|
||||
}
|
||||
|
||||
pub struct Direct3D11 {
|
||||
pub(crate) device_context: ID3D11DeviceContext,
|
||||
pub(crate) device: ID3D11Device,
|
||||
}
|
||||
|
||||
pub struct FilterCommon {
|
||||
pub(crate) d3d11: Direct3D11,
|
||||
pub(crate) preset: ShaderPreset,
|
||||
pub(crate) luts: FxHashMap<usize, OwnedTexture>,
|
||||
pub samplers: SamplerSet,
|
||||
}
|
||||
|
||||
impl FilterChain {
|
||||
|
@ -90,12 +103,148 @@ impl FilterChain {
|
|||
);
|
||||
}
|
||||
|
||||
fn create_constant_buffer(device: &ID3D11Device, size: u32) -> util::Result<ID3D11Buffer> {
|
||||
|
||||
unsafe {
|
||||
let buffer = device.CreateBuffer(&D3D11_BUFFER_DESC {
|
||||
ByteWidth: size,
|
||||
Usage: D3D11_USAGE_DYNAMIC,
|
||||
BindFlags: D3D11_BIND_CONSTANT_BUFFER,
|
||||
CPUAccessFlags: D3D11_CPU_ACCESS_WRITE,
|
||||
MiscFlags: D3D11_RESOURCE_MISC_FLAG(0),
|
||||
StructureByteStride: 0,
|
||||
}, None)?;
|
||||
|
||||
Ok(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
fn init_passes(
|
||||
device: &ID3D11Device,
|
||||
passes: Vec<ShaderPassMeta>,
|
||||
semantics: &ReflectSemantics,
|
||||
) -> util::Result<()>
|
||||
{
|
||||
// let mut filters = Vec::new();
|
||||
let mut filters = Vec::new();
|
||||
|
||||
for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() {
|
||||
let reflection = reflect.reflect(index, semantics)?;
|
||||
let hlsl = reflect.compile(None)?;
|
||||
|
||||
let vertex_dxil = util::d3d_compile_shader(
|
||||
hlsl.vertex.as_bytes(),
|
||||
b"main\0",
|
||||
b"vs_5_0\0"
|
||||
)?;
|
||||
let vs = d3d11_compile_bound_shader(device, &vertex_dxil, None,
|
||||
ID3D11Device::CreateVertexShader)?;
|
||||
|
||||
let ia_desc = [
|
||||
D3D11_INPUT_ELEMENT_DESC {
|
||||
SemanticName: PCSTR(b"TEXCOORD\0".as_ptr()),
|
||||
SemanticIndex: 0,
|
||||
Format: DXGI_FORMAT_R32G32_FLOAT,
|
||||
InputSlot: 0,
|
||||
AlignedByteOffset: offset_of!(D3D11VertexLayout, position) as u32,
|
||||
InputSlotClass: D3D11_INPUT_PER_VERTEX_DATA,
|
||||
InstanceDataStepRate: 0,
|
||||
},
|
||||
D3D11_INPUT_ELEMENT_DESC {
|
||||
SemanticName: PCSTR(b"TEXCOORD\0".as_ptr()),
|
||||
SemanticIndex: 1,
|
||||
Format: DXGI_FORMAT_R32G32_FLOAT,
|
||||
InputSlot: 0,
|
||||
AlignedByteOffset: offset_of!(D3D11VertexLayout, texcoord) as u32,
|
||||
InputSlotClass: D3D11_INPUT_PER_VERTEX_DATA,
|
||||
InstanceDataStepRate: 0,
|
||||
}
|
||||
];
|
||||
let vertex_ia = util::d3d11_create_input_layout(device, &ia_desc, &vertex_dxil)?;
|
||||
|
||||
let fragment_dxil = util::d3d_compile_shader(
|
||||
hlsl.fragment.as_bytes(),
|
||||
b"main\0",
|
||||
b"ps_5_0\0"
|
||||
)?;
|
||||
let ps = d3d11_compile_bound_shader(device, &fragment_dxil, None,
|
||||
ID3D11Device::CreatePixelShader)?;
|
||||
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
};
|
||||
|
||||
let mut uniform_bindings = FxHashMap::default();
|
||||
for param in reflection.meta.parameter_meta.values() {
|
||||
uniform_bindings.insert(
|
||||
UniformBinding::Parameter(param.id.clone()),
|
||||
param.offset,
|
||||
);
|
||||
}
|
||||
|
||||
for (semantics, param) in &reflection.meta.variable_meta {
|
||||
uniform_bindings.insert(
|
||||
UniformBinding::SemanticVariable(*semantics),
|
||||
param.offset
|
||||
);
|
||||
}
|
||||
|
||||
for (semantics, param) in &reflection.meta.texture_size_meta {
|
||||
uniform_bindings.insert(
|
||||
UniformBinding::TextureSize(*semantics),
|
||||
param.offset
|
||||
);
|
||||
}
|
||||
|
||||
filters.push(FilterPass {
|
||||
reflection,
|
||||
compiled: hlsl,
|
||||
vertex_shader: vs,
|
||||
vertex_layout: vertex_ia,
|
||||
pixel_shader: ps,
|
||||
uniform_bindings,
|
||||
uniform_buffer: ubo_cbuffer,
|
||||
push_buffer: push_cbuffer,
|
||||
source,
|
||||
config: config.clone(),
|
||||
})
|
||||
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
/// Load a filter chain from a pre-parsed `ShaderPreset`.
|
||||
pub fn load_from_preset(device: &ID3D11Device, preset: ShaderPreset) -> util::Result<FilterChain> {
|
||||
let (passes, semantics) = FilterChain::load_preset(&preset)?;
|
||||
|
||||
let samplers = SamplerSet::new(device)?;
|
||||
|
||||
// initialize passes
|
||||
// let filters = FilterChain::init_passes(passes, &semantics)?;
|
||||
let filters = FilterChain::init_passes(device, passes, &semantics)?;
|
||||
|
||||
// let default_filter = filters.first().map(|f| f.config.filter).unwrap_or_default();
|
||||
// let default_wrap = filters
|
||||
|
@ -122,22 +271,26 @@ impl FilterChain {
|
|||
// FilterChain::init_history(&filters, default_filter, default_wrap);
|
||||
|
||||
Ok(FilterChain {
|
||||
luts
|
||||
// passes: filters,
|
||||
// output_framebuffers: output_framebuffers.into_boxed_slice(),
|
||||
// feedback_framebuffers: feedback_framebuffers.into_boxed_slice(),
|
||||
// history_framebuffers,
|
||||
// filter_vao,
|
||||
// common: FilterCommon {
|
||||
// // 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,
|
||||
// draw_quad,
|
||||
// },
|
||||
common: FilterCommon {
|
||||
d3d11: Direct3D11 {
|
||||
device: device.clone(),
|
||||
},
|
||||
luts,
|
||||
samplers,
|
||||
// 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,
|
||||
// draw_quad,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -13,15 +13,7 @@ use librashader_reflect::reflect::ShaderReflection;
|
|||
use rustc_hash::FxHashMap;
|
||||
use std::error::Error;
|
||||
use windows::Win32::Graphics::Direct3D::ID3DBlob;
|
||||
use windows::Win32::Graphics::Direct3D11::{
|
||||
ID3D11Buffer, ID3D11PixelShader, ID3D11SamplerState, ID3D11ShaderResourceView,
|
||||
ID3D11VertexShader, D3D11_MAP_WRITE_DISCARD,
|
||||
};
|
||||
|
||||
pub struct DxShader<T> {
|
||||
pub blob: ID3DBlob,
|
||||
pub compiled: T,
|
||||
}
|
||||
use windows::Win32::Graphics::Direct3D11::{ID3D11Buffer, ID3D11PixelShader, ID3D11SamplerState, ID3D11ShaderResourceView, ID3D11VertexShader, D3D11_MAP_WRITE_DISCARD, ID3D11InputLayout};
|
||||
|
||||
pub struct ConstantBuffer {
|
||||
pub binding: u32,
|
||||
|
@ -35,13 +27,14 @@ pub struct ConstantBuffer {
|
|||
pub struct FilterPass {
|
||||
pub reflection: ShaderReflection,
|
||||
pub compiled: ShaderCompilerOutput<String, GlslangHlslContext>,
|
||||
pub vertex_shader: DxShader<ID3D11VertexShader>,
|
||||
pub pixel_shader: DxShader<ID3D11PixelShader>,
|
||||
pub vertex_shader: ID3D11VertexShader,
|
||||
pub vertex_layout: ID3D11InputLayout,
|
||||
pub pixel_shader: ID3D11PixelShader,
|
||||
|
||||
pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>,
|
||||
|
||||
pub uniform_buffer: ConstantBuffer,
|
||||
pub push_buffer: ConstantBuffer,
|
||||
pub uniform_buffer: Option<ConstantBuffer>,
|
||||
pub push_buffer: Option<ConstantBuffer>,
|
||||
pub source: ShaderSource,
|
||||
pub config: ShaderPassConfig,
|
||||
}
|
||||
|
|
|
@ -7,6 +7,10 @@ pub struct SamplerSet {
|
|||
}
|
||||
|
||||
impl SamplerSet {
|
||||
pub fn get(&self, wrap: WrapMode, filter: FilterMode) -> &ID3D11SamplerState {
|
||||
self.samplers.get(&(wrap, filter))
|
||||
.unwrap()
|
||||
}
|
||||
pub fn new(device: &ID3D11Device) -> Result<SamplerSet> {
|
||||
let mut samplers = FxHashMap::default();
|
||||
let wrap_modes =
|
||||
|
|
|
@ -3,6 +3,10 @@ use librashader_common::{FilterMode, Size, WrapMode};
|
|||
use windows::Win32::Graphics::Direct3D11::*;
|
||||
use windows::Win32::Graphics::Dxgi::Common::*;
|
||||
use std::error::Error;
|
||||
use std::slice;
|
||||
use windows::core::PCSTR;
|
||||
use windows::Win32::Graphics::Direct3D::Fxc::{D3DCompile, D3DCOMPILE_DEBUG, D3DCOMPILE_SKIP_OPTIMIZATION};
|
||||
use windows::Win32::Graphics::Direct3D::ID3DBlob;
|
||||
|
||||
/// wtf retroarch?
|
||||
const DXGI_FORMAT_EX_A4R4G4B4_UNORM: DXGI_FORMAT = DXGI_FORMAT(1000);
|
||||
|
@ -101,5 +105,63 @@ pub fn d3d11_get_closest_format(
|
|||
return DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
pub fn d3d_compile_shader(source: &[u8], entry: &[u8], version: &[u8]) -> Result<ID3DBlob> {
|
||||
unsafe {
|
||||
let mut blob = None;
|
||||
D3DCompile(
|
||||
source.as_ptr().cast(),
|
||||
source.len(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
PCSTR(entry.as_ptr()),
|
||||
PCSTR(version.as_ptr()),
|
||||
if cfg!(debug_assertions) {
|
||||
D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION
|
||||
} else {
|
||||
0
|
||||
},
|
||||
0,
|
||||
&mut blob,
|
||||
None,
|
||||
)?;
|
||||
|
||||
Ok(blob.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
pub type ShaderFactory<'a, L, T>
|
||||
= unsafe fn (&'a ID3D11Device, &[u8], linkage: L) -> windows::core::Result<T>;
|
||||
|
||||
pub fn d3d11_compile_bound_shader<'a, T, L>(device: &'a ID3D11Device, blob: &ID3DBlob, linkage: L, factory: ShaderFactory<'a, L, T>)
|
||||
-> Result<T>
|
||||
where L: Into<windows::core::InParam<'a, ID3D11ClassLinkage>>,{
|
||||
unsafe {
|
||||
// SAFETY: slice as valid for as long as vs_blob is alive.
|
||||
let dxil = slice::from_raw_parts(
|
||||
blob.GetBufferPointer().cast::<u8>(),
|
||||
blob.GetBufferSize(),
|
||||
);
|
||||
|
||||
let compiled = factory(device, dxil, linkage)?;
|
||||
Ok(compiled)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn d3d11_create_input_layout(device: &ID3D11Device, desc: &[D3D11_INPUT_ELEMENT_DESC], blob: &ID3DBlob) -> Result<ID3D11InputLayout> {
|
||||
unsafe {
|
||||
// SAFETY: slice as valid for as long as vs_blob is alive.
|
||||
let dxil = slice::from_raw_parts(
|
||||
blob.GetBufferPointer().cast::<u8>(),
|
||||
blob.GetBufferSize(),
|
||||
);
|
||||
|
||||
let compiled =
|
||||
device.CreateInputLayout(desc, dxil)?;
|
||||
Ok(compiled)
|
||||
}
|
||||
}
|
||||
|
||||
// todo: d3d11.c 2097
|
||||
pub type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
||||
|
|
|
@ -312,37 +312,6 @@ impl FilterChain {
|
|||
gl::GenerateMipmap(gl::TEXTURE_2D);
|
||||
}
|
||||
|
||||
// gl::TexParameteri(
|
||||
// gl::TEXTURE_2D,
|
||||
// gl::TEXTURE_WRAP_S,
|
||||
// GLenum::from(texture.wrap_mode) as GLint,
|
||||
// );
|
||||
// gl::TexParameteri(
|
||||
// gl::TEXTURE_2D,
|
||||
// gl::TEXTURE_WRAP_T,
|
||||
// GLenum::from(texture.wrap_mode) as GLint,
|
||||
// );
|
||||
//
|
||||
// if !linear {
|
||||
// gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
|
||||
// gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
|
||||
// } else {
|
||||
// gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
|
||||
// if mipmap {
|
||||
// gl::TexParameteri(
|
||||
// gl::TEXTURE_2D,
|
||||
// gl::TEXTURE_MIN_FILTER,
|
||||
// gl::LINEAR_MIPMAP_LINEAR as GLint,
|
||||
// );
|
||||
// } else {
|
||||
// gl::TexParameteri(
|
||||
// gl::TEXTURE_2D,
|
||||
// gl::TEXTURE_MIN_FILTER,
|
||||
// gl::LINEAR as GLint,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
gl::BindTexture(gl::TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ pub struct SamplerSet {
|
|||
|
||||
impl SamplerSet {
|
||||
pub fn get(&self, wrap: WrapMode, filter: FilterMode, mip: FilterMode) -> GLuint {
|
||||
|
||||
// eprintln!("{wrap}, {filter}, {mip}");
|
||||
*self.samplers.get(&(wrap, filter, mip))
|
||||
.unwrap()
|
||||
|
|
Loading…
Reference in a new issue