-
-
Notifications
You must be signed in to change notification settings - Fork 145
Description
Description
Adding the [D2DInputComplex(0)] attribute to an ID2D1PixelShader causes the app to crash.
Reproduction Steps
-
Configure a project to compile and run a ComputeSharp shader. You can use the [WinUI sample project] (https://github.com/Sergio0694/ComputeSharp/tree/main/samples/ComputeSharp.SwapChain.WinUI).
-
In the
ComputeSharp.SwapChain.UI\Shaders\Runnersfolder, add the following code to the project in a file namedD2D1MultiPassRunner.cs. This code is adapted from the D2D1ContouredLayersRunner sample.
using ComputeSharp;
using ComputeSharp.D2D1;
using ComputeSharp.D2D1.WinUI;
using System;
namespace ComputeSharp.SwapChain.Core.Shaders.Runners
{
/// <summary>
/// A multi-pass D2D1 effect with complex sampling.
/// </summary>
public sealed partial class D2D1MultiPassRunner : PixelShaderEffect
{
/// <summary>
/// First pass: Generate concentric circles.
/// </summary>
private static readonly CanvasEffectNode<PixelShaderEffect<ConcentricCirclesPass>> ConcentricCirclesNode = new();
/// <summary>
/// Second pass: Apply anti-aliasing with complex sampling.
/// </summary>
private static readonly CanvasEffectNode<PixelShaderEffect<AntiAliasingComplexPass>> AntiAliasingComplexNode = new();
/// <summary>
/// Third pass: Apply post-processing with complex sampling
/// </summary>
//private static readonly CanvasEffectNode<PixelShaderEffect<PostProcessingComplexPass>> PostProcessingComplexNode = new();
/// <inheritdoc/>
protected override unsafe void BuildEffectGraph(CanvasEffectGraph effectGraph)
{
// Create the effects with texture resources
var contouredLayers = new PixelShaderEffect<ConcentricCirclesPass>();
var antiAliasingComplex = new PixelShaderEffect<AntiAliasingComplexPass>();
//var postProcessingComplex = new PixelShaderEffect<PostProcessingComplexPass>();
// Connect the nodes using Sources[0]
antiAliasingComplex.Sources[0] = contouredLayers;
//postProcessingComplex.Sources[0] = antiAliasingComplex;
// Register all nodes
effectGraph.RegisterNode(ConcentricCirclesNode, contouredLayers);
effectGraph.RegisterNode(AntiAliasingComplexNode, antiAliasingComplex);
//effectGraph.RegisterNode(PostProcessingComplexNode, postProcessingComplex);
//effectGraph.RegisterOutputNode(postProcessingComplex);
effectGraph.RegisterOutputNode(antiAliasingComplex);
}
/// <inheritdoc/>
protected override void ConfigureEffectGraph(CanvasEffectGraph effectGraph)
{
float time = (float)ElapsedTime.TotalSeconds;
//int2 dispatchSize = new int2(ScreenWidth, ScreenHeight);
int2 dispatchSize = new int2(Math.Max(1, ScreenWidth), Math.Max(1, ScreenHeight));
// Configure first pass
effectGraph.GetNode(ConcentricCirclesNode).ConstantBuffer = new ConcentricCirclesPass(time, dispatchSize);
// Configure second pass with texture resource
effectGraph.GetNode(AntiAliasingComplexNode).ConstantBuffer = new AntiAliasingComplexPass(time, dispatchSize);
// Configure third pass with texture resource
//effectGraph.GetNode(PostProcessingComplexNode).ConstantBuffer = new PostProcessingComplexPass(time, dispatchSize);
}
}
/// <summary>
/// First pass: Generate the concentric circles effect.
/// </summary>
[D2DInputCount(0)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
internal readonly partial struct ConcentricCirclesPass(float time, int2 dispatchSize) : ID2D1PixelShader
{
/// <inheritdoc/>
public float4 Execute()
{
int2 xy = (int2)D2D.GetScenePosition().XY;
float2 uv = (float2)xy / (float2)dispatchSize;
float2 center = new float2(0.5f, 0.5f);
float2 offset = uv - center;
float distance = Hlsl.Length(offset);
// Create concentric circles
float circles = Hlsl.Sin(distance * 20.0f - time * 2.0f) * 0.5f + 0.5f;
// Add some color variation
float3 color = new float3(
circles * 0.8f + 0.2f,
circles * 0.6f + 0.4f,
circles * 0.4f + 0.6f
);
return new float4(color, 1.0f);
}
}
/// <summary>
/// Second pass: Apply anti-aliasing with complex sampling.
/// </summary>
[D2DInputCount(1)]
//[D2DInputSimple(0)]
[D2DInputComplex(0)] // Declare input 0 as complex for D2D.SampleInput
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
internal readonly partial struct AntiAliasingComplexPass(float time, int2 dispatchSize) : ID2D1PixelShader
{
/// <inheritdoc/>
public float4 Execute()
{
//return D2D.GetInput(0);
int2 xy = (int2)D2D.GetScenePosition().XY;
float2 uv = (float2)xy / (float2)dispatchSize;
return D2D.SampleInput(0, uv);
}
}
/// <summary>
/// Third pass: Apply post-processing with complex sampling.
/// </summary>
//[D2DInputCount(1)]
//[D2DInputComplex(0)] // Declare input 0 as complex for D2D.SampleInput
//[D2DRequiresScenePosition]
//[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
//[D2DGeneratedPixelShaderDescriptor]
//internal readonly partial struct PostProcessingComplexPass(float time, int2 dispatchSize) : ID2D1PixelShader
//{
// /// <inheritdoc/>
// public float4 Execute()
// {
// int2 xy = (int2)D2D.GetScenePosition().XY;
// float2 uv = (float2)xy / (float2)dispatchSize;
// // Sample from anti-aliasing pass using complex sampling
// float4 inputColor = D2D.SampleInput(0, uv); // D2D.GetInput(0);
// // Apply color grading and time-based effects
// float3 colorGraded = inputColor.XYZ;
// // Add time-based color variation
// float3 colorShift = new float3(
// 1.0f + 0.1f * Hlsl.Sin(time * 0.5f),
// 1.0f + 0.05f * Hlsl.Sin(time * 0.7f),
// 1.0f + 0.15f * Hlsl.Sin(time * 0.3f)
// );
// colorGraded *= colorShift;
// // Add subtle noise for texture
// float noise = Hlsl.Frac(Hlsl.Sin(Hlsl.Dot(uv, new float2(12.9898f, 78.233f))) * 43758.5453f);
// colorGraded += noise * 0.2f;
// // Apply contrast enhancement
// colorGraded = Hlsl.Pow(Hlsl.Abs(colorGraded), 0.9f);
// // Final color with proper alpha
// return new float4(Hlsl.Clamp(colorGraded, 0.0f, 1.0f), inputColor.W);
// }
//}
}- If using the ComputeSharp sample project, add the following code to
MainViewModel.ComputeShaderOptionsas the first element in theReadOnlyCollection:
new(nameof(ContouredLayers), new ContouredLayersRunner(), new D2D1MultiPassRunner()),-
Compile and run the application. The ContouredLayers shader displays.
-
Click Settings, and in the context menu, select Win2D (Direct2D).
Expected Behavior
The multi-pass pixel shader runs, displaying animated, concentric circles.
Actual Behavior
The app crashes.
This is the debug output:
onecoreuap\windows\frameworkudk\warppal.cpp(783)\Microsoft.Internal.WarpPal.dll!00007FFC6535EE4C: (caller: 00007FFC6698C27E) ReturnHr(6) tid(1fb4) 80004002 No such interface supported
Exception thrown at 0x00007FFC6C049F0A in ShaderGallery.exe: Microsoft C++ exception: HResultException at memory location 0x000000EA7197EED0.
Exception thrown at 0x00007FFC6C049F0A in ShaderGallery.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFC6C049F0A in ShaderGallery.exe: Microsoft C++ exception: HResultException at memory location 0x000000EA7197EFC0.
Exception thrown at 0x00007FFC6C049F0A in ShaderGallery.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFC6C049F0A in ShaderGallery.exe: Microsoft C++ exception: HResultException at memory location 0x000000EA6EF7CF00.
Exception thrown at 0x00007FFC6C049F0A in ShaderGallery.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFC6C049F0A (KernelBase.dll) in ShaderGallery.exe: WinRT originate error - 0x88990027 : 'IDispatcherQueueHandler::Invoke failed.'.
Unhandled exception at 0x00007FFBE7AB3B76 (CoreMessagingXP.dll) in ShaderGallery.exe: 0xC000027B: An application-internal exception has occurred (parameters: 0x000002DA343CE940, 0x0000000000000001).
Here's the stack dump:
KernelBase.dll!RaiseFailFastException() Unknown
combase.dll!RoFailFastWithErrorContextInternal2(HRESULT hrError, unsigned long cStowedExceptions, _STOWED_EXCEPTION_INFORMATION_V2 * * aStowedExceptionPointers) Line 1469 C++
CoreMessagingXP.dll!Microsoft::UI::Dispatching::DispatcherQueue::DeferInvokeCallback(void *) Unknown
CoreMessagingXP.dll!CFlat::SehSafe::Execute<<lambda_a81ff790741c2a62f2197c2561f5fe49>>() Unknown
CoreMessagingXP.dll!Microsoft::CoreUI::ActionCallback::ImportAdapter$(class CFlat::Box$1<struct CFlat::FunctionPointerAndUserData$1<long (*)(void *)> > *) Unknown
CoreMessagingXP.dll!Microsoft::CoreUI::Messaging::MessageSession::Callback_InvokeDeferInvoke(class Microsoft::CoreUI::ActionCallback *,struct System::UIntPtr) Unknown
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::DeferredCall::Callback_Dispatch(void) Unknown
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::DeferredCallDispatcher::Callback_OnDispatch(void) Unknown
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::Dispatcher::Callback_DispatchNextItem(class Microsoft::CoreUI::Dispatch::DispatchItem *) Unknown
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::Dispatcher::Callback_DispatchLoop(enum Microsoft::CoreUI::Dispatch::RunnablePriorityMask) Unknown
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::EventLoop::Callback_RunCoreLoop(enum Microsoft::CoreUI::Dispatch::RunMode) Unknown
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::UserAdapter::DrainCoreMessagingQueue(enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,void * *) Unknown
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::UserAdapter::OnUserDispatch(bool,enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,void * *) Unknown
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::UserAdapter::DoWork(struct HWND__ *,enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,bool) Unknown
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::UserAdapter::HandleDispatchNotifyMessage(struct HWND__ *,unsigned __int64,__int64) Unknown
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::UserAdapter::WindowProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
user32.dll!UserCallWinProcCheckWow(struct _ACTIVATION_CONTEXT *,__int64 (*)(struct tagWND *,unsigned int,unsigned __int64,__int64),struct HWND__ *,enum _WM_VALUE,unsigned __int64,__int64,void *,int) Unknown
user32.dll!DispatchClientMessage() Unknown
user32.dll!__fnDWORD() Unknown
ntdll.dll!KiUserCallbackDispatcherContinue() Unknown
win32u.dll!NtUserGetMessage() Unknown
user32.dll!GetMessageW() Unknown
bdhkm64.dll!00007ffb8d531ded() Unknown
bdhkm64.dll!00007ffb8d54a88a() Unknown
bdhkm64.dll!00007ffb8d545712() Unknown
Microsoft.ui.xaml.dll!DirectUI::FrameworkApplication::RunDesktopWindowMessageLoop() Line 1321 C++
Microsoft.ui.xaml.dll!DirectUI::FrameworkApplication::StartDesktop() Line 242 C++
[External Code]
[Inline Frame] hostpolicy.dll!coreclr_t::execute_assembly(int managed_assembly_path, const char * *) Line 108 C++
hostpolicy.dll!run_app_for_context(const hostpolicy_context_t & context, int argc, const wchar_t * * argv) Line 256 C++
hostpolicy.dll!run_app(const int argc, const wchar_t * * argv) Line 285 C++
hostpolicy.dll!corehost_main(const int argc, const wchar_t * * argv) Line 426 C++
hostfxr.dll!execute_app(const std::wstring & impl_dll_dir, corehost_init_t * init, const int argc, const wchar_t * * argv) Line 145 C++
hostfxr.dll!`anonymous namespace'::read_config_and_execute(const std::wstring & host_command, const host_startup_info_t & host_info, const std::wstring & app_candidate, const std::unordered_map<enum known_options,std::vector<std::wstring,std::allocator<std::wstring>>,known_options_hash,std::equal_to<enum known_options>,std::allocator<std::pair<enum known_options const ,std::vector<std::wstring,std::allocator<std::wstring>>>>> & opts, int new_argc, const wchar_t * * new_argv, host_mode_t mode, const bool is_sdk_command, wchar_t * out_buffer, int buffer_size, int * required_buffer_size) Line 532 C++
hostfxr.dll!fx_muxer_t::handle_exec_host_command(const std::wstring & host_command, const host_startup_info_t & host_info, const std::wstring & app_candidate, const std::unordered_map<enum known_options,std::vector<std::wstring,std::allocator<std::wstring>>,known_options_hash,std::equal_to<enum known_options>,std::allocator<std::pair<enum known_options const ,std::vector<std::wstring,std::allocator<std::wstring>>>>> & opts, int argc, const wchar_t * * argv, int argoff, host_mode_t mode, const bool is_sdk_command, wchar_t * result_buffer, int buffer_size, int * required_buffer_size) Line 1007 C++
hostfxr.dll!fx_muxer_t::execute(const std::wstring host_command, const int argc, const wchar_t * * argv, const host_startup_info_t & host_info, wchar_t * result_buffer, int buffer_size, int * required_buffer_size) Line 578 C++
hostfxr.dll!hostfxr_main_startupinfo(const int argc, const wchar_t * * argv, const wchar_t * host_path, const wchar_t * dotnet_root, const wchar_t * app_path) Line 63 C++
ShaderGallery.exe!exe_start(const int argc, const wchar_t * * argv) Line 253 C++
ShaderGallery.exe!wmain(const int argc, const wchar_t * * argv) Line 324 C++
[External Code]
System info
- ComputeSharp NuGet version: 3.2.0
- Operating system version: Windows 11 Pro version 24H2, build 26100.4652
- CPU/GPU model:
- Integrated chipset: Intel(R) Iris(R) Xe Graphics NVIDIA @ 3840 x 2160 (32 bit) (60Hz); adapter attributes HARDWARE_TYPE_GPU,D3D11_GRAPHICS,D3D12_GRAPHICS,D3D12_CORE_COMPUTE,D3D12_GENERIC_ML,D3D12_GENERIC_MEDIA; feature levels: 12_1,12_0,11_1,11_0,10_1,10_0,9_3,9_2,9_1,1_0_CORE
- GPU: NVIDIA GeForce RTX 4070 Laptop GPU; adapter attributes HARDWARE_TYPE_GPU,D3D11_GRAPHICS,D3D12_GRAPHICS,D3D12_CORE_COMPUTE,D3D12_GENERIC_ML,D3D12_GENERIC_MEDIA; feature levels: 12_2,12_1,12_0,11_1,11_0,10_1,10_0,9_3,9_2,9_1,1_0_CORE
- NVIDIA Control Panel setting Preferred graphic processor set to High-performance NVIDIA processor, although the issue repros with Integrated graphics.
- Visual Studio version: 17.14.8
Additional context (optional)
I'm a complete n00b to shader programming, so it's quite possible that I'm doing something wrong. I've reproduced this issue on another computer with an RTX-4090 NVIDIA card, so it's probably not my hardware configuration.
Just guessing, it seems like the system QIs for a DirectX interface and doesn't find it, causing the system to fall back to WARP. Gemini says this:
0x88990027 (D2DERR_RECREATE_TARGET): This is a Direct2D error code. D2DERR_RECREATE_TARGET specifically means "The render target has been invalidated and must be recreated." This usually happens when:
The underlying Direct3D device is lost (e.g., due to a driver crash, GPU reset, TDR - Timeout Detection and Recovery, or power-saving mode).
The display mode changes.
The application attempts an operation that's not supported by the current device capabilities.
IDispatcherQueueHandler::Invokefailed: This indicates that an operation scheduled on the UI thread (viaDispatcherQueue) failed, likely because it was trying to interact with the D2D1 rendering system that had already crashed or become invalid.
Maybe there's a better way to implement a multipass pixel shader with complex sampling. I can do a multipass shader with simple sampling, but I need complex sampling for various effects. I've managed to implement a multipass compute shader, but the mechanism is completely different, requiring me to ping-pong ReadWriteBuffer<float4> instances. Maybe there's a better way to do this, too.