d3d12: load lut texture data
This commit is contained in:
parent
9a3ce029d7
commit
56538dbfbf
|
@ -74,13 +74,14 @@ impl FilterChainD3D12 {
|
|||
|
||||
let fence_event = unsafe { CreateEventA(None, false, false, None)? };
|
||||
let fence: ID3D12Fence = device.CreateFence(0, D3D12_FENCE_FLAG_NONE)?;
|
||||
let mut residuals = Vec::new();
|
||||
|
||||
let mut luts = FxHashMap::default();
|
||||
|
||||
for (index, texture) in textures.iter().enumerate() {
|
||||
let image = Image::load(&texture.path, UVDirection::TopLeft)?;
|
||||
|
||||
let texture = LutTexture::new(
|
||||
let (texture, staging) = LutTexture::new(
|
||||
device,
|
||||
heap,
|
||||
&cmd,
|
||||
|
@ -91,6 +92,7 @@ impl FilterChainD3D12 {
|
|||
false,
|
||||
)?;
|
||||
luts.insert(index, texture);
|
||||
residuals.push(staging);
|
||||
}
|
||||
|
||||
cmd.Close()?;
|
||||
|
@ -106,6 +108,7 @@ impl FilterChainD3D12 {
|
|||
|
||||
unsafe { WaitForSingleObject(fence_event, INFINITE) };
|
||||
}
|
||||
|
||||
Ok(luts)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use std::mem::ManuallyDrop;
|
||||
use crate::error;
|
||||
use crate::error::assume_d3d12_init;
|
||||
use crate::heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot, LutTextureHeap};
|
||||
use crate::util::d3d12_get_closest_format;
|
||||
use crate::util::{d3d12_get_closest_format, d3d12_resource_transition, d3d12_update_subresources};
|
||||
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
||||
use librashader_runtime::image::Image;
|
||||
use windows::Win32::Graphics::Direct3D12::{ID3D12CommandList, 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_RANGE};
|
||||
use windows::Win32::Graphics::Direct3D12::{ID3D12CommandList, 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_RANGE, D3D12_SUBRESOURCE_DATA, D3D12_RESOURCE_STATE_COPY_DEST};
|
||||
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
|
||||
|
||||
pub struct LutTexture {
|
||||
|
@ -24,7 +25,7 @@ impl LutTexture {
|
|||
filter: FilterMode,
|
||||
wrap_mode: WrapMode,
|
||||
mipmap: bool,
|
||||
) -> error::Result<LutTexture> {
|
||||
) -> error::Result<(LutTexture, ID3D12Resource)> {
|
||||
// todo: d3d12:800
|
||||
let mut desc = D3D12_RESOURCE_DESC {
|
||||
Dimension: D3D12_RESOURCE_DIMENSION_TEXTURE2D,
|
||||
|
@ -93,8 +94,8 @@ impl LutTexture {
|
|||
};
|
||||
|
||||
let mut layout = D3D12_PLACED_SUBRESOURCE_FOOTPRINT::default();
|
||||
let mut numrows = 0;
|
||||
let mut rowsize = 0;
|
||||
// let mut numrows = 0;
|
||||
// let mut rowsize = 0;
|
||||
let mut total = 0;
|
||||
// texture upload
|
||||
unsafe {
|
||||
|
@ -104,8 +105,7 @@ impl LutTexture {
|
|||
1,
|
||||
0,
|
||||
Some(&mut layout),
|
||||
Some(&mut numrows),
|
||||
Some(&mut rowsize),
|
||||
None, None,
|
||||
Some(&mut total),
|
||||
);
|
||||
|
||||
|
@ -137,27 +137,28 @@ impl LutTexture {
|
|||
assume_d3d12_init!(upload, "CreateCommittedResource");
|
||||
|
||||
unsafe {
|
||||
let mut range = D3D12_RANGE {
|
||||
Begin: 0,
|
||||
End: 0
|
||||
};
|
||||
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,
|
||||
}];
|
||||
|
||||
let mut buf = std::ptr::null_mut();
|
||||
d3d12_resource_transition(cmd, &resource, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_DEST);
|
||||
|
||||
upload.Map(0, Some(&range), Some(&mut buf))?;
|
||||
|
||||
upload.Unmap(0, None);
|
||||
d3d12_update_subresources(cmd, &resource,
|
||||
&upload, 0, 0, 1, &subresource)?;
|
||||
|
||||
d3d12_resource_transition(cmd, &resource, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)
|
||||
}
|
||||
// todo: upload image data to textur
|
||||
|
||||
Ok(LutTexture {
|
||||
Ok((LutTexture {
|
||||
resource,
|
||||
descriptor,
|
||||
size: source.size,
|
||||
filter,
|
||||
wrap_mode,
|
||||
})
|
||||
}, upload))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use std::mem::ManuallyDrop;
|
||||
use std::u64;
|
||||
use crate::error;
|
||||
use windows::core::PCSTR;
|
||||
use windows::Win32::Graphics::Direct3D::Fxc::{
|
||||
D3DCompile, D3DCOMPILE_DEBUG, D3DCOMPILE_SKIP_OPTIMIZATION,
|
||||
};
|
||||
use windows::Win32::Graphics::Direct3D::ID3DBlob;
|
||||
use windows::Win32::Graphics::Direct3D12::{
|
||||
ID3D12Device, D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FEATURE_FORMAT_SUPPORT,
|
||||
};
|
||||
use windows::Win32::Graphics::Direct3D12::{ID3D12Device, D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FEATURE_FORMAT_SUPPORT, ID3D12CommandList, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_RESOURCE_DESC, D3D12_RESOURCE_BARRIER, D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, D3D12_RESOURCE_BARRIER_FLAG_NONE, D3D12_RESOURCE_DESC1, D3D12_RESOURCE_BARRIER_0, D3D12_RESOURCE_TRANSITION_BARRIER, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_STATES, D3D12_PLACED_SUBRESOURCE_FOOTPRINT, D3D12_MEMCPY_DEST, D3D12_SUBRESOURCE_DATA, D3D12_RESOURCE_DIMENSION_BUFFER, D3D12_TEXTURE_COPY_LOCATION, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, D3D12_TEXTURE_COPY_LOCATION_0, D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT};
|
||||
use windows::Win32::Graphics::Dxgi::Common::*;
|
||||
use crate::error::assume_d3d12_init;
|
||||
|
||||
/// wtf retroarch?
|
||||
const DXGI_FORMAT_EX_A4R4G4B4_UNORM: DXGI_FORMAT = DXGI_FORMAT(1000);
|
||||
|
@ -140,3 +141,187 @@ pub fn d3d_compile_shader(source: &[u8], entry: &[u8], version: &[u8]) -> error:
|
|||
Ok(blob.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn d3d12_resource_transition(cmd: &ID3D12GraphicsCommandList,
|
||||
resource: &ID3D12Resource,
|
||||
before: D3D12_RESOURCE_STATES,
|
||||
after: D3D12_RESOURCE_STATES
|
||||
) {
|
||||
let barrier = [D3D12_RESOURCE_BARRIER {
|
||||
Type: D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
|
||||
Flags: D3D12_RESOURCE_BARRIER_FLAG_NONE,
|
||||
Anonymous: D3D12_RESOURCE_BARRIER_0 {
|
||||
Transition: ManuallyDrop::new(D3D12_RESOURCE_TRANSITION_BARRIER {
|
||||
pResource: windows::core::ManuallyDrop::new(resource),
|
||||
Subresource: D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
|
||||
StateBefore: before,
|
||||
StateAfter: after,
|
||||
})
|
||||
},
|
||||
}];
|
||||
|
||||
unsafe {
|
||||
cmd.ResourceBarrier(&barrier)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn d3d12_update_subresources(cmd: &ID3D12GraphicsCommandList,
|
||||
destination_resource: &ID3D12Resource,
|
||||
intermediate_resource: &ID3D12Resource,
|
||||
intermediate_offset: u64,
|
||||
first_subresouce: u32,
|
||||
num_subresources: u32,
|
||||
source: &[D3D12_SUBRESOURCE_DATA]
|
||||
) -> error::Result<u64> {
|
||||
|
||||
// let allocation_size = std::mem::size_of::<D3D12_PLACED_SUBRESOURCE_FOOTPRINT>()
|
||||
// + std::mem::size_of::<u32>()
|
||||
// + std::mem::size_of::<u64>() * num_subresources;
|
||||
|
||||
unsafe {
|
||||
let destination_desc = destination_resource.GetDesc();
|
||||
let mut device: Option<ID3D12Device> = None;
|
||||
destination_resource.GetDevice(&mut device)?;
|
||||
assume_d3d12_init!(device, "GetDevice");
|
||||
|
||||
|
||||
let mut layouts = vec![D3D12_PLACED_SUBRESOURCE_FOOTPRINT::default(); num_subresources as usize];
|
||||
let mut num_rows = vec![0; num_subresources as usize];
|
||||
let mut row_sizes_in_bytes = vec![0; num_subresources as usize];
|
||||
let mut required_size = 0;
|
||||
// texture upload
|
||||
unsafe {
|
||||
device.GetCopyableFootprints(
|
||||
&destination_desc,
|
||||
first_subresouce,
|
||||
num_subresources,
|
||||
intermediate_offset,
|
||||
Some(layouts.as_mut_ptr()),
|
||||
Some(num_rows.as_mut_ptr()),
|
||||
Some(row_sizes_in_bytes.as_mut_ptr()),
|
||||
Some(&mut required_size),
|
||||
);
|
||||
}
|
||||
|
||||
update_subresources(
|
||||
cmd,
|
||||
destination_resource,
|
||||
intermediate_resource,
|
||||
first_subresouce,
|
||||
num_subresources,
|
||||
required_size,
|
||||
&layouts,
|
||||
&num_rows,
|
||||
&row_sizes_in_bytes,
|
||||
source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn update_subresources(
|
||||
cmd: &ID3D12GraphicsCommandList,
|
||||
destination_resource: &ID3D12Resource,
|
||||
intermediate_resource: &ID3D12Resource,
|
||||
first_subresouce: u32,
|
||||
num_subresources: u32,
|
||||
required_size: u64,
|
||||
layouts: &[D3D12_PLACED_SUBRESOURCE_FOOTPRINT],
|
||||
num_rows: &[u32],
|
||||
row_sizes_in_bytes: &[u64],
|
||||
source_data: &[D3D12_SUBRESOURCE_DATA],
|
||||
) -> error::Result<u64> {
|
||||
// ToDo: implement validation as in the original function
|
||||
|
||||
|
||||
unsafe {
|
||||
let mut data = std::ptr::null_mut();
|
||||
intermediate_resource.Map(0, None, Some(&mut data))?;
|
||||
|
||||
for i in 0..num_subresources as usize {
|
||||
let dest_data = D3D12_MEMCPY_DEST {
|
||||
pData: data.offset(layouts[i].Offset as isize)
|
||||
as *mut std::ffi::c_void,
|
||||
RowPitch: layouts[i].Footprint.RowPitch as usize,
|
||||
SlicePitch: ((layouts[i].Footprint.RowPitch)
|
||||
* num_rows[i]) as usize,
|
||||
};
|
||||
|
||||
memcpy_subresource(
|
||||
&dest_data,
|
||||
&source_data[i],
|
||||
row_sizes_in_bytes[i],
|
||||
num_rows[i],
|
||||
layouts[i].Footprint.Depth,
|
||||
);
|
||||
}
|
||||
intermediate_resource.Unmap(0, None);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let destination_desc = destination_resource.GetDesc();
|
||||
if destination_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER {
|
||||
cmd.CopyBufferRegion(
|
||||
destination_resource,
|
||||
0,
|
||||
intermediate_resource,
|
||||
layouts[0].Offset,
|
||||
layouts[0].Footprint.Width as u64,
|
||||
);
|
||||
} else {
|
||||
for i in 0..num_subresources as usize {
|
||||
|
||||
let dest_location = D3D12_TEXTURE_COPY_LOCATION {
|
||||
pResource: windows::core::ManuallyDrop::new(destination_resource),
|
||||
Type: D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
||||
Anonymous: D3D12_TEXTURE_COPY_LOCATION_0 {
|
||||
SubresourceIndex: i as u32 + first_subresouce
|
||||
},
|
||||
};
|
||||
|
||||
let source_location = D3D12_TEXTURE_COPY_LOCATION {
|
||||
pResource: windows::core::ManuallyDrop::new(intermediate_resource),
|
||||
Type: D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
|
||||
Anonymous: D3D12_TEXTURE_COPY_LOCATION_0 {
|
||||
PlacedFootprint: layouts[i]
|
||||
},
|
||||
};
|
||||
|
||||
cmd.CopyTextureRegion(
|
||||
&dest_location,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&source_location,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(required_size)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// this function should not leak to the public API, so
|
||||
// there is no point in using struct wrappers
|
||||
unsafe fn memcpy_subresource(
|
||||
dest: &D3D12_MEMCPY_DEST,
|
||||
src: &D3D12_SUBRESOURCE_DATA,
|
||||
row_sizes_in_bytes: u64,
|
||||
num_rows: u32,
|
||||
num_slices: u32,
|
||||
) {
|
||||
for z in 0..num_slices as usize {
|
||||
let dest_slice =
|
||||
dest.pData.offset((dest.SlicePitch * z) as isize);
|
||||
let src_slice = src.pData.offset((src.SlicePitch * z as isize) as isize);
|
||||
|
||||
for y in 0..num_rows as usize {
|
||||
std::ptr::copy_nonoverlapping(
|
||||
src_slice.offset((src.RowPitch * y as isize) as isize),
|
||||
dest_slice.offset((dest.RowPitch * y) as isize),
|
||||
row_sizes_in_bytes as usize,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue