librashader/librashader-runtime-d3d11/src/texture.rs

213 lines
6.6 KiB
Rust
Raw Normal View History

2022-11-27 18:21:36 +11:00
use librashader_common::{FilterMode, Size, WrapMode};
2022-12-22 13:39:31 +11:00
use librashader_runtime::image::Image;
2023-01-30 13:26:34 +11:00
use librashader_runtime::scaling::MipmapSize;
2022-11-26 18:38:15 +11:00
use windows::Win32::Graphics::Direct3D::D3D_SRV_DIMENSION_TEXTURE2D;
2022-12-01 11:05:12 +11:00
use windows::Win32::Graphics::Direct3D11::{
2023-01-15 19:06:09 +11:00
ID3D11Device, ID3D11DeviceContext, ID3D11RenderTargetView, 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,
2022-12-01 11:05:12 +11:00
};
2022-11-26 18:38:15 +11:00
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
2022-11-30 17:38:05 +11:00
2023-01-17 10:45:02 +11:00
use crate::error::{assume_d3d11_init, Result};
use crate::framebuffer::OwnedFramebuffer;
2022-11-26 18:38:15 +11:00
2023-01-13 19:19:58 +11:00
/// An image view for use as a shader resource.
///
/// Contains an `ID3D11ShaderResourceView`, and a size.
2022-11-26 18:38:15 +11:00
#[derive(Debug, Clone)]
2023-01-13 18:54:16 +11:00
pub struct D3D11InputView {
2023-01-15 07:10:40 +11:00
/// A handle to the shader resource view.
2022-11-27 18:21:36 +11:00
pub handle: ID3D11ShaderResourceView,
2023-01-15 07:10:40 +11:00
/// The size of the image.
2022-12-01 09:59:55 +11:00
pub size: Size<u32>,
2022-11-29 13:00:54 +11:00
}
2023-01-13 18:54:16 +11:00
2023-01-13 19:19:58 +11:00
/// An image view for use as a render target.
///
/// Contains an `ID3D11RenderTargetView`, and a size.
2023-01-13 18:54:16 +11:00
#[derive(Debug, Clone)]
pub struct D3D11OutputView {
2023-01-15 07:10:40 +11:00
/// A handle to the render target view.
2023-01-13 18:54:16 +11:00
pub handle: ID3D11RenderTargetView,
2023-01-15 07:10:40 +11:00
/// The size of the image.
2023-01-13 18:54:16 +11:00
pub size: Size<u32>,
}
2022-11-29 13:00:54 +11:00
#[derive(Debug, Clone)]
2023-01-15 19:01:23 +11:00
pub struct InputTexture {
2023-01-13 18:54:16 +11:00
pub view: D3D11InputView,
2022-11-27 18:21:36 +11:00
pub filter: FilterMode,
pub wrap_mode: WrapMode,
2022-11-26 18:38:15 +11:00
}
2023-01-13 18:54:16 +11:00
impl InputTexture {
2023-01-15 19:01:23 +11:00
pub(crate) fn from_framebuffer(
2022-12-22 13:39:31 +11:00
fbo: &OwnedFramebuffer,
wrap_mode: WrapMode,
filter: FilterMode,
) -> Result<Self> {
2023-01-13 18:54:16 +11:00
Ok(InputTexture {
view: D3D11InputView {
handle: fbo.create_shader_resource_view()?,
size: fbo.size,
},
filter,
2022-12-22 13:39:31 +11:00
wrap_mode,
})
}
}
2023-01-15 19:01:23 +11:00
impl AsRef<InputTexture> for InputTexture {
fn as_ref(&self) -> &InputTexture {
self
}
}
2022-11-26 18:38:15 +11:00
#[derive(Debug, Clone)]
pub(crate) struct LutTexture {
2022-12-02 11:16:13 +11:00
// The handle to the Texture2D must be kept alive.
#[allow(dead_code)]
2022-11-26 18:38:15 +11:00
pub handle: ID3D11Texture2D,
2022-12-02 11:16:13 +11:00
#[allow(dead_code)]
2022-11-26 18:38:15 +11:00
pub desc: D3D11_TEXTURE2D_DESC,
2023-01-13 18:54:16 +11:00
pub image: InputTexture,
2022-11-26 18:38:15 +11:00
}
2023-01-15 19:01:23 +11:00
impl AsRef<InputTexture> for LutTexture {
fn as_ref(&self) -> &InputTexture {
&self.image
}
}
2022-12-01 09:59:55 +11:00
impl LutTexture {
2022-11-30 17:38:05 +11:00
pub fn new(
device: &ID3D11Device,
2022-12-01 09:59:55 +11:00
context: &ID3D11DeviceContext,
2022-11-30 17:38:05 +11:00
source: &Image,
desc: D3D11_TEXTURE2D_DESC,
filter: FilterMode,
wrap_mode: WrapMode,
2022-12-01 09:59:55 +11:00
) -> Result<LutTexture> {
2022-11-26 18:38:15 +11:00
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();
2022-11-26 18:38:15 +11:00
}
2022-12-01 11:05:12 +11:00
// Don't need to determine format support because LUTs are always DXGI_FORMAT_R8G8B8A8_UNORM
// since we load them with the Image module.
2022-11-26 18:38:15 +11:00
unsafe {
2023-01-17 10:45:02 +11:00
let mut handle = None;
device.CreateTexture2D(&desc, None, Some(&mut handle))?;
assume_d3d11_init!(handle, "CreateTexture2D");
2022-11-26 18:38:15 +11:00
// need a staging texture to defer mipmap generation
2023-01-17 10:45:02 +11:00
let mut staging = None;
device.CreateTexture2D(
2022-11-30 17:38:05 +11:00
&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,
}),
2023-01-17 10:45:02 +11:00
Some(&mut staging),
2022-11-30 17:38:05 +11:00
)?;
2023-01-17 10:45:02 +11:00
assume_d3d11_init!(staging, "CreateTexture2D");
2022-11-26 18:38:15 +11:00
2022-11-27 07:55:14 +11:00
// todo: do format conversion (leverage image crate..?
// is this necessary with CopySubresourceRegion)...
2022-11-26 18:38:15 +11:00
2022-11-30 17:38:05 +11:00
context.CopySubresourceRegion(
&handle,
0,
0,
0,
0,
&staging,
0,
Some(&D3D11_BOX {
2022-11-26 18:38:15 +11:00
left: 0,
top: 0,
front: 0,
right: source.size.width,
bottom: source.size.height,
back: 1,
2022-11-30 17:38:05 +11:00
}),
);
2022-11-26 18:38:15 +11:00
2023-01-17 10:45:02 +11:00
let mut srv = None;
device.CreateShaderResourceView(
2023-01-03 17:06:42 +11:00
&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,
},
},
}),
2023-01-17 10:45:02 +11:00
Some(&mut srv),
2023-01-03 17:06:42 +11:00
)?;
2023-01-17 10:45:02 +11:00
assume_d3d11_init!(srv, "CreateShaderResourceView");
2023-01-03 17:06:42 +11:00
2022-11-26 18:38:15 +11:00
if (desc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS).0 != 0 {
2022-11-30 17:38:05 +11:00
context.GenerateMips(&srv)
2022-11-26 18:38:15 +11:00
}
// let mut subresource = context.Map(staging, 0, D3D11_MAP_WRITE, 0)?;
// staging.Upd
2022-12-01 09:59:55 +11:00
Ok(LutTexture {
2022-11-26 18:38:15 +11:00
handle,
// staging,
desc,
2023-01-13 18:54:16 +11:00
image: InputTexture {
view: D3D11InputView {
2022-11-29 13:00:54 +11:00
handle: srv,
size: source.size,
},
2022-11-27 18:21:36 +11:00
filter,
2022-11-30 17:38:05 +11:00
wrap_mode,
},
2022-11-26 18:38:15 +11:00
})
}
}
}