使用Evergine与DirectX12时出现System.AccessViolationException求助
问题分析与修复方案
异常原因
你遇到的System.AccessViolationException异常,本质是DirectX 12运行时尝试访问无效内存地址。结合异常触发点commandBuffer.SetGraphicsPipelineState(_pipelineState),核心原因大概率是图形管线状态(PipelineState)未正确初始化,或CommandBuffer处于异常状态,具体可能包括:
- PipelineState对象创建时参数不合法(如输入布局与着色器不匹配、资源关联错误)
- PipelineState已被提前释放或未完成初始化
- CommandBuffer未处于正确的录制状态(如未开始录制、已结束录制)
具体修复步骤
1. 确保PipelineState创建参数完全符合DX12要求
检查Renderable.cs中PipelineState的创建逻辑,需保证以下几点:
- 输入布局与着色器语义严格匹配:顶点数据的类型、语义名称(如
POSITION)、语义索引必须和HLSL着色器的输入完全一致。例如顶点数据是Vector3,着色器中必须对应float3 POSITION : SV_POSITION;(或正确的语义绑定)。 - 显式配置DX12所需的管线状态参数:DX12对管线状态的要求比DX11更严格,不能依赖默认值。需显式设置光栅化状态、混合状态、图元拓扑类型、渲染目标格式等:
var pipelineDesc = new GraphicsPipelineStateDescription { InputLayout = inputLayout, VertexShader = vertexShaderByteCode, PixelShader = pixelShaderByteCode, // 显式设置光栅化状态(按需调整) RasterizerState = new RasterizerDescription(CullMode.Back, FillMode.Solid) { IsDepthClipEnabled = true, IsMultisampleEnabled = false }, // 显式设置混合状态(纯色三角形可使用默认) BlendState = BlendDescription.Default, // 深度模板状态(如果不需要深度可禁用) DepthStencilState = new DepthStencilDescription(false, false), PrimitiveTopologyType = PrimitiveTopologyType.Triangle, // 匹配当前渲染目标的格式 RenderTargetFormats = new[] { graphicsContext.SurfaceFormat }, DepthStencilFormat = graphicsContext.DepthStencilFormat }; // 确保使用DX12上下文的工厂创建管线状态 _pipelineState = graphicsContext.Factory.CreateGraphicsPipelineState(pipelineDesc);
2. 验证CommandBuffer的状态正确性
在Triangle.cs的RenderInternal方法中,确保CommandBuffer处于录制状态时调用SetGraphicsPipelineState:
// 确认CommandBuffer已正确开始录制 commandBuffer.Begin(); // 在此之后执行管线状态设置、绘制等操作 commandBuffer.SetGraphicsPipelineState(_pipelineState); // ...其他绘制逻辑 // 绘制完成后结束录制并提交 commandBuffer.End(); graphicsContext.CommandQueue.ExecuteCommandBuffer(commandBuffer);
避免在CommandBuffer未开始录制、已结束录制的状态下调用API。
3. 检查着色器编译的完整性
即使使用了Level_12_0配置文件,仍需确认:
- 顶点着色器和像素着色器都成功编译,无编译错误
- 着色器的目标Profile与DX12兼容(推荐使用
sm_5_1或更高,对应GraphicsProfile.Level_12_1)
var compilerParams = CompilerParameters.Default with { Profile = GraphicsProfile.Level_12_1, // 添加调试信息,方便排查着色器问题 DebugMode = true }; var vertexResult = graphicsContext.ShaderCompile(vertexSource, "VS", ShaderStages.Vertex, compilerParams); var pixelResult = graphicsContext.ShaderCompile(pixelSource, "PS", ShaderStages.Pixel, compilerParams); // 检查编译是否成功 if (!vertexResult.Success || !pixelResult.Success) { throw new InvalidOperationException($"Shader compile error: {vertexResult.ErrorMessage}\n{pixelResult.ErrorMessage}"); }
4. 确保资源生命周期正确管理
在Evergine中,PipelineState等资源需正确关联到上下文或资源容器,避免被GC提前回收。可将_pipelineState添加到组件的Resources集合中:
// 在Renderable.cs的Initialize方法中创建PipelineState后 this.Resources.Add(_pipelineState);
总结
DirectX 12的异常大多源于资源初始化不规范或状态管理错误,重点排查PipelineState的创建参数、CommandBuffer的录制状态,以及资源生命周期管理。对比Evergine官方LowLevelAPIDemo项目的管线创建逻辑,逐步验证每一步的参数是否匹配DX12的要求。
内容的提问来源于stack exchange,提问作者bertiooo
相关产品推荐
相关产品推荐

