librashader/librashader-runtime-d3d12/src/luts.rs

218 lines
7.5 KiB
Rust
Raw Normal View History

2023-02-06 10:34:30 +11:00
use crate::descriptor_heap::{CpuStagingHeap, D3D12DescriptorHeap};
2023-01-25 15:15:43 +11:00
use crate::error;
use crate::error::assume_d3d12_init;
2023-02-06 08:17:23 +11:00
use crate::mipmap::MipmapGenContext;
use crate::texture::InputTexture;
2023-01-25 17:32:10 +11:00
use crate::util::{d3d12_get_closest_format, d3d12_resource_transition, d3d12_update_subresources};
2023-02-06 10:34:30 +11:00
use librashader_common::{FilterMode, ImageFormat, WrapMode};
2023-01-24 18:02:27 +11:00
use librashader_runtime::image::Image;
2023-01-27 09:57:54 +11:00
use librashader_runtime::scaling::MipmapSize;
2023-02-06 08:17:23 +11:00
use std::ops::Deref;
use windows::Win32::Graphics::Direct3D12::{
ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_FEATURE_DATA_FORMAT_SUPPORT,
D3D12_FORMAT_SUPPORT1_MIP, D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE,
2023-02-06 10:34:30 +11:00
D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_HEAP_FLAG_NONE, D3D12_HEAP_PROPERTIES,
D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_TYPE_UPLOAD, D3D12_MEMORY_POOL_UNKNOWN,
D3D12_PLACED_SUBRESOURCE_FOOTPRINT, D3D12_RESOURCE_DESC, D3D12_RESOURCE_DIMENSION_BUFFER,
D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_SHADER_RESOURCE_VIEW_DESC,
D3D12_SHADER_RESOURCE_VIEW_DESC_0, D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_SUBRESOURCE_DATA,
D3D12_TEX2D_SRV, D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
2023-02-06 08:17:23 +11:00
};
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
2023-01-24 18:02:27 +11:00
pub struct LutTexture {
2023-01-25 15:15:43 +11:00
resource: ID3D12Resource,
2023-02-01 11:23:57 +11:00
view: InputTexture,
2023-01-28 17:38:55 +11:00
miplevels: Option<u16>,
2023-01-24 18:02:27 +11:00
}
impl LutTexture {
pub fn new(
device: &ID3D12Device,
2023-02-01 09:50:47 +11:00
heap: &mut D3D12DescriptorHeap<CpuStagingHeap>,
2023-01-25 15:15:43 +11:00
cmd: &ID3D12GraphicsCommandList,
2023-01-24 18:02:27 +11:00
source: &Image,
filter: FilterMode,
wrap_mode: WrapMode,
2023-01-25 15:15:43 +11:00
mipmap: bool,
2023-01-25 17:32:10 +11:00
) -> error::Result<(LutTexture, ID3D12Resource)> {
2023-01-28 17:38:55 +11:00
let miplevels = source.size.calculate_miplevels() as u16;
2023-01-25 15:15:43 +11:00
let mut desc = D3D12_RESOURCE_DESC {
Dimension: D3D12_RESOURCE_DIMENSION_TEXTURE2D,
Alignment: 0,
Width: source.size.width as u64,
Height: source.size.height,
DepthOrArraySize: 1,
2023-01-28 17:38:55 +11:00
MipLevels: if mipmap { miplevels } else { 1 },
2023-01-25 15:15:43 +11:00
Format: ImageFormat::R8G8B8A8Unorm.into(),
SampleDesc: DXGI_SAMPLE_DESC {
Count: 1,
Quality: 0,
},
Layout: Default::default(),
Flags: Default::default(),
};
2023-01-28 17:38:55 +11:00
let mut format_support = D3D12_FEATURE_DATA_FORMAT_SUPPORT {
2023-01-25 15:15:43 +11:00
Format: desc.Format,
Support1: D3D12_FORMAT_SUPPORT1_TEXTURE2D | D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE,
..Default::default()
};
2023-01-28 17:38:55 +11:00
if mipmap {
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
format_support.Support1 |= D3D12_FORMAT_SUPPORT1_MIP;
}
2023-01-25 15:15:43 +11:00
desc.Format = d3d12_get_closest_format(device, desc.Format, format_support);
let descriptor = heap.alloc_slot()?;
// create handles on GPU
let mut resource: Option<ID3D12Resource> = None;
unsafe {
device.CreateCommittedResource(
&D3D12_HEAP_PROPERTIES {
Type: D3D12_HEAP_TYPE_DEFAULT,
CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
CreationNodeMask: 1,
VisibleNodeMask: 1,
},
D3D12_HEAP_FLAG_NONE,
&desc,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
None,
&mut resource,
)?;
}
assume_d3d12_init!(resource, "CreateCommittedResource");
unsafe {
let srv_desc = D3D12_SHADER_RESOURCE_VIEW_DESC {
Format: desc.Format,
ViewDimension: D3D12_SRV_DIMENSION_TEXTURE2D,
Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
Texture2D: D3D12_TEX2D_SRV {
2023-02-01 17:25:39 +11:00
MipLevels: u32::MAX,
2023-01-25 15:15:43 +11:00
..Default::default()
},
},
};
2023-02-06 08:17:23 +11:00
device.CreateShaderResourceView(
&resource,
Some(&srv_desc),
*descriptor.deref().as_ref(),
);
2023-01-25 15:15:43 +11:00
}
let mut buffer_desc = D3D12_RESOURCE_DESC {
Dimension: D3D12_RESOURCE_DIMENSION_BUFFER,
..Default::default()
};
let mut layout = D3D12_PLACED_SUBRESOURCE_FOOTPRINT::default();
let mut total = 0;
// texture upload
unsafe {
device.GetCopyableFootprints(
&desc,
0,
1,
0,
Some(&mut layout),
2023-01-27 09:57:54 +11:00
None,
None,
2023-01-25 15:15:43 +11:00
Some(&mut total),
);
buffer_desc.Width = total;
buffer_desc.Height = 1;
buffer_desc.DepthOrArraySize = 1;
buffer_desc.MipLevels = 1;
buffer_desc.SampleDesc.Count = 1;
buffer_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
}
let mut upload: Option<ID3D12Resource> = None;
unsafe {
device.CreateCommittedResource(
&D3D12_HEAP_PROPERTIES {
Type: D3D12_HEAP_TYPE_UPLOAD,
CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
CreationNodeMask: 1,
VisibleNodeMask: 1,
},
D3D12_HEAP_FLAG_NONE,
&buffer_desc,
D3D12_RESOURCE_STATE_GENERIC_READ,
None,
&mut upload,
)?;
}
assume_d3d12_init!(upload, "CreateCommittedResource");
2023-02-10 13:03:55 +11:00
let subresource = [D3D12_SUBRESOURCE_DATA {
pData: source.bytes.as_ptr().cast(),
RowPitch: 4 * source.size.width as isize,
SlicePitch: (4 * source.size.width * source.size.height) as isize,
}];
d3d12_resource_transition(
cmd,
&resource,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_COPY_DEST,
);
2023-01-25 15:15:43 +11:00
2023-02-10 13:03:55 +11:00
d3d12_update_subresources(cmd, &resource, &upload, 0, 0, 1, &subresource)?;
2023-01-25 15:15:43 +11:00
2023-02-10 13:03:55 +11:00
d3d12_resource_transition(
cmd,
&resource,
D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
);
2023-01-27 09:57:54 +11:00
2023-02-01 11:23:57 +11:00
let view = InputTexture::new(
2023-02-06 10:03:38 +11:00
resource.clone(),
2023-01-25 15:15:43 +11:00
descriptor,
2023-02-01 11:23:57 +11:00
source.size,
ImageFormat::R8G8B8A8Unorm,
filter,
2023-02-06 17:05:19 +11:00
wrap_mode,
2023-02-01 11:23:57 +11:00
);
2023-02-06 08:17:23 +11:00
Ok((
LutTexture {
resource,
view,
miplevels: if mipmap { Some(miplevels) } else { None },
},
upload,
))
2023-01-24 18:02:27 +11:00
}
2023-01-28 17:38:55 +11:00
pub fn generate_mipmaps(&self, gen_mips: &mut MipmapGenContext) -> error::Result<()> {
if let Some(miplevels) = self.miplevels {
2023-02-06 08:17:23 +11:00
gen_mips.generate_mipmaps(
&self.resource,
miplevels,
self.view.size,
ImageFormat::R8G8B8A8Unorm.into(),
)?
2023-01-28 17:38:55 +11:00
}
Ok(())
}
2023-02-01 11:23:57 +11:00
}
2023-02-01 09:50:47 +11:00
2023-02-01 11:23:57 +11:00
impl AsRef<InputTexture> for LutTexture {
fn as_ref(&self) -> &InputTexture {
&self.view
2023-02-01 09:50:47 +11:00
}
2023-02-06 08:17:23 +11:00
}