0adf3505ec
This doesn't cause an API break in the C API but we don't actually make an attempt to verify that it's safe to access any of the device contexts.
174 lines
5.6 KiB
Rust
174 lines
5.6 KiB
Rust
use librashader_common::{FilterMode, Size, WrapMode};
|
|
use librashader_runtime::image::Image;
|
|
use librashader_runtime::scaling::MipmapSize;
|
|
use windows::Win32::Graphics::Direct3D::D3D_SRV_DIMENSION_TEXTURE2D;
|
|
use windows::Win32::Graphics::Direct3D11::{
|
|
ID3D11Device, ID3D11DeviceContext, ID3D11ShaderResourceView, ID3D11Texture2D, D3D11_BIND_FLAG,
|
|
D3D11_BIND_RENDER_TARGET, D3D11_BIND_SHADER_RESOURCE, D3D11_BOX, D3D11_CPU_ACCESS_FLAG,
|
|
D3D11_CPU_ACCESS_WRITE, D3D11_RESOURCE_MISC_FLAG, D3D11_RESOURCE_MISC_GENERATE_MIPS,
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC, D3D11_SHADER_RESOURCE_VIEW_DESC_0, D3D11_SUBRESOURCE_DATA,
|
|
D3D11_TEX2D_SRV, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DYNAMIC, D3D11_USAGE_STAGING,
|
|
};
|
|
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
|
|
|
|
/// An image view for use as a shader resource.
|
|
///
|
|
/// Contains an `ID3D11ShaderResourceView`, and a size.
|
|
#[derive(Debug, Clone)]
|
|
pub struct D3D11InputView {
|
|
/// A handle to the shader resource view.
|
|
pub handle: ID3D11ShaderResourceView,
|
|
/// The size of the image.
|
|
pub size: Size<u32>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct InputTexture {
|
|
pub view: D3D11InputView,
|
|
pub filter: FilterMode,
|
|
pub wrap_mode: WrapMode,
|
|
}
|
|
|
|
impl AsRef<InputTexture> for InputTexture {
|
|
fn as_ref(&self) -> &InputTexture {
|
|
self
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub(crate) struct ExampleTexture {
|
|
// The handle to the Texture2D must be kept alive.
|
|
#[allow(dead_code)]
|
|
pub handle: ID3D11Texture2D,
|
|
#[allow(dead_code)]
|
|
pub desc: D3D11_TEXTURE2D_DESC,
|
|
pub image: InputTexture,
|
|
}
|
|
|
|
impl AsRef<InputTexture> for ExampleTexture {
|
|
fn as_ref(&self) -> &InputTexture {
|
|
&self.image
|
|
}
|
|
}
|
|
|
|
impl ExampleTexture {
|
|
pub fn new(
|
|
device: &ID3D11Device,
|
|
context: &ID3D11DeviceContext,
|
|
source: &Image,
|
|
desc: D3D11_TEXTURE2D_DESC,
|
|
filter: FilterMode,
|
|
wrap_mode: WrapMode,
|
|
) -> Result<ExampleTexture, windows::core::Error> {
|
|
let mut desc = D3D11_TEXTURE2D_DESC {
|
|
Width: source.size.width,
|
|
Height: source.size.height,
|
|
// todo: set this to 0
|
|
MipLevels: if (desc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS).0 != 0 {
|
|
0
|
|
} else {
|
|
1
|
|
},
|
|
ArraySize: 1,
|
|
SampleDesc: DXGI_SAMPLE_DESC {
|
|
Count: 1,
|
|
Quality: 0,
|
|
},
|
|
CPUAccessFlags: if desc.Usage == D3D11_USAGE_DYNAMIC {
|
|
D3D11_CPU_ACCESS_WRITE
|
|
} else {
|
|
D3D11_CPU_ACCESS_FLAG(0)
|
|
},
|
|
..desc
|
|
};
|
|
desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
|
|
|
|
// determine number of mipmaps required
|
|
if (desc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS).0 != 0 {
|
|
desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
|
|
desc.MipLevels = source.size.calculate_miplevels();
|
|
}
|
|
|
|
// Don't need to determine format support because LUTs are always DXGI_FORMAT_R8G8B8A8_UNORM
|
|
// since we load them with the Image module.
|
|
|
|
unsafe {
|
|
let mut handle = None;
|
|
device.CreateTexture2D(&desc, None, Some(&mut handle))?;
|
|
let handle = handle.unwrap();
|
|
|
|
// need a staging texture to defer mipmap generation
|
|
let mut staging = None;
|
|
device.CreateTexture2D(
|
|
&D3D11_TEXTURE2D_DESC {
|
|
MipLevels: 1,
|
|
BindFlags: D3D11_BIND_FLAG(0),
|
|
MiscFlags: D3D11_RESOURCE_MISC_FLAG(0),
|
|
Usage: D3D11_USAGE_STAGING,
|
|
CPUAccessFlags: D3D11_CPU_ACCESS_WRITE,
|
|
..desc
|
|
},
|
|
Some(&D3D11_SUBRESOURCE_DATA {
|
|
pSysMem: source.bytes.as_ptr().cast(),
|
|
SysMemPitch: source.pitch as u32,
|
|
SysMemSlicePitch: 0,
|
|
}),
|
|
Some(&mut staging),
|
|
)?;
|
|
let staging = staging.unwrap();
|
|
|
|
context.CopySubresourceRegion(
|
|
&handle,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
&staging,
|
|
0,
|
|
Some(&D3D11_BOX {
|
|
left: 0,
|
|
top: 0,
|
|
front: 0,
|
|
right: source.size.width,
|
|
bottom: source.size.height,
|
|
back: 1,
|
|
}),
|
|
);
|
|
|
|
let mut srv = None;
|
|
device.CreateShaderResourceView(
|
|
&handle,
|
|
Some(&D3D11_SHADER_RESOURCE_VIEW_DESC {
|
|
Format: desc.Format,
|
|
ViewDimension: D3D_SRV_DIMENSION_TEXTURE2D,
|
|
Anonymous: D3D11_SHADER_RESOURCE_VIEW_DESC_0 {
|
|
Texture2D: D3D11_TEX2D_SRV {
|
|
MostDetailedMip: 0,
|
|
MipLevels: u32::MAX,
|
|
},
|
|
},
|
|
}),
|
|
Some(&mut srv),
|
|
)?;
|
|
let srv = srv.unwrap();
|
|
|
|
if (desc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS).0 != 0 {
|
|
context.GenerateMips(&srv)
|
|
}
|
|
|
|
Ok(ExampleTexture {
|
|
handle,
|
|
desc,
|
|
image: InputTexture {
|
|
view: D3D11InputView {
|
|
handle: srv,
|
|
size: source.size,
|
|
},
|
|
filter,
|
|
wrap_mode,
|
|
},
|
|
})
|
|
}
|
|
}
|
|
}
|