librashader/librashader-runtime-d3d11/src/util.rs

168 lines
5.2 KiB
Rust
Raw Normal View History

2022-12-01 11:05:12 +11:00
use crate::error;
2022-11-27 11:35:33 +11:00
use std::slice;
use windows::core::PCSTR;
2022-11-30 17:38:05 +11:00
use windows::Win32::Graphics::Direct3D::Fxc::{
D3DCompile, D3DCOMPILE_DEBUG, D3DCOMPILE_SKIP_OPTIMIZATION,
};
2022-11-27 11:35:33 +11:00
use windows::Win32::Graphics::Direct3D::ID3DBlob;
2022-11-30 17:38:05 +11:00
use windows::Win32::Graphics::Direct3D11::*;
use windows::Win32::Graphics::Dxgi::Common::*;
2022-11-26 18:38:15 +11:00
/// wtf retroarch?
const DXGI_FORMAT_EX_A4R4G4B4_UNORM: DXGI_FORMAT = DXGI_FORMAT(1000);
2022-11-26 18:38:15 +11:00
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,
}
}
2022-11-26 18:38:15 +11:00
pub fn d3d11_get_closest_format(
device: &ID3D11Device,
format: DXGI_FORMAT,
format_support_mask: i32,
) -> DXGI_FORMAT {
let default_list = [format, DXGI_FORMAT_UNKNOWN];
2022-11-30 17:38:05 +11:00
let format_support_list = d3d11_format_fallback_list(format).unwrap_or(&default_list);
2022-11-26 18:38:15 +11:00
let format_support_mask = format_support_mask as u32;
2022-11-26 18:38:15 +11:00
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;
}
}
}
2022-11-30 17:38:05 +11:00
DXGI_FORMAT_UNKNOWN
2022-11-26 18:38:15 +11:00
}
2022-12-01 11:05:12 +11:00
pub fn d3d_compile_shader(source: &[u8], entry: &[u8], version: &[u8]) -> error::Result<ID3DBlob> {
2022-11-27 11:35:33 +11:00
unsafe {
let mut blob = None;
D3DCompile(
source.as_ptr().cast(),
source.len(),
None,
None,
None,
PCSTR(entry.as_ptr()),
PCSTR(version.as_ptr()),
2022-12-01 11:05:12 +11:00
if cfg!(feature = "debug-shader") {
2022-11-27 11:35:33 +11:00
D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION
} else {
2022-12-02 11:16:13 +11:00
0
2022-11-27 11:35:33 +11:00
},
0,
&mut blob,
None,
)?;
Ok(blob.unwrap())
}
}
2022-11-30 17:38:05 +11:00
pub type ShaderFactory<'a, L, T> =
unsafe fn(&'a ID3D11Device, &[u8], linkage: L) -> windows::core::Result<T>;
2022-11-27 11:35:33 +11:00
2022-11-30 17:38:05 +11:00
pub fn d3d11_compile_bound_shader<'a, T, L>(
device: &'a ID3D11Device,
blob: &ID3DBlob,
linkage: L,
factory: ShaderFactory<'a, L, T>,
2022-12-01 11:05:12 +11:00
) -> error::Result<T>
2022-11-30 17:38:05 +11:00
where
L: Into<windows::core::InParam<'a, ID3D11ClassLinkage>>,
{
2022-11-27 11:35:33 +11:00
unsafe {
// SAFETY: slice as valid for as long as vs_blob is alive.
2022-11-30 17:38:05 +11:00
let dxil =
slice::from_raw_parts(blob.GetBufferPointer().cast::<u8>(), blob.GetBufferSize());
2022-11-27 11:35:33 +11:00
let compiled = factory(device, dxil, linkage)?;
Ok(compiled)
}
}
2022-11-30 17:38:05 +11:00
pub fn d3d11_create_input_layout(
device: &ID3D11Device,
desc: &[D3D11_INPUT_ELEMENT_DESC],
blob: &ID3DBlob,
2022-12-01 11:05:12 +11:00
) -> error::Result<ID3D11InputLayout> {
2022-11-27 11:35:33 +11:00
unsafe {
// SAFETY: slice as valid for as long as vs_blob is alive.
2022-11-30 17:38:05 +11:00
let dxil =
slice::from_raw_parts(blob.GetBufferPointer().cast::<u8>(), blob.GetBufferSize());
2022-11-27 11:35:33 +11:00
2022-11-30 17:38:05 +11:00
let compiled = device.CreateInputLayout(desc, dxil)?;
2022-11-27 11:35:33 +11:00
Ok(compiled)
}
}