windows: Check required GPU/driver feature StructuredBuffer (#37776)

Check whether the GPU/driver supports the StructuredBuffer feature
required by our shaders. If it doesn’t, log an error and skip that
GPU/driver, so Windows can fall back to the software renderer.

Release Notes:

- N/A
This commit is contained in:
张小白
2025-09-08 12:22:57 +00:00
committed by GitHub
parent 80a4746a46
commit 17499453f6
@@ -8,8 +8,9 @@ use windows::Win32::{
D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1,
},
Direct3D11::{
D3D11_CREATE_DEVICE_BGRA_SUPPORT, D3D11_CREATE_DEVICE_DEBUG, D3D11_SDK_VERSION,
D3D11CreateDevice, ID3D11Device, ID3D11DeviceContext,
D3D11_CREATE_DEVICE_BGRA_SUPPORT, D3D11_CREATE_DEVICE_DEBUG,
D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS,
D3D11_SDK_VERSION, D3D11CreateDevice, ID3D11Device, ID3D11DeviceContext,
},
Dxgi::{
CreateDXGIFactory2, DXGI_CREATE_FACTORY_DEBUG, DXGI_CREATE_FACTORY_FLAGS,
@@ -54,12 +55,10 @@ impl DirectXDevices {
let adapter =
get_adapter(&dxgi_factory, debug_layer_available).context("Getting DXGI adapter")?;
let (device, device_context) = {
let mut device: Option<ID3D11Device> = None;
let mut context: Option<ID3D11DeviceContext> = None;
let mut feature_level = D3D_FEATURE_LEVEL::default();
get_device(
let device = get_device(
&adapter,
Some(&mut device),
Some(&mut context),
Some(&mut feature_level),
debug_layer_available,
@@ -77,7 +76,7 @@ impl DirectXDevices {
}
_ => unreachable!(),
}
(device.unwrap(), context.unwrap())
(device, context.unwrap())
};
Ok(Self {
@@ -134,7 +133,7 @@ fn get_adapter(dxgi_factory: &IDXGIFactory6, debug_layer_available: bool) -> Res
}
// Check to see whether the adapter supports Direct3D 11, but don't
// create the actual device yet.
if get_device(&adapter, None, None, None, debug_layer_available)
if get_device(&adapter, None, None, debug_layer_available)
.log_err()
.is_some()
{
@@ -148,11 +147,11 @@ fn get_adapter(dxgi_factory: &IDXGIFactory6, debug_layer_available: bool) -> Res
#[inline]
fn get_device(
adapter: &IDXGIAdapter1,
device: Option<*mut Option<ID3D11Device>>,
context: Option<*mut Option<ID3D11DeviceContext>>,
feature_level: Option<*mut D3D_FEATURE_LEVEL>,
debug_layer_available: bool,
) -> Result<()> {
) -> Result<ID3D11Device> {
let mut device: Option<ID3D11Device> = None;
let device_flags = if debug_layer_available {
D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_DEBUG
} else {
@@ -171,10 +170,30 @@ fn get_device(
D3D_FEATURE_LEVEL_10_1,
]),
D3D11_SDK_VERSION,
device,
Some(&mut device),
feature_level,
context,
)?;
}
Ok(())
let device = device.unwrap();
let mut data = D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS::default();
unsafe {
device
.CheckFeatureSupport(
D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS,
&mut data as *mut _ as _,
std::mem::size_of::<D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS>() as u32,
)
.context("Checking GPU device feature support")?;
}
if data
.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x
.as_bool()
{
Ok(device)
} else {
Err(anyhow::anyhow!(
"Required feature StructuredBuffer is not supported by GPU/driver"
))
}
}