dx11: lut upload

This commit is contained in:
chyyran 2022-11-26 02:38:15 -05:00
parent e64b2f3300
commit 5cd30ade02
9 changed files with 570 additions and 314 deletions

View file

@ -2,7 +2,8 @@ use std::path::Path;
pub struct Image { pub struct Image {
pub bytes: Vec<u8>, pub bytes: Vec<u8>,
pub size: Size<u32> pub size: Size<u32>,
pub pitch: usize,
} }
impl Image { impl Image {
@ -11,9 +12,13 @@ impl Image {
let height = image.height(); let height = image.height();
let width = image.width(); let width = image.width();
let pitch = image.sample_layout().height_stride.max(
image.sample_layout().width_stride
);
Ok(Image { Ok(Image {
bytes: image.to_vec(), bytes: image.into_raw(),
pitch,
size: Size { size: Size {
height, height,
width, width,

View file

@ -1,19 +1,22 @@
use std::error::Error; use crate::texture::OwnedTexture;
use std::path::Path;
use rustc_hash::FxHashMap;
use windows::Win32::Graphics::Direct3D11::{D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_GENERATE_MIPS, D3D11_SAMPLER_DESC, D3D11_TEXTURE2D_DESC, ID3D11Device, ID3D11DeviceContext};
use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SAMPLE_DESC};
use librashader_common::image::Image; use librashader_common::image::Image;
use librashader_common::Size; use librashader_common::Size;
use librashader_preprocess::ShaderSource; use librashader_preprocess::ShaderSource;
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
use librashader_reflect::back::{CompilerBackend, CompileShader, FromCompilation};
use librashader_reflect::back::cross::GlslangHlslContext; use librashader_reflect::back::cross::GlslangHlslContext;
use librashader_reflect::back::targets::HLSL; use librashader_reflect::back::targets::HLSL;
use librashader_reflect::back::{CompilerBackend, CompileShader, FromCompilation};
use librashader_reflect::front::shaderc::GlslangCompilation; use librashader_reflect::front::shaderc::GlslangCompilation;
use librashader_reflect::reflect::semantics::{
ReflectSemantics, SemanticMap, TextureSemantics, UniformSemantic, VariableSemantics,
};
use librashader_reflect::reflect::ReflectShader; use librashader_reflect::reflect::ReflectShader;
use librashader_reflect::reflect::semantics::{ReflectSemantics, SemanticMap, TextureSemantics, UniformSemantic, VariableSemantics}; use rustc_hash::FxHashMap;
use crate::util::Texture; 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 crate::util;
type ShaderPassMeta<'a> = ( type ShaderPassMeta<'a> = (
&'a ShaderPassConfig, &'a ShaderPassConfig,
@ -23,19 +26,20 @@ type ShaderPassMeta<'a> = (
>, >,
); );
pub struct FilterChain {
pub luts: FxHashMap<usize, OwnedTexture>,
}
struct FilterChain { pub struct Direct3D11 {
pub(crate) device_context: ID3D11DeviceContext,
pub(crate) device: ID3D11Device,
} }
pub struct FilterCommon { pub struct FilterCommon {
pub(crate) device_context: ID3D11DeviceContext, pub(crate) d3d11: Direct3D11,
pub(crate) preset: ShaderPreset, pub(crate) preset: ShaderPreset,
} }
// todo: d3d11.c 2097
type Result<T> = std::result::Result<T, Box<dyn Error>>;
impl FilterChain { impl FilterChain {
fn load_pass_semantics( fn load_pass_semantics(
uniform_semantics: &mut FxHashMap<String, UniformSemantic>, uniform_semantics: &mut FxHashMap<String, UniformSemantic>,
@ -87,7 +91,7 @@ impl FilterChain {
} }
/// Load a filter chain from a pre-parsed `ShaderPreset`. /// Load a filter chain from a pre-parsed `ShaderPreset`.
pub fn load_from_preset(preset: ShaderPreset) -> Result<FilterChain> { pub fn load_from_preset(device: &ID3D11Device, preset: ShaderPreset) -> util::Result<FilterChain> {
let (passes, semantics) = FilterChain::load_preset(&preset)?; let (passes, semantics) = FilterChain::load_preset(&preset)?;
// initialize passes // initialize passes
@ -112,13 +116,13 @@ impl FilterChain {
// feedback_textures.resize_with(filters.len(), Texture::default); // feedback_textures.resize_with(filters.len(), Texture::default);
// load luts // load luts
let luts = FilterChain::load_luts(&preset.textures)?; let luts = FilterChain::load_luts(device, &preset.textures)?;
// let (history_framebuffers, history_textures) = // let (history_framebuffers, history_textures) =
// FilterChain::init_history(&filters, default_filter, default_wrap); // FilterChain::init_history(&filters, default_filter, default_wrap);
Ok(FilterChain { Ok(FilterChain {
luts
// 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(),
@ -137,41 +141,42 @@ impl FilterChain {
}) })
} }
fn load_luts(device: &ID3D11Device, textures: &[TextureConfig]) -> Result<FxHashMap<usize, Texture>> { fn load_luts(
device: &ID3D11Device,
textures: &[TextureConfig],
) -> util::Result<FxHashMap<usize, OwnedTexture>> {
let mut luts = FxHashMap::default(); let mut luts = FxHashMap::default();
for (index, texture) in textures.iter().enumerate() { for (index, texture) in textures.iter().enumerate() {
let image = Image::load(&texture.path)?; let image = Image::load(&texture.path)?;
let desc = D3D11_TEXTURE2D_DESC { let desc = D3D11_TEXTURE2D_DESC {
Width: image.width, Width: image.size.width,
Height: image.height, Height: image.size.height,
Format: DXGI_FORMAT_R8G8B8A8_UNORM, Format: DXGI_FORMAT_R8G8B8A8_UNORM,
Usage: D3D11_USAGE_DEFAULT,
MiscFlags: if texture.mipmap { MiscFlags: if texture.mipmap {
D3D11_RESOURCE_MISC_GENERATE_MIPS D3D11_RESOURCE_MISC_GENERATE_MIPS
} else { } else {
0 D3D11_RESOURCE_MISC_FLAG(0)
}, },
..Default::default() ..Default::default()
}; };
let mut texture = Texture::new(device, image.size, desc); let mut texture = OwnedTexture::new(device, &image, desc)?;
// todo: update texture d3d11_common: 150 // todo: update texture d3d11_common: 150
luts.insert(index, texture); luts.insert(index, texture);
} }
Ok(luts) Ok(luts)
} }
/// Load the shader preset at the given path into a filter chain. /// Load the shader preset at the given path into a filter chain.
pub fn load_from_path(path: impl AsRef<Path>) -> Result<FilterChain> { pub fn load_from_path(device: &ID3D11Device, path: impl AsRef<Path>) -> util::Result<FilterChain> {
// load passes from preset // load passes from preset
let preset = ShaderPreset::try_parse(path)?; let preset = ShaderPreset::try_parse(path)?;
Self::load_from_preset(preset) Self::load_from_preset(device, preset)
} }
fn load_preset( fn load_preset(preset: &ShaderPreset) -> util::Result<(Vec<ShaderPassMeta>, ReflectSemantics)> {
preset: &ShaderPreset,
) -> Result<(Vec<ShaderPassMeta>, ReflectSemantics)> {
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default(); let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> = let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> =
Default::default(); Default::default();
@ -198,7 +203,7 @@ impl FilterChain {
Ok::<_, Box<dyn Error>>((shader, source, reflect)) Ok::<_, Box<dyn Error>>((shader, source, reflect))
}) })
.into_iter() .into_iter()
.collect::<Result<Vec<(&ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>()?; .collect::<util::Result<Vec<(&ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>()?;
for details in &passes { for details in &passes {
FilterChain::load_pass_semantics( FilterChain::load_pass_semantics(
@ -234,4 +239,4 @@ impl FilterChain {
Ok((passes, semantics)) Ok((passes, semantics))
} }
} }

View file

@ -1,20 +1,26 @@
use std::error::Error; use crate::filter_chain::FilterCommon;
use rustc_hash::FxHashMap; use crate::texture::{ExternalTexture, OwnedTexture};
use windows::Win32::Graphics::Direct3D11::{D3D11_MAP_WRITE_DISCARD, ID3D11Buffer, ID3D11PixelShader, ID3D11SamplerState, ID3D11ShaderResourceView, ID3D11VertexShader};
use windows::Win32::Graphics::Direct3D::ID3DBlob;
use librashader_common::Size; use librashader_common::Size;
use librashader_preprocess::ShaderSource; use librashader_preprocess::ShaderSource;
use librashader_presets::ShaderPassConfig; use librashader_presets::ShaderPassConfig;
use librashader_reflect::back::cross::GlslangHlslContext; use librashader_reflect::back::cross::GlslangHlslContext;
use librashader_reflect::back::ShaderCompilerOutput; use librashader_reflect::back::ShaderCompilerOutput;
use librashader_reflect::reflect::semantics::{BindingStage, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniformSemantic, VariableSemantics}; use librashader_reflect::reflect::semantics::{
BindingStage, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniformSemantic,
VariableSemantics,
};
use librashader_reflect::reflect::ShaderReflection; use librashader_reflect::reflect::ShaderReflection;
use crate::filter_chain::FilterCommon; use rustc_hash::FxHashMap;
use crate::util::Texture; 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 struct DxShader<T> {
pub blob: ID3DBlob, pub blob: ID3DBlob,
pub compiled: T pub compiled: T,
} }
pub struct ConstantBuffer { pub struct ConstantBuffer {
@ -22,7 +28,7 @@ pub struct ConstantBuffer {
pub size: u32, pub size: u32,
pub stage_mask: BindingStage, pub stage_mask: BindingStage,
pub buffer: ID3D11Buffer, pub buffer: ID3D11Buffer,
pub storage: Box<[u8]> pub storage: Box<[u8]>,
} }
// slang_process.cpp 141 // slang_process.cpp 141
@ -34,7 +40,6 @@ pub struct FilterPass {
pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>, pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>,
pub uniform_buffer: ConstantBuffer, pub uniform_buffer: ConstantBuffer,
pub push_buffer: ConstantBuffer, pub push_buffer: ConstantBuffer,
pub source: ShaderSource, pub source: ShaderSource,
@ -48,10 +53,8 @@ impl FilterPass {
} }
#[inline(always)] #[inline(always)]
fn build_uniform<T>( fn build_uniform<T>(buffer: &mut [u8], value: T)
buffer: &mut [u8], where
value: T,
) where
T: Copy, T: Copy,
T: bytemuck::Pod, T: bytemuck::Pod,
{ {
@ -65,14 +68,15 @@ impl FilterPass {
buffer.copy_from_slice(vec4); buffer.copy_from_slice(vec4);
} }
fn bind_texture(texture_binding: &mut [Option<ID3D11ShaderResourceView>; 16], fn bind_texture(
sampler_binding: &mut [Option<ID3D11SamplerState>; 16], texture_binding: &mut [Option<ID3D11ShaderResourceView>; 16],
binding: &TextureBinding, sampler_binding: &mut [Option<ID3D11SamplerState>; 16],
texture: &Texture binding: &TextureBinding,
) texture: &ExternalTexture,
{ ) {
texture_binding[binding.binding as usize] = Some(texture.srv.clone()); texture_binding[binding.binding as usize] = Some(texture.srv.clone());
sampler_binding[binding.binding as usize] = Some(texture.sampler.clone()); // todo: make samplers for all wrapmode/filtermode combos.
// sampler_binding[binding.binding as usize] = Some(texture.sampler.clone());
} }
// framecount should be pre-modded // framecount should be pre-modded
@ -85,17 +89,14 @@ impl FilterPass {
frame_direction: i32, frame_direction: i32,
fb_size: Size<u32>, fb_size: Size<u32>,
// viewport: &Viewport, // viewport: &Viewport,
original: &Texture, original: &ExternalTexture,
source: &Texture, source: &ExternalTexture,
) { ) {
let mut textures: [Option<ID3D11ShaderResourceView>; 16] = std::array::from_fn(|_| None); let mut textures: [Option<ID3D11ShaderResourceView>; 16] = std::array::from_fn(|_| None);
let mut samplers: [Option<ID3D11SamplerState>; 16] = std::array::from_fn(|_| None); let mut samplers: [Option<ID3D11SamplerState>; 16] = std::array::from_fn(|_| None);
// Bind MVP // Bind MVP
if let Some(offset) = if let Some(offset) = self.uniform_bindings.get(&VariableSemantics::MVP.into()) {
self.uniform_bindings.get(&VariableSemantics::MVP.into())
{
let mvp_size = mvp.len() * std::mem::size_of::<f32>(); let mvp_size = mvp.len() * std::mem::size_of::<f32>();
let (buffer, offset) = match offset { let (buffer, offset) = match offset {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset), MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
@ -105,10 +106,7 @@ impl FilterPass {
} }
// bind OutputSize // bind OutputSize
if let Some(offset) = self if let Some(offset) = self.uniform_bindings.get(&VariableSemantics::Output.into()) {
.uniform_bindings
.get(&VariableSemantics::Output.into())
{
let (buffer, offset) = match offset { let (buffer, offset) = match offset {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset), MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset), MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
@ -153,10 +151,7 @@ impl FilterPass {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset), MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset), MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
}; };
FilterPass::build_uniform( FilterPass::build_uniform(&mut buffer[offset..][..4], frame_direction)
&mut buffer[offset..][..4],
frame_direction,
)
} }
// bind Original sampler // bind Original sampler
@ -178,10 +173,7 @@ impl FilterPass {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset), MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset), MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
}; };
FilterPass::build_vec4( FilterPass::build_vec4(&mut buffer[offset..][..16], original.size);
&mut buffer[offset..][..16],
original.size,
);
} }
// bind Source sampler // bind Source sampler
@ -204,10 +196,7 @@ impl FilterPass {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset), MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset), MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
}; };
FilterPass::build_vec4( FilterPass::build_vec4(&mut buffer[offset..][..16], source.size);
&mut buffer[offset..][..16],
source.size,
);
} }
if let Some(binding) = self if let Some(binding) = self
@ -227,10 +216,7 @@ impl FilterPass {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset), MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset), MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
}; };
FilterPass::build_vec4( FilterPass::build_vec4(&mut buffer[offset..][..16], original.size);
&mut buffer[offset..][..16],
original.size,
);
} }
// for (index, output) in parent.history_textures.iter().enumerate() { // for (index, output) in parent.history_textures.iter().enumerate() {
@ -317,12 +303,12 @@ impl FilterPass {
// bind float parameters // bind float parameters
for (id, offset) in for (id, offset) in
self.uniform_bindings self.uniform_bindings
.iter() .iter()
.filter_map(|(binding, value)| match binding { .filter_map(|(binding, value)| match binding {
UniformBinding::Parameter(id) => Some((id, value)), UniformBinding::Parameter(id) => Some((id, value)),
_ => None, _ => None,
}) })
{ {
let id = id.as_str(); let id = id.as_str();
let (buffer, offset) = match offset { let (buffer, offset) = match offset {
@ -385,10 +371,7 @@ impl FilterPass {
parent: &FilterCommon, parent: &FilterCommon,
frame_count: u32, frame_count: u32,
frame_direction: i32, frame_direction: i32,
) -> std::result::Result<(), Box<dyn Error>> ) -> std::result::Result<(), Box<dyn Error>> {
{
Ok(()) Ok(())
} }
} }

View file

@ -63,19 +63,20 @@ PixelOutput main(PixelInput pixelInput)
return output; return output;
}\0"; }\0";
use std::mem::transmute;
use gfx_maths::Mat4; use gfx_maths::Mat4;
use std::mem::transmute;
trait DXSample { pub trait DXSample {
fn new() -> Result<Self> fn new() -> Result<Self>
where where
Self: Sized; Self: Sized;
fn bind_to_window(&mut self, hwnd: &HWND) -> Result<()>; fn bind_to_window(&mut self, hwnd: &HWND) -> Result<()>;
fn update(&mut self) {} fn update(&mut self) {}
fn render(&mut self) -> Result<()> { Ok(()) } fn render(&mut self) -> Result<()> {
Ok(())
}
fn on_key_up(&mut self, _key: u8) {} fn on_key_up(&mut self, _key: u8) {}
fn on_key_down(&mut self, _key: u8) {} fn on_key_down(&mut self, _key: u8) {}
@ -88,9 +89,9 @@ trait DXSample {
} }
} }
fn run_sample<S>() -> Result<()> fn run_sample<S>(mut sample: S) -> Result<()>
where where
S: DXSample, S: DXSample,
{ {
let instance = unsafe { GetModuleHandleA(None)? }; let instance = unsafe { GetModuleHandleA(None)? };
@ -104,8 +105,6 @@ fn run_sample<S>() -> Result<()>
..Default::default() ..Default::default()
}; };
let mut sample = S::new()?;
let size = sample.window_size(); let size = sample.window_size();
let atom = unsafe { RegisterClassExA(&wc) }; let atom = unsafe { RegisterClassExA(&wc) };
@ -121,8 +120,6 @@ fn run_sample<S>() -> Result<()>
let mut title = sample.title(); let mut title = sample.title();
title.push('\0'); title.push('\0');
let hwnd = unsafe { let hwnd = unsafe {
@ -216,7 +213,6 @@ extern "system" fn wndproc<S: DXSample>(
} }
} }
#[repr(C)] #[repr(C)]
struct Vertex { struct Vertex {
position: [f32; 3], position: [f32; 3],
@ -228,37 +224,37 @@ struct Vertex {
struct TriangleUniforms { struct TriangleUniforms {
projection_matrix: Mat4, projection_matrix: Mat4,
model_matrix: Mat4, model_matrix: Mat4,
view_matrix: Mat4 view_matrix: Mat4,
} }
mod d3d11_hello_triangle { pub mod d3d11_hello_triangle {
use super::*;
use gfx_maths::{Quaternion, Vec3};
use std::slice; use std::slice;
use std::time::Instant; use std::time::Instant;
use gfx_maths::{Quaternion, Vec3};
use super::*;
const FRAME_COUNT: u32 = 2; const FRAME_COUNT: u32 = 2;
pub struct Sample { pub struct Sample {
dxgi_factory: IDXGIFactory4, pub dxgi_factory: IDXGIFactory4,
device: ID3D11Device, pub device: ID3D11Device,
context: ID3D11DeviceContext, pub context: ID3D11DeviceContext,
resources: Option<Resources> pub resources: Option<Resources>,
} }
pub struct Resources { pub struct Resources {
swapchain: IDXGISwapChain, pub swapchain: IDXGISwapChain,
depth_buffer: ID3D11Texture2D, pub depth_buffer: ID3D11Texture2D,
depth_stencil_view: ID3D11DepthStencilView, pub depth_stencil_view: ID3D11DepthStencilView,
triangle_vertices: ID3D11Buffer, pub triangle_vertices: ID3D11Buffer,
triangle_indices: ID3D11Buffer, pub triangle_indices: ID3D11Buffer,
triangle_uniforms: ID3D11Buffer, pub triangle_uniforms: ID3D11Buffer,
vs: ID3D11VertexShader, pub vs: ID3D11VertexShader,
ps: ID3D11PixelShader, pub ps: ID3D11PixelShader,
input_layout: ID3D11InputLayout, pub input_layout: ID3D11InputLayout,
frame_start: Instant, pub frame_start: Instant,
frame_end: Instant, pub frame_end: Instant,
elapsed: f32, pub elapsed: f32,
triangle_uniform_values: TriangleUniforms, triangle_uniform_values: TriangleUniforms,
pub backbuffer: ID3D11Texture2D, pub backbuffer: ID3D11Texture2D,
pub rtv: ID3D11RenderTargetView, pub rtv: ID3D11RenderTargetView,
@ -272,7 +268,7 @@ mod d3d11_hello_triangle {
dxgi_factory, dxgi_factory,
device, device,
context, context,
resources: None resources: None,
}) })
} }
@ -288,21 +284,24 @@ mod d3d11_hello_triangle {
let vs_compiled = unsafe { let vs_compiled = unsafe {
// SAFETY: slice as valid for as long as vs_blob is alive. // SAFETY: slice as valid for as long as vs_blob is alive.
slice::from_raw_parts(vs_blob.GetBufferPointer().cast::<u8>(), vs_blob.GetBufferSize()) slice::from_raw_parts(
vs_blob.GetBufferPointer().cast::<u8>(),
vs_blob.GetBufferSize(),
)
}; };
let vs = unsafe { let vs = unsafe { self.device.CreateVertexShader(vs_compiled, None) }?;
self.device.CreateVertexShader(vs_compiled, None)
}?;
let ps = unsafe { let ps = unsafe {
let ps = slice::from_raw_parts(ps_blob.GetBufferPointer().cast::<u8>(), ps_blob.GetBufferSize()); let ps = slice::from_raw_parts(
ps_blob.GetBufferPointer().cast::<u8>(),
ps_blob.GetBufferSize(),
);
self.device.CreatePixelShader(ps, None) self.device.CreatePixelShader(ps, None)
}?; }?;
let (input_layout, stencil_state, raster_state) =
let (input_layout, stencil_state, raster_state) create_pipeline_state(&self.device, vs_compiled)?;
= create_pipeline_state(&self.device, vs_compiled)?;
unsafe { unsafe {
self.context.OMSetDepthStencilState(&stencil_state, 1); self.context.OMSetDepthStencilState(&stencil_state, 1);
@ -332,7 +331,7 @@ mod d3d11_hello_triangle {
Height: HEIGHT as f32, Height: HEIGHT as f32,
MinDepth: D3D11_MIN_DEPTH, MinDepth: D3D11_MIN_DEPTH,
MaxDepth: D3D11_MAX_DEPTH, MaxDepth: D3D11_MAX_DEPTH,
} },
}); });
Ok(()) Ok(())
@ -348,7 +347,7 @@ mod d3d11_hello_triangle {
let time = time.as_secs() as f32 * 1000.0; let time = time.as_secs() as f32 * 1000.0;
// framelimit set to 60fps // framelimit set to 60fps
if time < (1000.0f32 / 144.0f32) { if time < (1000.0f32 / 60.0f32) {
return Ok(()); return Ok(());
} }
@ -361,21 +360,42 @@ mod d3d11_hello_triangle {
let buffer_number = 0; let buffer_number = 0;
unsafe { unsafe {
let mapped_resource = self.context.Map(&resources.triangle_uniforms, 0, D3D11_MAP_WRITE_DISCARD, 0)?; let mapped_resource = self.context.Map(
std::ptr::copy_nonoverlapping(&resources.triangle_uniform_values, mapped_resource.pData.cast(), 1); &resources.triangle_uniforms,
0,
D3D11_MAP_WRITE_DISCARD,
0,
)?;
std::ptr::copy_nonoverlapping(
&resources.triangle_uniform_values,
mapped_resource.pData.cast(),
1,
);
self.context.Unmap(&resources.triangle_uniforms, 0); self.context.Unmap(&resources.triangle_uniforms, 0);
} }
unsafe { unsafe {
self.context.VSSetConstantBuffers(buffer_number, Some(&[Some(resources.triangle_uniforms.clone())])); self.context.VSSetConstantBuffers(
self.context.OMSetRenderTargets(Some(&[Some(resources.rtv.clone())]), &resources.depth_stencil_view); buffer_number,
Some(&[Some(resources.triangle_uniforms.clone())]),
);
self.context.OMSetRenderTargets(
Some(&[Some(resources.rtv.clone())]),
&resources.depth_stencil_view,
);
self.context.RSSetViewports(Some(&[resources.viewport])) self.context.RSSetViewports(Some(&[resources.viewport]))
} }
unsafe { unsafe {
let color = [0.3, 0.4, 0.6, 1.0]; let color = [0.3, 0.4, 0.6, 1.0];
self.context.ClearRenderTargetView(&resources.rtv, color.as_ptr()); self.context
self.context.ClearDepthStencilView(&resources.depth_stencil_view, D3D11_CLEAR_DEPTH.0 as u32, 1.0, 0); .ClearRenderTargetView(&resources.rtv, color.as_ptr());
self.context.ClearDepthStencilView(
&resources.depth_stencil_view,
D3D11_CLEAR_DEPTH.0 as u32,
1.0,
0,
);
self.context.IASetInputLayout(&resources.input_layout); self.context.IASetInputLayout(&resources.input_layout);
} }
@ -383,18 +403,25 @@ mod d3d11_hello_triangle {
self.context.VSSetShader(&resources.vs, None); self.context.VSSetShader(&resources.vs, None);
self.context.PSSetShader(&resources.ps, None); self.context.PSSetShader(&resources.ps, None);
let stride =std::mem::size_of::<Vertex>() as u32; let stride = std::mem::size_of::<Vertex>() as u32;
let offset = 0; let offset = 0;
self.context.IASetVertexBuffers(0, 1, Some(&Some(resources.triangle_vertices.clone())), Some(&stride), Some(&offset)); self.context.IASetVertexBuffers(
self.context.IASetIndexBuffer(&resources.triangle_indices, DXGI_FORMAT_R32_UINT, 0); 0,
self.context.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 1,
Some(&Some(resources.triangle_vertices.clone())),
Some(&stride),
Some(&offset),
);
self.context
.IASetIndexBuffer(&resources.triangle_indices, DXGI_FORMAT_R32_UINT, 0);
self.context
.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
} }
unsafe { unsafe {
self.context.DrawIndexed(3, 0, 0); self.context.DrawIndexed(3, 0, 0);
} }
unsafe { unsafe {
resources.swapchain.Present(0, 0).ok()?; resources.swapchain.Present(0, 0).ok()?;
} }
@ -402,7 +429,10 @@ mod d3d11_hello_triangle {
} }
} }
fn create_rtv(device: &ID3D11Device, swapchain: &IDXGISwapChain) -> Result<(ID3D11RenderTargetView, ID3D11Texture2D)>{ fn create_rtv(
device: &ID3D11Device,
swapchain: &IDXGISwapChain,
) -> Result<(ID3D11RenderTargetView, ID3D11Texture2D)> {
unsafe { unsafe {
let backbuffer: ID3D11Texture2D = swapchain.GetBuffer(0)?; let backbuffer: ID3D11Texture2D = swapchain.GetBuffer(0)?;
let rtv = device.CreateRenderTargetView(&backbuffer, None)?; let rtv = device.CreateRenderTargetView(&backbuffer, None)?;
@ -410,28 +440,38 @@ mod d3d11_hello_triangle {
Ok((rtv, backbuffer)) Ok((rtv, backbuffer))
} }
} }
fn create_pipeline_state(device: &ID3D11Device, vs_blob: &[u8]) -> Result<(ID3D11InputLayout, ID3D11DepthStencilState, ID3D11RasterizerState)> { fn create_pipeline_state(
device: &ID3D11Device,
vs_blob: &[u8],
) -> Result<(
ID3D11InputLayout,
ID3D11DepthStencilState,
ID3D11RasterizerState,
)> {
unsafe { unsafe {
let input_layout = device.CreateInputLayout(&[ let input_layout = device.CreateInputLayout(
D3D11_INPUT_ELEMENT_DESC { &[
SemanticName: s!("POSITION"), D3D11_INPUT_ELEMENT_DESC {
SemanticIndex: 0, SemanticName: s!("POSITION"),
Format: DXGI_FORMAT_R32G32B32_FLOAT, SemanticIndex: 0,
InputSlot: 0, Format: DXGI_FORMAT_R32G32B32_FLOAT,
AlignedByteOffset: 0, InputSlot: 0,
InputSlotClass: D3D11_INPUT_PER_VERTEX_DATA, AlignedByteOffset: 0,
InstanceDataStepRate: 0 InputSlotClass: D3D11_INPUT_PER_VERTEX_DATA,
}, InstanceDataStepRate: 0,
D3D11_INPUT_ELEMENT_DESC { },
SemanticName: s!("COLOR"), D3D11_INPUT_ELEMENT_DESC {
SemanticIndex: 0, SemanticName: s!("COLOR"),
Format: DXGI_FORMAT_R32G32B32_FLOAT, SemanticIndex: 0,
InputSlot: 0, Format: DXGI_FORMAT_R32G32B32_FLOAT,
AlignedByteOffset: D3D11_APPEND_ALIGNED_ELEMENT, InputSlot: 0,
InputSlotClass: D3D11_INPUT_PER_VERTEX_DATA, AlignedByteOffset: D3D11_APPEND_ALIGNED_ELEMENT,
InstanceDataStepRate: 0 InputSlotClass: D3D11_INPUT_PER_VERTEX_DATA,
}, InstanceDataStepRate: 0,
], vs_blob)?; },
],
vs_blob,
)?;
let stencil_state = device.CreateDepthStencilState(&D3D11_DEPTH_STENCIL_DESC { let stencil_state = device.CreateDepthStencilState(&D3D11_DEPTH_STENCIL_DESC {
DepthEnable: BOOL::from(true), DepthEnable: BOOL::from(true),
@ -451,7 +491,7 @@ mod d3d11_hello_triangle {
StencilDepthFailOp: D3D11_STENCIL_OP_DECR, StencilDepthFailOp: D3D11_STENCIL_OP_DECR,
StencilPassOp: D3D11_STENCIL_OP_KEEP, StencilPassOp: D3D11_STENCIL_OP_KEEP,
StencilFunc: D3D11_COMPARISON_ALWAYS, StencilFunc: D3D11_COMPARISON_ALWAYS,
} },
})?; })?;
let rasterizer_state = device.CreateRasterizerState(&D3D11_RASTERIZER_DESC { let rasterizer_state = device.CreateRasterizerState(&D3D11_RASTERIZER_DESC {
@ -464,41 +504,47 @@ mod d3d11_hello_triangle {
FrontCounterClockwise: BOOL::from(false), FrontCounterClockwise: BOOL::from(false),
MultisampleEnable: BOOL::from(false), MultisampleEnable: BOOL::from(false),
ScissorEnable: BOOL::from(false), ScissorEnable: BOOL::from(false),
SlopeScaledDepthBias: 0.0f32 SlopeScaledDepthBias: 0.0f32,
})?; })?;
Ok((input_layout, stencil_state, rasterizer_state)) Ok((input_layout, stencil_state, rasterizer_state))
} }
} }
fn create_depth_buffer(device: &ID3D11Device) -> Result<(ID3D11Texture2D, ID3D11DepthStencilView)>{ fn create_depth_buffer(
device: &ID3D11Device,
) -> Result<(ID3D11Texture2D, ID3D11DepthStencilView)> {
unsafe { unsafe {
let buffer = device.CreateTexture2D(&D3D11_TEXTURE2D_DESC { let buffer = device.CreateTexture2D(
Width: WIDTH as u32, &D3D11_TEXTURE2D_DESC {
Height: HEIGHT as u32, Width: WIDTH as u32,
MipLevels: 1, Height: HEIGHT as u32,
ArraySize: 1, MipLevels: 1,
Format: DXGI_FORMAT_D24_UNORM_S8_UINT, ArraySize: 1,
SampleDesc: DXGI_SAMPLE_DESC { Format: DXGI_FORMAT_D24_UNORM_S8_UINT,
Count: 1, SampleDesc: DXGI_SAMPLE_DESC {
Quality: 0 Count: 1,
}, Quality: 0,
Usage: D3D11_USAGE_DEFAULT,
BindFlags: D3D11_BIND_DEPTH_STENCIL,
CPUAccessFlags: Default::default(),
MiscFlags: Default::default(),
}, None)?;
let view = device.CreateDepthStencilView(&buffer,Some(&D3D11_DEPTH_STENCIL_VIEW_DESC {
Format: DXGI_FORMAT_D24_UNORM_S8_UINT,
ViewDimension: D3D11_DSV_DIMENSION_TEXTURE2D,
Anonymous: D3D11_DEPTH_STENCIL_VIEW_DESC_0 {
Texture2D: D3D11_TEX2D_DSV {
MipSlice: 0,
}, },
Usage: D3D11_USAGE_DEFAULT,
BindFlags: D3D11_BIND_DEPTH_STENCIL,
CPUAccessFlags: Default::default(),
MiscFlags: Default::default(),
}, },
..Default::default() None,
}))?; )?;
let view = device.CreateDepthStencilView(
&buffer,
Some(&D3D11_DEPTH_STENCIL_VIEW_DESC {
Format: DXGI_FORMAT_D24_UNORM_S8_UINT,
ViewDimension: D3D11_DSV_DIMENSION_TEXTURE2D,
Anonymous: D3D11_DEPTH_STENCIL_VIEW_DESC_0 {
Texture2D: D3D11_TEX2D_DSV { MipSlice: 0 },
},
..Default::default()
}),
)?;
Ok((buffer, view)) Ok((buffer, view))
} }
@ -506,22 +552,21 @@ mod d3d11_hello_triangle {
fn create_triangle_uniforms(device: &ID3D11Device) -> Result<ID3D11Buffer> { fn create_triangle_uniforms(device: &ID3D11Device) -> Result<ID3D11Buffer> {
unsafe { unsafe {
device.CreateBuffer(&D3D11_BUFFER_DESC { device.CreateBuffer(
ByteWidth: (std::mem::size_of::<TriangleUniforms>()) as u32, &D3D11_BUFFER_DESC {
Usage: D3D11_USAGE_DYNAMIC, ByteWidth: (std::mem::size_of::<TriangleUniforms>()) as u32,
BindFlags: D3D11_BIND_CONSTANT_BUFFER, Usage: D3D11_USAGE_DYNAMIC,
CPUAccessFlags: D3D11_CPU_ACCESS_WRITE, BindFlags: D3D11_BIND_CONSTANT_BUFFER,
MiscFlags: Default::default(), CPUAccessFlags: D3D11_CPU_ACCESS_WRITE,
StructureByteStride: 0, MiscFlags: Default::default(),
}, None) StructureByteStride: 0,
},
None,
)
} }
} }
fn create_triangle_buffers(device: &ID3D11Device) -> Result<(ID3D11Buffer, ID3D11Buffer)> {
fn create_triangle_buffers(
device: &ID3D11Device,
) -> Result<(ID3D11Buffer, ID3D11Buffer)> {
let vertices = [ let vertices = [
Vertex { Vertex {
position: [0.5f32, -0.5, 0.0], position: [0.5f32, -0.5, 0.0],
@ -539,35 +584,40 @@ mod d3d11_hello_triangle {
let indices = [0, 1, 2]; let indices = [0, 1, 2];
unsafe { unsafe {
let vertex_buffer = device.CreateBuffer(&D3D11_BUFFER_DESC { let vertex_buffer = device.CreateBuffer(
ByteWidth: (std::mem::size_of::<Vertex>() * vertices.len()) as u32, &D3D11_BUFFER_DESC {
Usage: D3D11_USAGE_DEFAULT, ByteWidth: (std::mem::size_of::<Vertex>() * vertices.len()) as u32,
BindFlags: D3D11_BIND_VERTEX_BUFFER, Usage: D3D11_USAGE_DEFAULT,
CPUAccessFlags: Default::default(), BindFlags: D3D11_BIND_VERTEX_BUFFER,
MiscFlags: Default::default(), CPUAccessFlags: Default::default(),
StructureByteStride: 0, MiscFlags: Default::default(),
}, Some(&D3D11_SUBRESOURCE_DATA { StructureByteStride: 0,
pSysMem: vertices.as_ptr().cast(), },
SysMemPitch: 0, Some(&D3D11_SUBRESOURCE_DATA {
SysMemSlicePitch: 0, pSysMem: vertices.as_ptr().cast(),
}))?; SysMemPitch: 0,
SysMemSlicePitch: 0,
}),
)?;
let index_buffer = device.CreateBuffer(&D3D11_BUFFER_DESC { let index_buffer = device.CreateBuffer(
ByteWidth: (std::mem::size_of::<u32>() * indices.len()) as u32, &D3D11_BUFFER_DESC {
Usage: D3D11_USAGE_DEFAULT, ByteWidth: (std::mem::size_of::<u32>() * indices.len()) as u32,
BindFlags: D3D11_BIND_INDEX_BUFFER, Usage: D3D11_USAGE_DEFAULT,
CPUAccessFlags: Default::default(), BindFlags: D3D11_BIND_INDEX_BUFFER,
MiscFlags: Default::default(), CPUAccessFlags: Default::default(),
StructureByteStride: 0, MiscFlags: Default::default(),
}, Some(&D3D11_SUBRESOURCE_DATA { StructureByteStride: 0,
pSysMem: indices.as_ptr().cast(), },
SysMemPitch: 0, Some(&D3D11_SUBRESOURCE_DATA {
SysMemSlicePitch: 0, pSysMem: indices.as_ptr().cast(),
}))?; SysMemPitch: 0,
SysMemSlicePitch: 0,
}),
)?;
Ok((vertex_buffer, index_buffer)) Ok((vertex_buffer, index_buffer))
} }
} }
fn create_device() -> Result<(IDXGIFactory4, ID3D11Device, ID3D11DeviceContext)> { fn create_device() -> Result<(IDXGIFactory4, ID3D11Device, ID3D11DeviceContext)> {
let dxgi_factory_flags = if cfg!(debug_assertions) { let dxgi_factory_flags = if cfg!(debug_assertions) {
@ -583,19 +633,27 @@ mod d3d11_hello_triangle {
let mut out_context = None; let mut out_context = None;
let mut _out_feature_level = D3D_FEATURE_LEVEL_11_0; let mut _out_feature_level = D3D_FEATURE_LEVEL_11_0;
unsafe { D3D11CreateDevice(None, D3D_DRIVER_TYPE_HARDWARE, unsafe {
HINSTANCE::default(), D3D11CreateDevice(
Default::default(), None,
Some(&feature_levels), D3D_DRIVER_TYPE_HARDWARE,
D3D11_SDK_VERSION, HINSTANCE::default(),
Some(&mut out_device), D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_DEBUG,
Some(&mut _out_feature_level), Some(&feature_levels),
Some(&mut out_context)) D3D11_SDK_VERSION,
Some(&mut out_device),
Some(&mut _out_feature_level),
Some(&mut out_context),
)
}?; }?;
Ok((dxgi_factory, out_device.unwrap(), out_context.unwrap())) Ok((dxgi_factory, out_device.unwrap(), out_context.unwrap()))
} }
fn create_swapchain(fac: &IDXGIFactory4, device: &ID3D11Device, hwnd: HWND) -> Result<IDXGISwapChain>{ fn create_swapchain(
fac: &IDXGIFactory4,
device: &ID3D11Device,
hwnd: HWND,
) -> Result<IDXGISwapChain> {
let swapchain_desc = DXGI_SWAP_CHAIN_DESC { let swapchain_desc = DXGI_SWAP_CHAIN_DESC {
BufferDesc: DXGI_MODE_DESC { BufferDesc: DXGI_MODE_DESC {
Width: WIDTH as u32, Width: WIDTH as u32,
@ -620,7 +678,6 @@ mod d3d11_hello_triangle {
Flags: 0, Flags: 0,
}; };
let mut swap_chain = None; let mut swap_chain = None;
unsafe { unsafe {
fac.CreateSwapChain(&*device, &swapchain_desc, &mut swap_chain) fac.CreateSwapChain(&*device, &swapchain_desc, &mut swap_chain)
@ -630,21 +687,30 @@ mod d3d11_hello_triangle {
Ok(swap_chain.expect("[dx11] swapchain creation failed.")) Ok(swap_chain.expect("[dx11] swapchain creation failed."))
} }
fn compile_shader(source: &[u8], entry: &[u8], version: &[u8]) -> Result<ID3DBlob>{ fn compile_shader(source: &[u8], entry: &[u8], version: &[u8]) -> Result<ID3DBlob> {
unsafe { unsafe {
let mut blob = None; let mut blob = None;
D3DCompile(source.as_ptr().cast(), source.len(), D3DCompile(
None, None, None, source.as_ptr().cast(),
PCSTR(entry.as_ptr()), source.len(),
PCSTR(version.as_ptr()), D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION, 0, &mut blob, None)?; None,
None,
None,
PCSTR(entry.as_ptr()),
PCSTR(version.as_ptr()),
D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION,
0,
&mut blob,
None,
)?;
Ok(blob.unwrap()) Ok(blob.unwrap())
} }
} }
} }
pub fn main() -> Result<()> { pub fn main<S: DXSample>(sample: S) -> Result<()> {
run_sample::<d3d11_hello_triangle::Sample>()?; run_sample(sample)?;
Ok(()) Ok(())
} }

View file

@ -1,31 +1,40 @@
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
#![feature(let_chains)]
mod filter_chain; mod filter_chain;
use librashader_preprocess::ShaderSource; use librashader_preprocess::ShaderSource;
use librashader_presets::ShaderPassConfig; use librashader_presets::ShaderPassConfig;
use librashader_reflect::back::targets::HLSL; use librashader_reflect::back::targets::HLSL;
use librashader_reflect::back::{CompileShader, FromCompilation}; use librashader_reflect::back::{CompileShader, FromCompilation};
use librashader_reflect::front::shaderc::GlslangCompilation;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::error::Error; use std::error::Error;
use std::path::Path; use std::path::Path;
use librashader_reflect::front::shaderc::GlslangCompilation;
use librashader_reflect::reflect::semantics::{ReflectSemantics, SemanticMap, TextureSemantics, UniformSemantic, VariableSemantics}; use librashader_reflect::reflect::semantics::{
ReflectSemantics, SemanticMap, TextureSemantics, UniformSemantic, VariableSemantics,
};
use librashader_reflect::reflect::ReflectShader; use librashader_reflect::reflect::ReflectShader;
mod filter_pass;
#[cfg(test)] #[cfg(test)]
mod hello_triangle; mod hello_triangle;
mod filter_pass; mod texture;
mod util; mod util;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::hello_triangle::DXSample;
use super::*; use super::*;
#[test] #[test]
fn triangle_dx11() { fn triangle_dx11() {
hello_triangle::main().unwrap(); let sample = hello_triangle::d3d11_hello_triangle::Sample::new().unwrap();
let device = sample.device.clone();
let chain = filter_chain::FilterChain::load_from_path(&device, "../test/slang-shaders/crt/crt-royale.slangp").unwrap();
std::mem::forget(chain);
hello_triangle::main(sample).unwrap();
} }
} }

View file

@ -0,0 +1,146 @@
use librashader_common::Size;
use windows::Win32::Graphics::Direct3D11::{ID3D11Device, ID3D11SamplerState, ID3D11ShaderResourceView, ID3D11Texture2D, D3D11_BIND_RENDER_TARGET, D3D11_BIND_SHADER_RESOURCE, D3D11_CPU_ACCESS_FLAG, D3D11_CPU_ACCESS_WRITE, D3D11_FORMAT_SUPPORT_RENDER_TARGET, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE, D3D11_FORMAT_SUPPORT_TEXTURE2D, D3D11_RESOURCE_MISC_GENERATE_MIPS, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DYNAMIC, D3D11_SHADER_RESOURCE_VIEW_DESC, D3D11_SHADER_RESOURCE_VIEW_DESC_0, D3D11_TEX2D_SRV, D3D11_BIND_FLAG, D3D11_RESOURCE_MISC_FLAG, D3D11_USAGE_STAGING, ID3D11DeviceContext, D3D11_SUBRESOURCE_DATA, D3D11_MAP_WRITE, D3D11_BOX};
use windows::Win32::Graphics::Direct3D::D3D_SRV_DIMENSION_TEXTURE2D;
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
use librashader_common::image::Image;
use crate::util::d3d11_get_closest_format;
use crate::util::Result;
#[derive(Debug, Clone)]
pub struct ExternalTexture {
pub srv: ID3D11ShaderResourceView,
pub size: Size<u32>, // pub image: GlImage,
}
#[derive(Debug, Clone)]
pub struct OwnedTexture {
pub handle: ID3D11Texture2D,
// pub staging: ID3D11Texture2D,
pub srv: ID3D11ShaderResourceView,
pub desc: D3D11_TEXTURE2D_DESC,
pub size: Size<u32>, // pub image: GlImage,
// pub filter: FilterMode,
// pub mip_filter: FilterMode,
// pub wrap_mode: WrapMode,
}
impl OwnedTexture {
pub fn new(device: &ID3D11Device, source: &Image, desc: D3D11_TEXTURE2D_DESC) -> Result<OwnedTexture> {
let mut desc = D3D11_TEXTURE2D_DESC {
Width: source.size.width,
Height: source.size.height,
// todo: set this to 0
MipLevels: if (desc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS).0 != 0 {
0
} else {
1
},
ArraySize: 1,
SampleDesc: DXGI_SAMPLE_DESC {
Count: 1,
Quality: 0,
},
CPUAccessFlags: if desc.Usage == D3D11_USAGE_DYNAMIC {
D3D11_CPU_ACCESS_WRITE
} else {
D3D11_CPU_ACCESS_FLAG(0)
},
..desc
};
desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
// determine number of mipmaps required
if (desc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS).0 != 0 {
let mut width = desc.Width >> 5;
let mut height = desc.Height >> 5;
desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
while width != 0 && height != 0 {
width >>= 1;
height >>= 1;
desc.MipLevels += 1;
}
}
// determine if format is supported.
// bruh why does D3D11_FORMAT_SUPPORT not implement bitor???
let mut format_support =
D3D11_FORMAT_SUPPORT_TEXTURE2D.0 | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE.0;
if (desc.BindFlags & D3D11_BIND_RENDER_TARGET).0 != 0 {
format_support |= D3D11_FORMAT_SUPPORT_RENDER_TARGET.0;
}
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();
let srv = device.CreateShaderResourceView(&handle, Some(&D3D11_SHADER_RESOURCE_VIEW_DESC {
Format: desc.Format,
ViewDimension: D3D_SRV_DIMENSION_TEXTURE2D,
Anonymous: D3D11_SHADER_RESOURCE_VIEW_DESC_0 {
Texture2D: D3D11_TEX2D_SRV {
MostDetailedMip: 0,
MipLevels: u32::MAX
}
},
}))?;
let mut context = None;
device.GetImmediateContext(&mut context);
// todo: make this fallible
let context = context.unwrap();
// need a staging texture to defer mipmap generation
let staging = device.CreateTexture2D(&D3D11_TEXTURE2D_DESC {
MipLevels: 1,
BindFlags: D3D11_BIND_FLAG(0),
MiscFlags: D3D11_RESOURCE_MISC_FLAG(0),
Usage: D3D11_USAGE_STAGING,
CPUAccessFlags: D3D11_CPU_ACCESS_WRITE,
..desc
}, Some(&D3D11_SUBRESOURCE_DATA {
pSysMem: source.bytes.as_ptr().cast(),
SysMemPitch: source.pitch as u32,
SysMemSlicePitch: 0
}))?;
// todo: do format conversion (leverage image crate..? is this necessary tbh)...
context.CopySubresourceRegion(&handle, 0, 0, 0, 0,
&staging, 0, Some(&D3D11_BOX {
left: 0,
top: 0,
front: 0,
right: source.size.width,
bottom: source.size.height,
back: 1,
}));
if (desc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS).0 != 0 {
context.GenerateMips(&srv)
}
// let mut subresource = context.Map(staging, 0, D3D11_MAP_WRITE, 0)?;
// staging.Upd
Ok(OwnedTexture {
handle,
// staging,
srv,
desc,
size: source.size,
})
}
}
}

View file

@ -1,64 +1,105 @@
use windows::Win32::Graphics::Direct3D11::{D3D11_BIND_RENDER_TARGET, D3D11_BIND_SHADER_RESOURCE, D3D11_CPU_ACCESS_WRITE, D3D11_FORMAT_SUPPORT_RENDER_TARGET, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE, D3D11_FORMAT_SUPPORT_TEXTURE2D, D3D11_RESOURCE_MISC_GENERATE_MIPS, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DYNAMIC, ID3D11Device, ID3D11SamplerState, ID3D11ShaderResourceView, ID3D11Texture2D};
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
use librashader_common::{FilterMode, Size, WrapMode}; use librashader_common::{FilterMode, Size, WrapMode};
#[derive(Debug, Clone)] use windows::Win32::Graphics::Direct3D11::*;
pub struct Texture { use windows::Win32::Graphics::Dxgi::Common::*;
pub handle: ID3D11Texture2D, use std::error::Error;
pub staging: ID3D11Texture2D,
pub srv: ID3D11ShaderResourceView, /// wtf retroarch?
pub sampler: ID3D11SamplerState, const DXGI_FORMAT_EX_A4R4G4B4_UNORM: DXGI_FORMAT = DXGI_FORMAT(1000);
pub desc: D3D11_TEXTURE2D_DESC,
pub size: Size<u32> const fn d3d11_format_fallback_list(format: DXGI_FORMAT) -> Option<&'static [DXGI_FORMAT]> {
// pub image: GlImage, match format {
// pub filter: FilterMode, DXGI_FORMAT_R32G32B32A32_FLOAT => Some(&[
// pub mip_filter: FilterMode, DXGI_FORMAT_R32G32B32A32_FLOAT,
// pub wrap_mode: WrapMode, DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_R32G32B32_FLOAT,
DXGI_FORMAT_R11G11B10_FLOAT,
DXGI_FORMAT_UNKNOWN,
]),
DXGI_FORMAT_R16G16B16A16_FLOAT => Some(&[
DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_R32G32B32A32_FLOAT,
DXGI_FORMAT_R32G32B32_FLOAT,
DXGI_FORMAT_R11G11B10_FLOAT,
DXGI_FORMAT_UNKNOWN,
]),
DXGI_FORMAT_R8G8B8A8_UNORM => Some(&[
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_B8G8R8X8_UNORM,
DXGI_FORMAT_UNKNOWN,
]),
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB => Some(&[
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_B8G8R8X8_UNORM,
DXGI_FORMAT_UNKNOWN,
]),
DXGI_FORMAT_B8G8R8A8_UNORM => Some(&[
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_UNKNOWN,
]),
DXGI_FORMAT_B8G8R8X8_UNORM => Some(&[
DXGI_FORMAT_B8G8R8X8_UNORM,
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_UNKNOWN,
]),
DXGI_FORMAT_B5G6R5_UNORM => Some(&[
DXGI_FORMAT_B5G6R5_UNORM,
DXGI_FORMAT_B8G8R8X8_UNORM,
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_UNKNOWN,
]),
DXGI_FORMAT_EX_A4R4G4B4_UNORM | DXGI_FORMAT_B4G4R4A4_UNORM => Some(&[
DXGI_FORMAT_B4G4R4A4_UNORM,
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_UNKNOWN,
]),
DXGI_FORMAT_A8_UNORM => Some(&[
DXGI_FORMAT_A8_UNORM,
DXGI_FORMAT_R8_UNORM,
DXGI_FORMAT_R8G8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_UNKNOWN,
]),
DXGI_FORMAT_R8_UNORM => Some(&[
DXGI_FORMAT_R8_UNORM,
DXGI_FORMAT_A8_UNORM,
DXGI_FORMAT_R8G8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_UNKNOWN,
]),
_ => None,
}
} }
impl Texture { pub fn d3d11_get_closest_format(
pub fn new(device: &ID3D11Device, size: Size<u32>, desc: D3D11_TEXTURE2D_DESC) -> Texture { device: &ID3D11Device,
let mut desc = D3D11_TEXTURE2D_DESC { format: DXGI_FORMAT,
Width: size.width, format_support_mask: i32,
Height: size.height, ) -> DXGI_FORMAT {
MipLevels: 1, let default_list = [format, DXGI_FORMAT_UNKNOWN];
ArraySize: 1, let format_support_list = d3d11_format_fallback_list(format)
SampleDesc: DXGI_SAMPLE_DESC { .unwrap_or(&default_list);
Count: 1, let format_support_mask = format_support_mask as u32;
Quality: 0
},
CPUAccessFlags: if desc.Usage == D3D11_USAGE_DYNAMIC {
D3D11_CPU_ACCESS_WRITE
} else {
0
},
..desc
};
desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
// determine number of mipmaps required for supported in format_support_list {
if desc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS { unsafe {
let mut width = desc.Width >> 5; if let Ok(supported_format) = device.CheckFormatSupport(*supported)
let mut height = desc.Height >> 5; && (supported_format & format_support_mask) == format_support_mask {
desc.BindFlags |= D3D11_BIND_RENDER_TARGET; return *supported;
while width != 0 && height != 0 {
width >>= 1;
height >>= 1;
desc.MipLevels += 1;
} }
} }
// determine if format is supported.
let mut format_support = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE;
if desc.BindFlags |= D3D11_BIND_RENDER_TARGET {
format_support |= D3D11_FORMAT_SUPPORT_RENDER_TARGET;
}
// todo: actually check format support
// d3d11_common: 83
todo!();
} }
} return DXGI_FORMAT_UNKNOWN;
}
// todo: d3d11.c 2097
pub type Result<T> = std::result::Result<T, Box<dyn Error>>;

View file

@ -147,7 +147,8 @@ impl Framebuffer {
} }
} }
pub(crate) fn copy_from(&mut self, image: &GlImage) -> Result<()>{ pub(crate) fn copy_from(&mut self, image: &GlImage) -> Result<()> {
// todo: may want to use a shader and draw a quad to be faster.
if image.size != self.size || image.format != self.format { if image.size != self.size || image.format != self.format {
self.init(image.size, image.format)?; self.init(image.size, image.format)?;
} }

View file

@ -27,7 +27,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);
} }