Direct3D 12/PIX调试异常:像素着色器未被调用
Direct3D 12像素着色器未被调用的排查方向
我是Direct3D 12开发新手,搭建测试项目熟悉流程时遇到问题:通过PIX调试确认顶点着色器运行正常,但像素着色器未被调用。已检查裁剪区域、视口和深度缓冲,确认顶点未被裁剪,但问题仍未解决。
相关截图说明:
- PIX中的管线状态
- PIX中的顶点着色器输出
相关代码片段
光栅化状态、深度模板状态
D3D12_RASTERIZER_DESC rasterizer{}; rasterizer.FillMode = D3D12_FILL_MODE_SOLID; rasterizer.CullMode = D3D12_CULL_MODE_NONE; rasterizer.FrontCounterClockwise = FALSE; rasterizer.DepthClipEnable = TRUE; rasterizer.MultisampleEnable = FALSE; rasterizer.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; pipelineDesc.RasterizerState = rasterizer; D3D12_DEPTH_STENCIL_DESC depthStencil{}; depthStencil.DepthEnable = TRUE; depthStencil.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; depthStencil.DepthFunc = D3D12_COMPARISON_FUNC_LESS; depthStencil.StencilEnable = FALSE; depthStencil.FrontFace.StencilFailOp = D3D12_STENCIL_OP_KEEP; depthStencil.BackFace.StencilFailOp = D3D12_STENCIL_OP_KEEP; depthStencil.FrontFace.StencilPassOp = D3D12_STENCIL_OP_KEEP; depthStencil.BackFace.StencilPassOp = D3D12_STENCIL_OP_KEEP; depthStencil.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS; depthStencil.BackFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;
交换链创建、RTV创建
DXGI_SWAP_CHAIN_DESC1 swapchainDescription{}; DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreenDescription{}; swapchainDescription.Width = 0; swapchainDescription.Height = 0; swapchainDescription.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; swapchainDescription.Stereo = FALSE; swapchainDescription.SampleDesc = { 1, 0 }; swapchainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapchainDescription.BufferCount = 2; swapchainDescription.Scaling = DXGI_SCALING_NONE; swapchainDescription.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapchainDescription.AlphaMode = DXGI_ALPHA_MODE_IGNORE; swapchainDescription.Flags = 0; fullscreenDescription.RefreshRate = { 1, 60 }; fullscreenDescription.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; fullscreenDescription.Scaling = DXGI_MODE_SCALING_CENTERED; fullscreenDescription.Windowed = TRUE; CheckHresult(factory->CreateSwapChainForHwnd(commandQueue, hwnd, &swapchainDescription, &fullscreenDescription, NULL, &t_swapchain)); HRESULT sres = t_swapchain->QueryInterface(IID_PPV_ARGS(&swapchain)); D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapInfoRtv{}; descriptorHeapInfoRtv.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; descriptorHeapInfoRtv.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; descriptorHeapInfoRtv.NumDescriptors = 2; descriptorHeapInfoRtv.NodeMask = 0; device->CreateDescriptorHeap(&descriptorHeapInfoRtv, IID_PPV_ARGS(&rtv_descriptorHeap.descriptorHeap)); rtv_descriptorHeap.incrementSize = device->GetDescriptorHandleIncrementSize(descriptorHeapInfoRtv.Type); rtv_descriptorHeap.startHandle = rtv_descriptorHeap.descriptorHeap->GetCPUDescriptorHandleForHeapStart(); device->CreateRenderTargetView(swapchainBuffers[0], NULL, rtv_descriptorHeap.startHandle); device->CreateRenderTargetView(swapchainBuffers[1], NULL, rtv_descriptorHeap.AddOffset(1));
着色器代码
// Vertex Shader struct VS_IN { float4 pos : POSITION; }; struct VS_OUT { float4 pos : SV_Position; }; VS_OUT main(VS_IN inp) { VS_OUT outp; outp.pos = float4(inp.pos.x, inp.pos.y, inp.pos.z, 1.0f); return outp; } // Pixel Shader struct PS_OUT { float4 col_in : COLOR; }; struct VS_OUT { float4 pos : SV_Position; }; float4 main(VS_OUT inp) : SV_Target { PS_OUT outp; outp.col_in = float4(1.0f, 1.0f, 1.0f, 1.0f); return outp.col_in; }
已尝试操作:使用默认设置和自定义RenderTargetView描述、禁用深度测试、修改管线状态samplemask,问题仍未解决。
排查方向
- 检查齐次坐标转换:顶点着色器直接输出
w=1.0的原始坐标,未转换到Direct3D要求的齐次裁剪空间(x,y,z需落在[-w,w]范围内)。如果顶点不在此范围,光栅化阶段会被剔除。需将顶点坐标映射到NDC空间(比如正交投影下转换到[-1,1],透视投影执行对应计算)。 - 验证深度缓冲的创建与绑定:当前代码仅创建了RTV,未看到深度缓冲(DSV)的创建和绑定逻辑。开启
DepthEnable=TRUE但未正确绑定深度缓冲会导致光栅化异常,进而不触发像素着色器。需确认:- 创建了格式正确的深度纹理(如DXGI_FORMAT_D32_FLOAT)
- 创建DSV描述符堆并正确绑定到命令列表
- OMSetRenderTargets时同时设置RTV和DSV
- 确认PSO的像素着色器关联:检查管线状态对象(PSO)是否正确加载了像素着色器字节码,可在PIX中查看PSO的像素着色器配置是否正常。
- 重新验证视口与裁剪矩形:确保命令列表中调用了
RSSetViewports和RSSetScissorRects,且参数覆盖了渲染区域,没有意外剔除像素。 - 检查顶点输入布局匹配性:确认顶点输入布局的格式、步长与实际传入的顶点数据完全一致,避免因顶点位置解析错误导致输出坐标异常。
- 分析PIX光栅化统计:在PIX中查看光栅化阶段的像素生成数量,若为0说明顶点虽通过裁剪,但光栅化后无像素生成(如图元完全在视口外、图元面积为0)。
- 禁用光栅化相关限制:尝试将
RasterizerState.DepthClipEnable设为FALSE,同时关闭深度测试(DepthEnable=FALSE),再次测试是否触发像素着色器,排除深度相关问题。
内容的提问来源于stack exchange,提问作者Fredrik
相关产品推荐
相关产品推荐

