dx11: lut upload
This commit is contained in:
parent
e64b2f3300
commit
5cd30ade02
|
@ -2,7 +2,8 @@ use std::path::Path;
|
|||
|
||||
pub struct Image {
|
||||
pub bytes: Vec<u8>,
|
||||
pub size: Size<u32>
|
||||
pub size: Size<u32>,
|
||||
pub pitch: usize,
|
||||
}
|
||||
|
||||
impl Image {
|
||||
|
@ -11,9 +12,13 @@ impl Image {
|
|||
|
||||
let height = image.height();
|
||||
let width = image.width();
|
||||
let pitch = image.sample_layout().height_stride.max(
|
||||
image.sample_layout().width_stride
|
||||
);
|
||||
|
||||
Ok(Image {
|
||||
bytes: image.to_vec(),
|
||||
bytes: image.into_raw(),
|
||||
pitch,
|
||||
size: Size {
|
||||
height,
|
||||
width,
|
||||
|
|
|
@ -1,19 +1,22 @@
|
|||
use std::error::Error;
|
||||
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 crate::texture::OwnedTexture;
|
||||
use librashader_common::image::Image;
|
||||
use librashader_common::Size;
|
||||
use librashader_preprocess::ShaderSource;
|
||||
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
|
||||
use librashader_reflect::back::{CompilerBackend, CompileShader, FromCompilation};
|
||||
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::ReflectShader;
|
||||
use librashader_reflect::reflect::semantics::{ReflectSemantics, SemanticMap, TextureSemantics, UniformSemantic, VariableSemantics};
|
||||
use crate::util::Texture;
|
||||
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 crate::util;
|
||||
|
||||
type ShaderPassMeta<'a> = (
|
||||
&'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(crate) device_context: ID3D11DeviceContext,
|
||||
pub(crate) d3d11: Direct3D11,
|
||||
pub(crate) preset: ShaderPreset,
|
||||
}
|
||||
|
||||
// todo: d3d11.c 2097
|
||||
type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
||||
|
||||
impl FilterChain {
|
||||
fn load_pass_semantics(
|
||||
uniform_semantics: &mut FxHashMap<String, UniformSemantic>,
|
||||
|
@ -87,7 +91,7 @@ impl FilterChain {
|
|||
}
|
||||
|
||||
/// 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)?;
|
||||
|
||||
// initialize passes
|
||||
|
@ -112,13 +116,13 @@ impl FilterChain {
|
|||
// feedback_textures.resize_with(filters.len(), Texture::default);
|
||||
|
||||
// load luts
|
||||
let luts = FilterChain::load_luts(&preset.textures)?;
|
||||
let luts = FilterChain::load_luts(device, &preset.textures)?;
|
||||
|
||||
// let (history_framebuffers, history_textures) =
|
||||
// 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(),
|
||||
|
@ -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();
|
||||
|
||||
for (index, texture) in textures.iter().enumerate() {
|
||||
let image = Image::load(&texture.path)?;
|
||||
let desc = D3D11_TEXTURE2D_DESC {
|
||||
Width: image.width,
|
||||
Height: image.height,
|
||||
Width: image.size.width,
|
||||
Height: image.size.height,
|
||||
Format: DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
Usage: D3D11_USAGE_DEFAULT,
|
||||
MiscFlags: if texture.mipmap {
|
||||
D3D11_RESOURCE_MISC_GENERATE_MIPS
|
||||
} else {
|
||||
0
|
||||
D3D11_RESOURCE_MISC_FLAG(0)
|
||||
},
|
||||
..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
|
||||
luts.insert(index, texture);
|
||||
|
||||
}
|
||||
Ok(luts)
|
||||
}
|
||||
|
||||
/// 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
|
||||
let preset = ShaderPreset::try_parse(path)?;
|
||||
Self::load_from_preset(preset)
|
||||
Self::load_from_preset(device, preset)
|
||||
}
|
||||
|
||||
fn load_preset(
|
||||
preset: &ShaderPreset,
|
||||
) -> Result<(Vec<ShaderPassMeta>, ReflectSemantics)> {
|
||||
fn load_preset(preset: &ShaderPreset) -> util::Result<(Vec<ShaderPassMeta>, ReflectSemantics)> {
|
||||
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
|
||||
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> =
|
||||
Default::default();
|
||||
|
@ -198,7 +203,7 @@ impl FilterChain {
|
|||
Ok::<_, Box<dyn Error>>((shader, source, reflect))
|
||||
})
|
||||
.into_iter()
|
||||
.collect::<Result<Vec<(&ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>()?;
|
||||
.collect::<util::Result<Vec<(&ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>()?;
|
||||
|
||||
for details in &passes {
|
||||
FilterChain::load_pass_semantics(
|
||||
|
|
|
@ -1,20 +1,26 @@
|
|||
use std::error::Error;
|
||||
use rustc_hash::FxHashMap;
|
||||
use windows::Win32::Graphics::Direct3D11::{D3D11_MAP_WRITE_DISCARD, ID3D11Buffer, ID3D11PixelShader, ID3D11SamplerState, ID3D11ShaderResourceView, ID3D11VertexShader};
|
||||
use windows::Win32::Graphics::Direct3D::ID3DBlob;
|
||||
use crate::filter_chain::FilterCommon;
|
||||
use crate::texture::{ExternalTexture, OwnedTexture};
|
||||
use librashader_common::Size;
|
||||
use librashader_preprocess::ShaderSource;
|
||||
use librashader_presets::ShaderPassConfig;
|
||||
use librashader_reflect::back::cross::GlslangHlslContext;
|
||||
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 crate::filter_chain::FilterCommon;
|
||||
use crate::util::Texture;
|
||||
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
|
||||
pub compiled: T,
|
||||
}
|
||||
|
||||
pub struct ConstantBuffer {
|
||||
|
@ -22,7 +28,7 @@ pub struct ConstantBuffer {
|
|||
pub size: u32,
|
||||
pub stage_mask: BindingStage,
|
||||
pub buffer: ID3D11Buffer,
|
||||
pub storage: Box<[u8]>
|
||||
pub storage: Box<[u8]>,
|
||||
}
|
||||
|
||||
// slang_process.cpp 141
|
||||
|
@ -34,7 +40,6 @@ pub struct FilterPass {
|
|||
|
||||
pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>,
|
||||
|
||||
|
||||
pub uniform_buffer: ConstantBuffer,
|
||||
pub push_buffer: ConstantBuffer,
|
||||
pub source: ShaderSource,
|
||||
|
@ -48,10 +53,8 @@ impl FilterPass {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn build_uniform<T>(
|
||||
buffer: &mut [u8],
|
||||
value: T,
|
||||
) where
|
||||
fn build_uniform<T>(buffer: &mut [u8], value: T)
|
||||
where
|
||||
T: Copy,
|
||||
T: bytemuck::Pod,
|
||||
{
|
||||
|
@ -65,14 +68,15 @@ impl FilterPass {
|
|||
buffer.copy_from_slice(vec4);
|
||||
}
|
||||
|
||||
fn bind_texture(texture_binding: &mut [Option<ID3D11ShaderResourceView>; 16],
|
||||
fn bind_texture(
|
||||
texture_binding: &mut [Option<ID3D11ShaderResourceView>; 16],
|
||||
sampler_binding: &mut [Option<ID3D11SamplerState>; 16],
|
||||
binding: &TextureBinding,
|
||||
texture: &Texture
|
||||
)
|
||||
{
|
||||
texture: &ExternalTexture,
|
||||
) {
|
||||
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
|
||||
|
@ -85,17 +89,14 @@ impl FilterPass {
|
|||
frame_direction: i32,
|
||||
fb_size: Size<u32>,
|
||||
// viewport: &Viewport,
|
||||
original: &Texture,
|
||||
source: &Texture,
|
||||
original: &ExternalTexture,
|
||||
source: &ExternalTexture,
|
||||
) {
|
||||
|
||||
let mut textures: [Option<ID3D11ShaderResourceView>; 16] = std::array::from_fn(|_| None);
|
||||
let mut samplers: [Option<ID3D11SamplerState>; 16] = std::array::from_fn(|_| None);
|
||||
|
||||
// Bind MVP
|
||||
if let Some(offset) =
|
||||
self.uniform_bindings.get(&VariableSemantics::MVP.into())
|
||||
{
|
||||
if let Some(offset) = self.uniform_bindings.get(&VariableSemantics::MVP.into()) {
|
||||
let mvp_size = mvp.len() * std::mem::size_of::<f32>();
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||
|
@ -105,10 +106,7 @@ impl FilterPass {
|
|||
}
|
||||
|
||||
// bind OutputSize
|
||||
if let Some(offset) = self
|
||||
.uniform_bindings
|
||||
.get(&VariableSemantics::Output.into())
|
||||
{
|
||||
if let Some(offset) = self.uniform_bindings.get(&VariableSemantics::Output.into()) {
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_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::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||
};
|
||||
FilterPass::build_uniform(
|
||||
&mut buffer[offset..][..4],
|
||||
frame_direction,
|
||||
)
|
||||
FilterPass::build_uniform(&mut buffer[offset..][..4], frame_direction)
|
||||
}
|
||||
|
||||
// bind Original sampler
|
||||
|
@ -178,10 +173,7 @@ impl FilterPass {
|
|||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
&mut buffer[offset..][..16],
|
||||
original.size,
|
||||
);
|
||||
FilterPass::build_vec4(&mut buffer[offset..][..16], original.size);
|
||||
}
|
||||
|
||||
// bind Source sampler
|
||||
|
@ -204,10 +196,7 @@ impl FilterPass {
|
|||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
&mut buffer[offset..][..16],
|
||||
source.size,
|
||||
);
|
||||
FilterPass::build_vec4(&mut buffer[offset..][..16], source.size);
|
||||
}
|
||||
|
||||
if let Some(binding) = self
|
||||
|
@ -227,10 +216,7 @@ impl FilterPass {
|
|||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
&mut buffer[offset..][..16],
|
||||
original.size,
|
||||
);
|
||||
FilterPass::build_vec4(&mut buffer[offset..][..16], original.size);
|
||||
}
|
||||
|
||||
// for (index, output) in parent.history_textures.iter().enumerate() {
|
||||
|
@ -385,10 +371,7 @@ impl FilterPass {
|
|||
parent: &FilterCommon,
|
||||
frame_count: u32,
|
||||
frame_direction: i32,
|
||||
) -> std::result::Result<(), Box<dyn Error>>
|
||||
{
|
||||
|
||||
|
||||
) -> std::result::Result<(), Box<dyn Error>> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -63,11 +63,10 @@ PixelOutput main(PixelInput pixelInput)
|
|||
return output;
|
||||
}\0";
|
||||
|
||||
|
||||
use std::mem::transmute;
|
||||
use gfx_maths::Mat4;
|
||||
use std::mem::transmute;
|
||||
|
||||
trait DXSample {
|
||||
pub trait DXSample {
|
||||
fn new() -> Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
|
@ -75,7 +74,9 @@ trait DXSample {
|
|||
fn bind_to_window(&mut self, hwnd: &HWND) -> Result<()>;
|
||||
|
||||
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_down(&mut self, _key: u8) {}
|
||||
|
||||
|
@ -88,8 +89,8 @@ trait DXSample {
|
|||
}
|
||||
}
|
||||
|
||||
fn run_sample<S>() -> Result<()>
|
||||
where
|
||||
fn run_sample<S>(mut sample: S) -> Result<()>
|
||||
where
|
||||
S: DXSample,
|
||||
{
|
||||
let instance = unsafe { GetModuleHandleA(None)? };
|
||||
|
@ -104,8 +105,6 @@ fn run_sample<S>() -> Result<()>
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
let mut sample = S::new()?;
|
||||
|
||||
let size = sample.window_size();
|
||||
|
||||
let atom = unsafe { RegisterClassExA(&wc) };
|
||||
|
@ -121,8 +120,6 @@ fn run_sample<S>() -> Result<()>
|
|||
|
||||
let mut title = sample.title();
|
||||
|
||||
|
||||
|
||||
title.push('\0');
|
||||
|
||||
let hwnd = unsafe {
|
||||
|
@ -216,7 +213,6 @@ extern "system" fn wndproc<S: DXSample>(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
struct Vertex {
|
||||
position: [f32; 3],
|
||||
|
@ -228,37 +224,37 @@ struct Vertex {
|
|||
struct TriangleUniforms {
|
||||
projection_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::time::Instant;
|
||||
use gfx_maths::{Quaternion, Vec3};
|
||||
use super::*;
|
||||
|
||||
const FRAME_COUNT: u32 = 2;
|
||||
|
||||
pub struct Sample {
|
||||
dxgi_factory: IDXGIFactory4,
|
||||
device: ID3D11Device,
|
||||
context: ID3D11DeviceContext,
|
||||
resources: Option<Resources>
|
||||
pub dxgi_factory: IDXGIFactory4,
|
||||
pub device: ID3D11Device,
|
||||
pub context: ID3D11DeviceContext,
|
||||
pub resources: Option<Resources>,
|
||||
}
|
||||
|
||||
pub struct Resources {
|
||||
swapchain: IDXGISwapChain,
|
||||
depth_buffer: ID3D11Texture2D,
|
||||
depth_stencil_view: ID3D11DepthStencilView,
|
||||
triangle_vertices: ID3D11Buffer,
|
||||
triangle_indices: ID3D11Buffer,
|
||||
triangle_uniforms: ID3D11Buffer,
|
||||
vs: ID3D11VertexShader,
|
||||
ps: ID3D11PixelShader,
|
||||
input_layout: ID3D11InputLayout,
|
||||
frame_start: Instant,
|
||||
frame_end: Instant,
|
||||
elapsed: f32,
|
||||
pub swapchain: IDXGISwapChain,
|
||||
pub depth_buffer: ID3D11Texture2D,
|
||||
pub depth_stencil_view: ID3D11DepthStencilView,
|
||||
pub triangle_vertices: ID3D11Buffer,
|
||||
pub triangle_indices: ID3D11Buffer,
|
||||
pub triangle_uniforms: ID3D11Buffer,
|
||||
pub vs: ID3D11VertexShader,
|
||||
pub ps: ID3D11PixelShader,
|
||||
pub input_layout: ID3D11InputLayout,
|
||||
pub frame_start: Instant,
|
||||
pub frame_end: Instant,
|
||||
pub elapsed: f32,
|
||||
triangle_uniform_values: TriangleUniforms,
|
||||
pub backbuffer: ID3D11Texture2D,
|
||||
pub rtv: ID3D11RenderTargetView,
|
||||
|
@ -272,7 +268,7 @@ mod d3d11_hello_triangle {
|
|||
dxgi_factory,
|
||||
device,
|
||||
context,
|
||||
resources: None
|
||||
resources: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -288,21 +284,24 @@ mod d3d11_hello_triangle {
|
|||
|
||||
let vs_compiled = unsafe {
|
||||
// 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 {
|
||||
self.device.CreateVertexShader(vs_compiled, None)
|
||||
}?;
|
||||
let vs = unsafe { self.device.CreateVertexShader(vs_compiled, None) }?;
|
||||
|
||||
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)
|
||||
}?;
|
||||
|
||||
|
||||
let (input_layout, stencil_state, raster_state)
|
||||
= create_pipeline_state(&self.device, vs_compiled)?;
|
||||
let (input_layout, stencil_state, raster_state) =
|
||||
create_pipeline_state(&self.device, vs_compiled)?;
|
||||
|
||||
unsafe {
|
||||
self.context.OMSetDepthStencilState(&stencil_state, 1);
|
||||
|
@ -332,7 +331,7 @@ mod d3d11_hello_triangle {
|
|||
Height: HEIGHT as f32,
|
||||
MinDepth: D3D11_MIN_DEPTH,
|
||||
MaxDepth: D3D11_MAX_DEPTH,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Ok(())
|
||||
|
@ -348,7 +347,7 @@ mod d3d11_hello_triangle {
|
|||
let time = time.as_secs() as f32 * 1000.0;
|
||||
|
||||
// framelimit set to 60fps
|
||||
if time < (1000.0f32 / 144.0f32) {
|
||||
if time < (1000.0f32 / 60.0f32) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -361,21 +360,42 @@ mod d3d11_hello_triangle {
|
|||
let buffer_number = 0;
|
||||
|
||||
unsafe {
|
||||
let mapped_resource = self.context.Map(&resources.triangle_uniforms, 0, D3D11_MAP_WRITE_DISCARD, 0)?;
|
||||
std::ptr::copy_nonoverlapping(&resources.triangle_uniform_values, mapped_resource.pData.cast(), 1);
|
||||
let mapped_resource = self.context.Map(
|
||||
&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);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
self.context.VSSetConstantBuffers(buffer_number, Some(&[Some(resources.triangle_uniforms.clone())]));
|
||||
self.context.OMSetRenderTargets(Some(&[Some(resources.rtv.clone())]), &resources.depth_stencil_view);
|
||||
self.context.VSSetConstantBuffers(
|
||||
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]))
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let color = [0.3, 0.4, 0.6, 1.0];
|
||||
self.context.ClearRenderTargetView(&resources.rtv, color.as_ptr());
|
||||
self.context.ClearDepthStencilView(&resources.depth_stencil_view, D3D11_CLEAR_DEPTH.0 as u32, 1.0, 0);
|
||||
self.context
|
||||
.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);
|
||||
}
|
||||
|
||||
|
@ -383,18 +403,25 @@ mod d3d11_hello_triangle {
|
|||
self.context.VSSetShader(&resources.vs, 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;
|
||||
self.context.IASetVertexBuffers(0, 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);
|
||||
self.context.IASetVertexBuffers(
|
||||
0,
|
||||
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 {
|
||||
self.context.DrawIndexed(3, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
unsafe {
|
||||
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 {
|
||||
let backbuffer: ID3D11Texture2D = swapchain.GetBuffer(0)?;
|
||||
let rtv = device.CreateRenderTargetView(&backbuffer, None)?;
|
||||
|
@ -410,9 +440,17 @@ mod d3d11_hello_triangle {
|
|||
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 {
|
||||
let input_layout = device.CreateInputLayout(&[
|
||||
let input_layout = device.CreateInputLayout(
|
||||
&[
|
||||
D3D11_INPUT_ELEMENT_DESC {
|
||||
SemanticName: s!("POSITION"),
|
||||
SemanticIndex: 0,
|
||||
|
@ -420,7 +458,7 @@ mod d3d11_hello_triangle {
|
|||
InputSlot: 0,
|
||||
AlignedByteOffset: 0,
|
||||
InputSlotClass: D3D11_INPUT_PER_VERTEX_DATA,
|
||||
InstanceDataStepRate: 0
|
||||
InstanceDataStepRate: 0,
|
||||
},
|
||||
D3D11_INPUT_ELEMENT_DESC {
|
||||
SemanticName: s!("COLOR"),
|
||||
|
@ -429,9 +467,11 @@ mod d3d11_hello_triangle {
|
|||
InputSlot: 0,
|
||||
AlignedByteOffset: D3D11_APPEND_ALIGNED_ELEMENT,
|
||||
InputSlotClass: D3D11_INPUT_PER_VERTEX_DATA,
|
||||
InstanceDataStepRate: 0
|
||||
InstanceDataStepRate: 0,
|
||||
},
|
||||
], vs_blob)?;
|
||||
],
|
||||
vs_blob,
|
||||
)?;
|
||||
|
||||
let stencil_state = device.CreateDepthStencilState(&D3D11_DEPTH_STENCIL_DESC {
|
||||
DepthEnable: BOOL::from(true),
|
||||
|
@ -451,7 +491,7 @@ mod d3d11_hello_triangle {
|
|||
StencilDepthFailOp: D3D11_STENCIL_OP_DECR,
|
||||
StencilPassOp: D3D11_STENCIL_OP_KEEP,
|
||||
StencilFunc: D3D11_COMPARISON_ALWAYS,
|
||||
}
|
||||
},
|
||||
})?;
|
||||
|
||||
let rasterizer_state = device.CreateRasterizerState(&D3D11_RASTERIZER_DESC {
|
||||
|
@ -464,16 +504,19 @@ mod d3d11_hello_triangle {
|
|||
FrontCounterClockwise: BOOL::from(false),
|
||||
MultisampleEnable: BOOL::from(false),
|
||||
ScissorEnable: BOOL::from(false),
|
||||
SlopeScaledDepthBias: 0.0f32
|
||||
SlopeScaledDepthBias: 0.0f32,
|
||||
})?;
|
||||
|
||||
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 {
|
||||
let buffer = device.CreateTexture2D(&D3D11_TEXTURE2D_DESC {
|
||||
let buffer = device.CreateTexture2D(
|
||||
&D3D11_TEXTURE2D_DESC {
|
||||
Width: WIDTH as u32,
|
||||
Height: HEIGHT as u32,
|
||||
MipLevels: 1,
|
||||
|
@ -481,24 +524,27 @@ mod d3d11_hello_triangle {
|
|||
Format: DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
SampleDesc: DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0
|
||||
Quality: 0,
|
||||
},
|
||||
Usage: D3D11_USAGE_DEFAULT,
|
||||
BindFlags: D3D11_BIND_DEPTH_STENCIL,
|
||||
CPUAccessFlags: Default::default(),
|
||||
MiscFlags: Default::default(),
|
||||
}, None)?;
|
||||
},
|
||||
None,
|
||||
)?;
|
||||
|
||||
let view = device.CreateDepthStencilView(&buffer,Some(&D3D11_DEPTH_STENCIL_VIEW_DESC {
|
||||
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,
|
||||
},
|
||||
Texture2D: D3D11_TEX2D_DSV { MipSlice: 0 },
|
||||
},
|
||||
..Default::default()
|
||||
}))?;
|
||||
}),
|
||||
)?;
|
||||
|
||||
Ok((buffer, view))
|
||||
}
|
||||
|
@ -506,22 +552,21 @@ mod d3d11_hello_triangle {
|
|||
|
||||
fn create_triangle_uniforms(device: &ID3D11Device) -> Result<ID3D11Buffer> {
|
||||
unsafe {
|
||||
device.CreateBuffer(&D3D11_BUFFER_DESC {
|
||||
device.CreateBuffer(
|
||||
&D3D11_BUFFER_DESC {
|
||||
ByteWidth: (std::mem::size_of::<TriangleUniforms>()) as u32,
|
||||
Usage: D3D11_USAGE_DYNAMIC,
|
||||
BindFlags: D3D11_BIND_CONSTANT_BUFFER,
|
||||
CPUAccessFlags: D3D11_CPU_ACCESS_WRITE,
|
||||
MiscFlags: Default::default(),
|
||||
StructureByteStride: 0,
|
||||
}, None)
|
||||
},
|
||||
None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn create_triangle_buffers(
|
||||
device: &ID3D11Device,
|
||||
) -> Result<(ID3D11Buffer, ID3D11Buffer)> {
|
||||
fn create_triangle_buffers(device: &ID3D11Device) -> Result<(ID3D11Buffer, ID3D11Buffer)> {
|
||||
let vertices = [
|
||||
Vertex {
|
||||
position: [0.5f32, -0.5, 0.0],
|
||||
|
@ -539,35 +584,40 @@ mod d3d11_hello_triangle {
|
|||
|
||||
let indices = [0, 1, 2];
|
||||
unsafe {
|
||||
let vertex_buffer = device.CreateBuffer(&D3D11_BUFFER_DESC {
|
||||
let vertex_buffer = device.CreateBuffer(
|
||||
&D3D11_BUFFER_DESC {
|
||||
ByteWidth: (std::mem::size_of::<Vertex>() * vertices.len()) as u32,
|
||||
Usage: D3D11_USAGE_DEFAULT,
|
||||
BindFlags: D3D11_BIND_VERTEX_BUFFER,
|
||||
CPUAccessFlags: Default::default(),
|
||||
MiscFlags: Default::default(),
|
||||
StructureByteStride: 0,
|
||||
}, Some(&D3D11_SUBRESOURCE_DATA {
|
||||
},
|
||||
Some(&D3D11_SUBRESOURCE_DATA {
|
||||
pSysMem: vertices.as_ptr().cast(),
|
||||
SysMemPitch: 0,
|
||||
SysMemSlicePitch: 0,
|
||||
}))?;
|
||||
}),
|
||||
)?;
|
||||
|
||||
let index_buffer = device.CreateBuffer(&D3D11_BUFFER_DESC {
|
||||
let index_buffer = device.CreateBuffer(
|
||||
&D3D11_BUFFER_DESC {
|
||||
ByteWidth: (std::mem::size_of::<u32>() * indices.len()) as u32,
|
||||
Usage: D3D11_USAGE_DEFAULT,
|
||||
BindFlags: D3D11_BIND_INDEX_BUFFER,
|
||||
CPUAccessFlags: Default::default(),
|
||||
MiscFlags: Default::default(),
|
||||
StructureByteStride: 0,
|
||||
}, Some(&D3D11_SUBRESOURCE_DATA {
|
||||
},
|
||||
Some(&D3D11_SUBRESOURCE_DATA {
|
||||
pSysMem: indices.as_ptr().cast(),
|
||||
SysMemPitch: 0,
|
||||
SysMemSlicePitch: 0,
|
||||
}))?;
|
||||
}),
|
||||
)?;
|
||||
|
||||
Ok((vertex_buffer, index_buffer))
|
||||
}
|
||||
|
||||
}
|
||||
fn create_device() -> Result<(IDXGIFactory4, ID3D11Device, ID3D11DeviceContext)> {
|
||||
let dxgi_factory_flags = if cfg!(debug_assertions) {
|
||||
|
@ -583,19 +633,27 @@ mod d3d11_hello_triangle {
|
|||
let mut out_context = None;
|
||||
let mut _out_feature_level = D3D_FEATURE_LEVEL_11_0;
|
||||
|
||||
unsafe { D3D11CreateDevice(None, D3D_DRIVER_TYPE_HARDWARE,
|
||||
unsafe {
|
||||
D3D11CreateDevice(
|
||||
None,
|
||||
D3D_DRIVER_TYPE_HARDWARE,
|
||||
HINSTANCE::default(),
|
||||
Default::default(),
|
||||
D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_DEBUG,
|
||||
Some(&feature_levels),
|
||||
D3D11_SDK_VERSION,
|
||||
Some(&mut out_device),
|
||||
Some(&mut _out_feature_level),
|
||||
Some(&mut out_context))
|
||||
Some(&mut out_context),
|
||||
)
|
||||
}?;
|
||||
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 {
|
||||
BufferDesc: DXGI_MODE_DESC {
|
||||
Width: WIDTH as u32,
|
||||
|
@ -620,7 +678,6 @@ mod d3d11_hello_triangle {
|
|||
Flags: 0,
|
||||
};
|
||||
|
||||
|
||||
let mut swap_chain = None;
|
||||
unsafe {
|
||||
fac.CreateSwapChain(&*device, &swapchain_desc, &mut swap_chain)
|
||||
|
@ -630,21 +687,30 @@ mod d3d11_hello_triangle {
|
|||
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 {
|
||||
let mut blob = None;
|
||||
D3DCompile(source.as_ptr().cast(), source.len(),
|
||||
None, None, None,
|
||||
D3DCompile(
|
||||
source.as_ptr().cast(),
|
||||
source.len(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
PCSTR(entry.as_ptr()),
|
||||
PCSTR(version.as_ptr()), D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION, 0, &mut blob, None)?;
|
||||
PCSTR(version.as_ptr()),
|
||||
D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION,
|
||||
0,
|
||||
&mut blob,
|
||||
None,
|
||||
)?;
|
||||
|
||||
Ok(blob.unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() -> Result<()> {
|
||||
run_sample::<d3d11_hello_triangle::Sample>()?;
|
||||
pub fn main<S: DXSample>(sample: S) -> Result<()> {
|
||||
run_sample(sample)?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,31 +1,40 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(let_chains)]
|
||||
|
||||
mod filter_chain;
|
||||
|
||||
|
||||
use librashader_preprocess::ShaderSource;
|
||||
use librashader_presets::ShaderPassConfig;
|
||||
use librashader_reflect::back::targets::HLSL;
|
||||
use librashader_reflect::back::{CompileShader, FromCompilation};
|
||||
use librashader_reflect::front::shaderc::GlslangCompilation;
|
||||
use rustc_hash::FxHashMap;
|
||||
use std::error::Error;
|
||||
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;
|
||||
|
||||
mod filter_pass;
|
||||
#[cfg(test)]
|
||||
mod hello_triangle;
|
||||
mod filter_pass;
|
||||
mod texture;
|
||||
mod util;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::hello_triangle::DXSample;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
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();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
146
librashader-runtime-dx11/src/texture.rs
Normal file
146
librashader-runtime-dx11/src/texture.rs
Normal 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,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Texture {
|
||||
pub handle: ID3D11Texture2D,
|
||||
pub staging: ID3D11Texture2D,
|
||||
pub srv: ID3D11ShaderResourceView,
|
||||
pub sampler: ID3D11SamplerState,
|
||||
pub desc: D3D11_TEXTURE2D_DESC,
|
||||
pub size: Size<u32>
|
||||
// pub image: GlImage,
|
||||
// pub filter: FilterMode,
|
||||
// pub mip_filter: FilterMode,
|
||||
// pub wrap_mode: WrapMode,
|
||||
}
|
||||
use windows::Win32::Graphics::Direct3D11::*;
|
||||
use windows::Win32::Graphics::Dxgi::Common::*;
|
||||
use std::error::Error;
|
||||
|
||||
impl Texture {
|
||||
pub fn new(device: &ID3D11Device, size: Size<u32>, desc: D3D11_TEXTURE2D_DESC) -> Texture {
|
||||
let mut desc = D3D11_TEXTURE2D_DESC {
|
||||
Width: size.width,
|
||||
Height: size.height,
|
||||
MipLevels: 1,
|
||||
ArraySize: 1,
|
||||
SampleDesc: DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
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
|
||||
if desc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS {
|
||||
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.
|
||||
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!();
|
||||
/// wtf retroarch?
|
||||
const DXGI_FORMAT_EX_A4R4G4B4_UNORM: DXGI_FORMAT = DXGI_FORMAT(1000);
|
||||
|
||||
const fn d3d11_format_fallback_list(format: DXGI_FORMAT) -> Option<&'static [DXGI_FORMAT]> {
|
||||
match format {
|
||||
DXGI_FORMAT_R32G32B32A32_FLOAT => Some(&[
|
||||
DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn d3d11_get_closest_format(
|
||||
device: &ID3D11Device,
|
||||
format: DXGI_FORMAT,
|
||||
format_support_mask: i32,
|
||||
) -> DXGI_FORMAT {
|
||||
let default_list = [format, DXGI_FORMAT_UNKNOWN];
|
||||
let format_support_list = d3d11_format_fallback_list(format)
|
||||
.unwrap_or(&default_list);
|
||||
let format_support_mask = format_support_mask as u32;
|
||||
|
||||
for supported in format_support_list {
|
||||
unsafe {
|
||||
if let Ok(supported_format) = device.CheckFormatSupport(*supported)
|
||||
&& (supported_format & format_support_mask) == format_support_mask {
|
||||
return *supported;
|
||||
}
|
||||
}
|
||||
}
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
// todo: d3d11.c 2097
|
||||
pub type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
||||
|
|
|
@ -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 {
|
||||
self.init(image.size, image.format)?;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue