d3d12: add proper fallback for output textures that need mipmapping

This commit is contained in:
chyyran 2023-02-12 23:27:18 -05:00
parent d6bbdb43fd
commit f2357f9ab1
9 changed files with 71 additions and 33 deletions

View file

@ -44,6 +44,7 @@ features = [
] ]
[target.'cfg(windows)'.dev-dependencies.windows] [target.'cfg(windows)'.dev-dependencies.windows]
version = "0.44.0"
features = [ features = [
"Win32_Foundation", "Win32_Foundation",
"Win32_Graphics_Dxgi_Common", "Win32_Graphics_Dxgi_Common",

View file

@ -256,8 +256,14 @@ impl FilterChainD3D12 {
&preset.textures, &preset.textures,
)?; )?;
let framebuffer_gen = let framebuffer_gen = || {
|| OwnedImage::new(device, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm, false); OwnedImage::new(
device,
Size::new(1, 1),
ImageFormat::R8G8B8A8Unorm.into(),
false,
)
};
let input_gen = || None; let input_gen = || None;
let framebuffer_init = FramebufferInit::new( let framebuffer_init = FramebufferInit::new(
filters.iter().map(|f| &f.reflection.meta), filters.iter().map(|f| &f.reflection.meta),
@ -496,7 +502,7 @@ impl FilterChainD3D12 {
// old back will get dropped.. do we need to defer? // old back will get dropped.. do we need to defer?
let _old_back = std::mem::replace( let _old_back = std::mem::replace(
&mut back, &mut back,
OwnedImage::new(&self.common.d3d12, input.size, input.format.into(), false)?, OwnedImage::new(&self.common.d3d12, input.size, input.format, false)?,
); );
} }
unsafe { unsafe {
@ -627,6 +633,16 @@ impl FilterChainD3D12 {
source.wrap_mode = pass.config.wrap_mode; source.wrap_mode = pass.config.wrap_mode;
let target = &self.output_framebuffers[index]; let target = &self.output_framebuffers[index];
if pass.pipeline.format != target.format {
// eprintln!("recompiling final pipeline");
pass.pipeline.recompile(
target.format,
&self.common.root_signature,
&self.common.d3d12,
)?;
}
util::d3d12_resource_transition( util::d3d12_resource_transition(
cmd, cmd,
&target.handle, &target.handle,

View file

@ -13,7 +13,8 @@ use windows::Win32::Graphics::Direct3D12::{
D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FORMAT_SUPPORT1_MIP, D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FORMAT_SUPPORT1_MIP,
D3D12_FORMAT_SUPPORT1_RENDER_TARGET, D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE, D3D12_FORMAT_SUPPORT1_RENDER_TARGET, D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE,
D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_HEAP_FLAG_NONE, D3D12_HEAP_PROPERTIES, D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD,
D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE, D3D12_HEAP_FLAG_NONE, D3D12_HEAP_PROPERTIES,
D3D12_HEAP_TYPE_DEFAULT, D3D12_MEMORY_POOL_UNKNOWN, D3D12_RENDER_TARGET_VIEW_DESC, D3D12_HEAP_TYPE_DEFAULT, D3D12_MEMORY_POOL_UNKNOWN, D3D12_RENDER_TARGET_VIEW_DESC,
D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_DESC, D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_DESC,
D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
@ -24,13 +25,13 @@ use windows::Win32::Graphics::Direct3D12::{
D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_TEX2D_RTV, D3D12_TEX2D_SRV, D3D12_TEXTURE_COPY_LOCATION, D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_TEX2D_RTV, D3D12_TEX2D_SRV, D3D12_TEXTURE_COPY_LOCATION,
D3D12_TEXTURE_COPY_LOCATION_0, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, D3D12_TEXTURE_COPY_LOCATION_0, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
}; };
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC; use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_SAMPLE_DESC};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct OwnedImage { pub(crate) struct OwnedImage {
pub(crate) handle: ID3D12Resource, pub(crate) handle: ID3D12Resource,
pub(crate) size: Size<u32>, pub(crate) size: Size<u32>,
pub(crate) format: ImageFormat, pub(crate) format: DXGI_FORMAT,
pub(crate) max_mipmap: u16, pub(crate) max_mipmap: u16,
device: ID3D12Device, device: ID3D12Device,
} }
@ -38,10 +39,32 @@ pub(crate) struct OwnedImage {
static CLEAR: &[f32; 4] = &[0.0, 0.0, 0.0, 0.0]; static CLEAR: &[f32; 4] = &[0.0, 0.0, 0.0, 0.0];
impl OwnedImage { impl OwnedImage {
pub fn get_format_support(
device: &ID3D12Device,
format: DXGI_FORMAT,
mipmap: bool,
) -> DXGI_FORMAT {
let mut format_support = D3D12_FEATURE_DATA_FORMAT_SUPPORT {
Format: format,
Support1: D3D12_FORMAT_SUPPORT1_TEXTURE2D
| D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE
| D3D12_FORMAT_SUPPORT1_RENDER_TARGET,
..Default::default()
};
if mipmap {
format_support.Support1 |= D3D12_FORMAT_SUPPORT1_MIP;
format_support.Support2 |=
D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE;
}
d3d12_get_closest_format(device, format_support)
}
pub fn new( pub fn new(
device: &ID3D12Device, device: &ID3D12Device,
size: Size<u32>, size: Size<u32>,
format: ImageFormat, format: DXGI_FORMAT,
mipmap: bool, mipmap: bool,
) -> error::Result<OwnedImage> { ) -> error::Result<OwnedImage> {
let miplevels = if mipmap { let miplevels = if mipmap {
@ -76,9 +99,11 @@ impl OwnedImage {
if mipmap { if mipmap {
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
format_support.Support1 |= D3D12_FORMAT_SUPPORT1_MIP; format_support.Support1 |= D3D12_FORMAT_SUPPORT1_MIP;
format_support.Support2 |=
D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE;
} }
desc.Format = d3d12_get_closest_format(device, desc.Format, format_support); desc.Format = d3d12_get_closest_format(device, format_support);
let mut resource: Option<ID3D12Resource> = None; let mut resource: Option<ID3D12Resource> = None;
unsafe { unsafe {
device.CreateCommittedResource( device.CreateCommittedResource(
@ -101,7 +126,7 @@ impl OwnedImage {
Ok(OwnedImage { Ok(OwnedImage {
handle: resource, handle: resource,
size, size,
format, format: desc.Format,
device: device.clone(), device: device.clone(),
max_mipmap: miplevels as u16, max_mipmap: miplevels as u16,
}) })
@ -295,13 +320,14 @@ impl OwnedImage {
mipmap: bool, mipmap: bool,
) -> error::Result<Size<u32>> { ) -> error::Result<Size<u32>> {
let size = source_size.scale_viewport(scaling, *viewport_size); let size = source_size.scale_viewport(scaling, *viewport_size);
let format = Self::get_format_support(&self.device, format.into(), mipmap);
if self.size != size if self.size != size
|| (mipmap && self.max_mipmap == 1) || (mipmap && self.max_mipmap == 1)
|| (!mipmap && self.max_mipmap != 1) || (!mipmap && self.max_mipmap != 1)
|| format != self.format || format != self.format
{ {
let mut new = OwnedImage::new(&self.device, size, format, mipmap)?; let mut new = OwnedImage::new(&self.device, size, format, mipmap)?;
std::mem::swap(self, &mut new); std::mem::swap(self, &mut new);
} }
Ok(size) Ok(size)

View file

@ -1,4 +1,3 @@
use widestring::u16cstr;
use crate::error::assume_d3d12_init; use crate::error::assume_d3d12_init;
use crate::error::FilterChainError::Direct3DOperationError; use crate::error::FilterChainError::Direct3DOperationError;
use crate::quad_render::DrawQuad; use crate::quad_render::DrawQuad;
@ -6,6 +5,7 @@ use crate::{error, util};
use librashader_reflect::back::cross::CrossHlslContext; use librashader_reflect::back::cross::CrossHlslContext;
use librashader_reflect::back::dxil::DxilObject; use librashader_reflect::back::dxil::DxilObject;
use librashader_reflect::back::ShaderCompilerOutput; use librashader_reflect::back::ShaderCompilerOutput;
use widestring::u16cstr;
use windows::Win32::Foundation::BOOL; use windows::Win32::Foundation::BOOL;
use windows::Win32::Graphics::Direct3D::Dxc::{ use windows::Win32::Graphics::Direct3D::Dxc::{
CLSID_DxcLibrary, DxcCreateInstance, IDxcBlob, IDxcCompiler, IDxcUtils, IDxcValidator, DXC_CP, CLSID_DxcLibrary, DxcCreateInstance, IDxcBlob, IDxcCompiler, IDxcUtils, IDxcValidator, DXC_CP,
@ -309,12 +309,8 @@ impl D3D12GraphicsPipeline {
) -> error::Result<D3D12GraphicsPipeline> { ) -> error::Result<D3D12GraphicsPipeline> {
let vertex_dxil = let vertex_dxil =
util::dxc_compile_shader(library, dxc, &shader_assembly.vertex, u16cstr!("vs_6_0"))?; util::dxc_compile_shader(library, dxc, &shader_assembly.vertex, u16cstr!("vs_6_0"))?;
let fragment_dxil = util::dxc_compile_shader( let fragment_dxil =
library, util::dxc_compile_shader(library, dxc, &shader_assembly.fragment, u16cstr!("ps_6_0"))?;
dxc,
&shader_assembly.fragment,
u16cstr!("ps_6_0")
)?;
Self::new_from_blobs( Self::new_from_blobs(
device, device,

View file

@ -36,10 +36,10 @@ mod tests {
// "../test/slang-shaders/crt/crt-lottes.slangp", // "../test/slang-shaders/crt/crt-lottes.slangp",
// "../test/basic.slangp", // "../test/basic.slangp",
// "../test/slang-shaders/handheld/console-border/gbc-lcd-grid-v2.slangp", // "../test/slang-shaders/handheld/console-border/gbc-lcd-grid-v2.slangp",
"../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp", // "../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
// "../test/slang-shaders/test/feedback.slangp", // "../test/slang-shaders/test/feedback.slangp",
// "../test/slang-shaders/test/history.slangp", // "../test/slang-shaders/test/history.slangp",
// "../test/slang-shaders/crt/crt-royale.slangp", "../test/slang-shaders/crt/crt-royale.slangp",
// "../test/slang-shaders/vhs/VHSPro.slangp", // "../test/slang-shaders/vhs/VHSPro.slangp",
&SampleCommandLine { &SampleCommandLine {
use_warp_device: false, use_warp_device: false,

View file

@ -68,7 +68,7 @@ impl LutTexture {
format_support.Support1 |= D3D12_FORMAT_SUPPORT1_MIP; format_support.Support1 |= D3D12_FORMAT_SUPPORT1_MIP;
} }
desc.Format = d3d12_get_closest_format(device, desc.Format, format_support); desc.Format = d3d12_get_closest_format(device, format_support);
let descriptor = heap.alloc_slot()?; let descriptor = heap.alloc_slot()?;
// create handles on GPU // create handles on GPU
@ -183,7 +183,7 @@ impl LutTexture {
resource.clone(), resource.clone(),
descriptor, descriptor,
source.size, source.size,
ImageFormat::R8G8B8A8Unorm, ImageFormat::R8G8B8A8Unorm.into(),
filter, filter,
wrap_mode, wrap_mode,
); );

View file

@ -7,6 +7,9 @@ use librashader_runtime::scaling::MipmapSize;
use std::mem::ManuallyDrop; use std::mem::ManuallyDrop;
use std::ops::Deref; use std::ops::Deref;
use widestring::u16cstr; use widestring::u16cstr;
use windows::Win32::Graphics::Direct3D::Dxc::{
CLSID_DxcCompiler, CLSID_DxcLibrary, DxcCreateInstance,
};
use windows::Win32::Graphics::Direct3D12::{ use windows::Win32::Graphics::Direct3D12::{
ID3D12DescriptorHeap, ID3D12Device, ID3D12GraphicsCommandList, ID3D12PipelineState, ID3D12DescriptorHeap, ID3D12Device, ID3D12GraphicsCommandList, ID3D12PipelineState,
ID3D12Resource, ID3D12RootSignature, D3D12_COMPUTE_PIPELINE_STATE_DESC, ID3D12Resource, ID3D12RootSignature, D3D12_COMPUTE_PIPELINE_STATE_DESC,
@ -17,7 +20,6 @@ use windows::Win32::Graphics::Direct3D12::{
D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_TEX2D_SRV, D3D12_TEX2D_UAV, D3D12_UAV_DIMENSION_TEXTURE2D, D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_TEX2D_SRV, D3D12_TEX2D_UAV, D3D12_UAV_DIMENSION_TEXTURE2D,
D3D12_UNORDERED_ACCESS_VIEW_DESC, D3D12_UNORDERED_ACCESS_VIEW_DESC_0, D3D12_UNORDERED_ACCESS_VIEW_DESC, D3D12_UNORDERED_ACCESS_VIEW_DESC_0,
}; };
use windows::Win32::Graphics::Direct3D::Dxc::{CLSID_DxcCompiler, CLSID_DxcLibrary, DxcCreateInstance};
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT; use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT;
static GENERATE_MIPS_SRC: &[u8] = b" static GENERATE_MIPS_SRC: &[u8] = b"
@ -129,7 +131,8 @@ impl D3D12MipmapGen {
let library = DxcCreateInstance(&CLSID_DxcLibrary)?; let library = DxcCreateInstance(&CLSID_DxcLibrary)?;
let compiler = DxcCreateInstance(&CLSID_DxcCompiler)?; let compiler = DxcCreateInstance(&CLSID_DxcCompiler)?;
let blob = dxc_compile_shader(&library, &compiler, GENERATE_MIPS_SRC, u16cstr!("cs_6_0"))?; let blob =
dxc_compile_shader(&library, &compiler, GENERATE_MIPS_SRC, u16cstr!("cs_6_0"))?;
let blob = let blob =
std::slice::from_raw_parts(blob.GetBufferPointer().cast(), blob.GetBufferSize()); std::slice::from_raw_parts(blob.GetBufferPointer().cast(), blob.GetBufferSize());
let root_signature: ID3D12RootSignature = device.CreateRootSignature(0, blob)?; let root_signature: ID3D12RootSignature = device.CreateRootSignature(0, blob)?;

View file

@ -1,5 +1,5 @@
use crate::descriptor_heap::{CpuStagingHeap, D3D12DescriptorHeapSlot, RenderTargetHeap}; use crate::descriptor_heap::{CpuStagingHeap, D3D12DescriptorHeapSlot, RenderTargetHeap};
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode}; use librashader_common::{FilterMode, Size, WrapMode};
use std::ops::Deref; use std::ops::Deref;
use windows::Win32::Graphics::Direct3D12::{ID3D12Resource, D3D12_CPU_DESCRIPTOR_HANDLE}; use windows::Win32::Graphics::Direct3D12::{ID3D12Resource, D3D12_CPU_DESCRIPTOR_HANDLE};
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT; use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT;
@ -96,7 +96,7 @@ impl InputTexture {
resource: ID3D12Resource, resource: ID3D12Resource,
handle: D3D12DescriptorHeapSlot<CpuStagingHeap>, handle: D3D12DescriptorHeapSlot<CpuStagingHeap>,
size: Size<u32>, size: Size<u32>,
format: ImageFormat, format: DXGI_FORMAT,
filter: FilterMode, filter: FilterMode,
wrap_mode: WrapMode, wrap_mode: WrapMode,
) -> InputTexture { ) -> InputTexture {
@ -105,7 +105,7 @@ impl InputTexture {
resource, resource,
descriptor: srv, descriptor: srv,
size, size,
format: format.into(), format,
wrap_mode, wrap_mode,
filter, filter,
} }

View file

@ -99,16 +99,16 @@ const fn d3d12_format_fallback_list(format: DXGI_FORMAT) -> Option<&'static [DXG
pub fn d3d12_get_closest_format( pub fn d3d12_get_closest_format(
device: &ID3D12Device, device: &ID3D12Device,
format: DXGI_FORMAT,
format_support: D3D12_FEATURE_DATA_FORMAT_SUPPORT, format_support: D3D12_FEATURE_DATA_FORMAT_SUPPORT,
) -> DXGI_FORMAT { ) -> DXGI_FORMAT {
let format = format_support.Format;
let default_list = [format, DXGI_FORMAT_UNKNOWN]; let default_list = [format, DXGI_FORMAT_UNKNOWN];
let format_support_list = d3d12_format_fallback_list(format).unwrap_or(&default_list); let format_support_list = d3d12_format_fallback_list(format).unwrap_or(&default_list);
for supported in format_support_list { for supported in format_support_list {
unsafe { unsafe {
let mut support = D3D12_FEATURE_DATA_FORMAT_SUPPORT { let mut support = D3D12_FEATURE_DATA_FORMAT_SUPPORT {
Format: format, Format: *supported,
..Default::default() ..Default::default()
}; };
if device if device
@ -137,11 +137,7 @@ pub fn dxc_compile_shader(
let include = unsafe { library.CreateDefaultIncludeHandler()? }; let include = unsafe { library.CreateDefaultIncludeHandler()? };
let source = source.as_ref(); let source = source.as_ref();
let blob = unsafe { let blob = unsafe {
library.CreateBlobFromPinned( library.CreateBlobFromPinned(source.as_ptr().cast(), source.len() as u32, DXC_CP_UTF8)?
source.as_ptr().cast(),
source.len() as u32,
DXC_CP_UTF8,
)?
}; };
unsafe { unsafe {