2023-02-02 10:09:34 +11:00
|
|
|
use std::ops::Deref;
|
2023-01-25 15:15:43 +11:00
|
|
|
use crate::error;
|
|
|
|
use crate::error::assume_d3d12_init;
|
2023-02-02 10:09:34 +11:00
|
|
|
use crate::descriptor_heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot, CpuStagingHeap};
|
2023-01-25 17:32:10 +11:00
|
|
|
use crate::util::{d3d12_get_closest_format, d3d12_resource_transition, d3d12_update_subresources};
|
2023-01-25 15:15:43 +11:00
|
|
|
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
2023-01-24 18:02:27 +11:00
|
|
|
use librashader_runtime::image::Image;
|
2023-02-01 09:50:47 +11:00
|
|
|
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_SHADER_SAMPLE, 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_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_TEX2D_SRV, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, D3D12_SUBRESOURCE_DATA, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_FORMAT_SUPPORT1_MIP, D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE};
|
2023-01-25 15:15:43 +11:00
|
|
|
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
|
2023-01-27 09:57:54 +11:00
|
|
|
use librashader_runtime::scaling::MipmapSize;
|
2023-02-01 09:50:47 +11:00
|
|
|
use crate::mipmap::{MipmapGenContext};
|
|
|
|
use crate::texture::InputTexture;
|
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-24 18:02:27 +11:00
|
|
|
// todo: d3d12:800
|
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-02 10:09:34 +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");
|
|
|
|
|
|
|
|
unsafe {
|
2023-01-25 17:32:10 +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,
|
|
|
|
}];
|
2023-01-25 15:15:43 +11:00
|
|
|
|
2023-01-25 17:32:10 +11:00
|
|
|
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-01-25 17:32:10 +11:00
|
|
|
d3d12_update_subresources(cmd, &resource,
|
|
|
|
&upload, 0, 0, 1, &subresource)?;
|
2023-01-25 15:15:43 +11:00
|
|
|
|
2023-01-25 17:32:10 +11:00
|
|
|
d3d12_resource_transition(cmd, &resource, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)
|
2023-01-25 15:15:43 +11:00
|
|
|
}
|
2023-01-27 09:57:54 +11:00
|
|
|
|
2023-02-01 11:23:57 +11:00
|
|
|
let view = InputTexture::new(
|
2023-01-25 15:15:43 +11:00
|
|
|
descriptor,
|
2023-02-01 11:23:57 +11:00
|
|
|
source.size,
|
|
|
|
ImageFormat::R8G8B8A8Unorm,
|
2023-01-25 15:15:43 +11:00
|
|
|
wrap_mode,
|
2023-02-01 11:23:57 +11:00
|
|
|
filter,
|
|
|
|
);
|
|
|
|
Ok((LutTexture {
|
|
|
|
resource,
|
|
|
|
view,
|
2023-01-28 17:38:55 +11:00
|
|
|
miplevels: if mipmap { Some(miplevels) } else { None }
|
2023-01-25 17:32:10 +11:00
|
|
|
}, 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 {
|
|
|
|
gen_mips.generate_mipmaps(&self.resource,
|
2023-02-01 09:50:47 +11:00
|
|
|
miplevels,
|
2023-02-01 11:23:57 +11:00
|
|
|
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-01 11:23:57 +11:00
|
|
|
}
|