floooh / sokol

minimal cross-platform standalone C headers

Home Page:https://floooh.github.io/sokol-html5

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

D3D11: return a soft-error if shader model isn't compatible with GPU

AndreiRudenko opened this issue · comments

Hello, im building TIC-80 with sokol renderer and when launch i get error on this line line. Videocard is intel hd on p6100 processor.
dxzxc9HHquM

Ouch. This doesn't happen during compilation though (which is already a "soft error"), but where the D3D11 shader is created from a compiled blob. Only reason I can think of is that the video driver or GPU doesn't support the D3D shader model since the CPU/GPU might be too old.

Hmm... I think I should at least change the code to make this case a soft error, and the next step would be checking if we can optionally use an older HLSL shader model (maybe similar to the GLES3/GLES2 fallback).

Can you attach a dxdiag log here? This contains the D3D properties of you graphics card, and might give an idea what's the underlying problem ("Win+R" to open the "Run" dialog, then "dxdiag", and then there's a "Save Information" Button (the messages are all in German on my machine, so I don't know the exact name of the button on your system).

PS: as a temporary workaround, if you compile the shader from embedded source code (not using the sokol_shdc compiler), you can try some other shader model strings here:

sokol/sokol_gfx.h

Lines 5105 to 5106 in 487822d

vs_blob = _sg_d3d11_compile_shader(&desc->vs, "vs_5_0");
fs_blob = _sg_d3d11_compile_shader(&desc->fs, "ps_5_0");

If this works it probably makes sense to make this configurable from the outside, and add a few more HLSL shader models to sokol_shdc.

...I tried "vs_4_0" and "ps_4_0", and at least all the sokol samples still work. Since SM5 only added compute shader support and some minor features not relevant for sokol-gfx I guess switching back to shader model 4 as default would be a no-brainer. Going back even further might be a problem though, since SM3 is already D3D9 territory.

Can you check somehow whether shader model 4 works on your side?

With "vs_4_0" and "ps_4_0" works well. Awesome, thank you!

Ok, good to know thanks :) I think I'll do a bit more research and then will switch everything to shader model 4. I'll keep this ticket open as reminder.

I believe this is a good idea in general. It would be quite useful here since I have some customers with older hardware on which I would like to still use shaders which do not require SM 5.0.

Ok noted, I didn't do anything about this yet, but I think it's a good idea to add HLSL4 as an output option to sokol-shdc, and also have the sokol-gfx D3D11 backend accept HLSL4 shaders.

Interesting enough I have just encountered a customer with Intel i3-540 CPU with built-in iGPU with supposed support for DirectX 10.0 and 9.1 feature levels:

image

In this case I assume shader model 4.0 should work. However, that user is failing at this line with assertion:

https://github.com/floooh/sokol/blob/master/sokol_gfx.h#L7050

Looks like I misinterpreted the return value of ID3D11Device::CheckFormatSupport(), it says that the function might return E_FAIL "if the described format does not exist":

https://docs.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11device-checkformatsupport

I'll add some code to "deactivate" the pixel format instead of failing hard with an assert.

@iryont I've made two fixes in the D3D11 pixelformat check, but both are "speculative" since I can't reproduce the behaviour on my Windows machines:

  • the D3D11 function is no longer called with DXGI_FORMAT_UNKNOWN
  • E_FAIL is now treated as a valid return value, and the associated sokol-pixelformat is "disabled"

The git commit is 86e7570

@floooh I do appreciate it. I cannot test it either, but I will send an executable to the user to see how it goes for him now.

@floooh His computer went through it this time, but without any assertion call (all of them are enabled) it failed at the IDXGISwapChain_Present with result of DXGI_ERROR_DEVICE_RESET. Is there a way to determine which command actually failed within the frame rendering pass? I don't quite get how D3D11_CREATE_DEVICE_DEBUG could help me here since I need to debug it on the user side.

@floooh I do highly apologize. My user was not computer friendly and since my application has auto updater he did forget to mention that it did in fact ran.... Until the application downloaded the old executable once again leading to the same error.

So your fix solved the issue :) Also, I have to mention that I needed to use shader model 4.0 for all of it to work for him (like the author of this post). I doubt I will ever need shader model 5.0 for that matter. It might be worth re-considering to let it be set outside of sokol gfx.

I suggest that shader model version could be at least configurable via ifdefs.

I've started to work on the HLSL4 stuff. The current situation seems to be:

  • sokol_gfx.h already accepts shader model 4 shaders when provided as byte code
  • ...but it's not possible to compile to shader model 4 when passing HLSL source code to sg_make_shader()

So I'm doing this:

  • sokol-shdc gets a hlsl4 output option, this doesn't seem to make much of a difference for HLSL source output, but it's necessary for generating shader model 4 byte code
  • the sokol-shdc fips integration will use hlsl4 instead of hlsl5, so all sokol samples and other projects using fips will automatically use HLSL4 by default
  • I'll change all the embedded byte code in sokol utility headers also to SM4
  • when creating a shader from HLSL source code, there will be a new init param in sg_shader_stage_desc to define the HLSL shader model used for compilation (e.g. vs_4_0, vs_5_0, ps_4_0 or ps_5_0 - currently this is hardcoded to vs_5_0 and ps_5_0), the default for this new item will be vs_4_0 and ps_4_0.

I don't expect any code to break when switching to shader model 4.0 as default, because as far as I have seen the only difference to sm 5.0 is compute shader support, which isn't relevant for sokol_gfx.h anyway.

PS: I forgot one change: if sokol-shdc is instructed to generate HLSL source instead of byte code, it will set the new sg_shader_stage_stage init param to the right value for the selected shader model version and shader stage.

ok this should be fixed now, see #327 and the 20-Jun-2020 update here: https://github.com/floooh/sokol#updates

There is one extra thing I did notice in production. I've encountered users with SM below 4.0 and for that I had some fallback renderers. However, Sokol actually never fails with shader creation and the shader returned from sg_make_shader appears to be valid, so users end up with black window. The application doesn't know it failed since otherwise it would fallback to another renderer if it could detect that.

I think this is related to the same issue as described here. The shader compilation never fails, even on hardware which does not support specified SM version since I ship it with d3dcompiler_47.dll. The only way to detect that the shader won't work is by using assertion code, but we don't do that in production, so why not make the shader invalid if it fails at the lines pointed by the author of this issue? Currently from what I can see it just sets the resource as SG_RESOURCESTATE_VALID, but it's not really valid and I think we would know that from checking status of ID3D11Device_CreateVertexShader and ID3D11Device_CreatePixelShader.

Yes I think that makes sense. I'll create a separate issue and copy your comment there.