git.s-ol.nu ~forks/DiligentCore / 26b4601
Fixed handling pixel shader UAVs in D3D11 assiduous 6 months ago
3 changed file(s) with 115 addition(s) and 108 deletion(s). Raw diff Collapse all Expand all
385385 }
386386 };
387387
388 enum PixelShaderUAVBindMode
389 {
390 Clear = 0,
391 Keep,
392 Bind
393 };
394
388395 using TBindingsPerStage = PipelineResourceSignatureD3D11Impl::TBindingsPerStage;
389396 void BindCacheResources(const ShaderResourceCacheD3D11& ResourceCache,
390397 const TBindingsPerStage& BaseBindings,
391 SHADER_TYPE ActiveStages);
398 SHADER_TYPE ActiveStages,
399 PixelShaderUAVBindMode& PsUavBindMode);
392400
393401 #ifdef DILIGENT_DEVELOPMENT
394402 void DvpValidateCommittedShaderResources();
295295 };
296296
297297 template <D3D11_RESOURCE_RANGE Range>
298 MinMaxSlot BindResources(Uint32 ShaderInd,
299 typename CachedResourceTraits<Range>::D3D11ResourceType* CommittedD3D11Resources[],
300 Uint8& Binding) const;
298 inline MinMaxSlot BindResources(Uint32 ShaderInd,
299 typename CachedResourceTraits<Range>::D3D11ResourceType* CommittedD3D11Resources[],
300 const TResourcesPerStage& BaseBindings) const;
301301
302302 template <D3D11_RESOURCE_RANGE Range>
303 MinMaxSlot BindResourceViews(Uint32 ShaderInd,
304 typename CachedResourceTraits<Range>::D3D11ResourceType* CommittedD3D11Views[],
305 ID3D11Resource* CommittedD3D11Resources[],
306 Uint8& Binding) const;
303 inline MinMaxSlot BindResourceViews(Uint32 ShaderInd,
304 typename CachedResourceTraits<Range>::D3D11ResourceType* CommittedD3D11Views[],
305 ID3D11Resource* CommittedD3D11Resources[],
306 const TResourcesPerStage& BaseBindings) const;
307307
308308 enum class StateTransitionMode
309309 {
491491 template void ShaderResourceCacheD3D11::TransitionResourceStates<ShaderResourceCacheD3D11::StateTransitionMode::Verify>(DeviceContextD3D11Impl& Ctx);
492492
493493 template <D3D11_RESOURCE_RANGE Range>
494 ShaderResourceCacheD3D11::MinMaxSlot ShaderResourceCacheD3D11::BindResources(
494 inline ShaderResourceCacheD3D11::MinMaxSlot ShaderResourceCacheD3D11::BindResources(
495495 Uint32 ShaderInd,
496496 typename CachedResourceTraits<Range>::D3D11ResourceType* CommittedD3D11Resources[],
497 Uint8& Binding) const
498 {
499 const auto ResCount = GetResourceCount<Range>(ShaderInd);
500 const auto ResArrays = GetConstResourceArrays<Range>(ShaderInd);
497 const TResourcesPerStage& BaseBindings) const
498 {
499 const auto ResCount = GetResourceCount<Range>(ShaderInd);
500 const auto ResArrays = GetConstResourceArrays<Range>(ShaderInd);
501 const Uint32 BaseBinding = BaseBindings[Range][ShaderInd];
501502
502503 MinMaxSlot Slots;
503504 for (Uint32 res = 0; res < ResCount; ++res)
504505 {
505 const Uint32 Slot = Binding++;
506 const Uint32 Slot = BaseBinding + res;
506507 if (CommittedD3D11Resources[Slot] != ResArrays.second[res])
507508 Slots.Add(Slot);
508509
515516
516517
517518 template <D3D11_RESOURCE_RANGE Range>
518 ShaderResourceCacheD3D11::MinMaxSlot ShaderResourceCacheD3D11::BindResourceViews(
519 inline ShaderResourceCacheD3D11::MinMaxSlot ShaderResourceCacheD3D11::BindResourceViews(
519520 Uint32 ShaderInd,
520521 typename CachedResourceTraits<Range>::D3D11ResourceType* CommittedD3D11Views[],
521522 ID3D11Resource* CommittedD3D11Resources[],
522 Uint8& Binding) const
523 {
524 const auto ResCount = GetResourceCount<Range>(ShaderInd);
525 const auto ResArrays = GetConstResourceArrays<Range>(ShaderInd);
523 const TResourcesPerStage& BaseBindings) const
524 {
525 const auto ResCount = GetResourceCount<Range>(ShaderInd);
526 const auto ResArrays = GetConstResourceArrays<Range>(ShaderInd);
527 const Uint32 BaseBinding = BaseBindings[Range][ShaderInd];
526528
527529 MinMaxSlot Slots;
528530 for (Uint32 res = 0; res < ResCount; ++res)
529531 {
530 const Uint32 Slot = Binding++;
532 const Uint32 Slot = BaseBinding + res;
531533 if (CommittedD3D11Views[Slot] != ResArrays.second[res])
532534 Slots.Add(Slot);
533535
265265
266266 void DeviceContextD3D11Impl::BindCacheResources(const ShaderResourceCacheD3D11& ResourceCache,
267267 const TBindingsPerStage& BaseBindings,
268 SHADER_TYPE ActiveStages)
269 {
270 bool ClearPixelShaderUAVs = m_CommittedRes.NumUAVs[PSInd] > 0;
271
268 SHADER_TYPE ActiveStages,
269 PixelShaderUAVBindMode& PsUavBindMode)
270 {
272271 while (ActiveStages != 0)
273272 {
274273 const auto ShaderInd = PlatformMisc::GetLSB(ActiveStages);
275274 const auto ShaderType = static_cast<SHADER_TYPE>(1u << ShaderInd);
276275 ActiveStages &= ~ShaderType;
277276
277 if (ResourceCache.GetCBCount(ShaderInd) > 0)
278278 {
279279 auto* d3d11CBs = m_CommittedRes.d3d11CBs[ShaderInd];
280 Uint8 Binding = BaseBindings[D3D11_RESOURCE_RANGE_CBV][ShaderInd];
281 auto Slots = ResourceCache.BindResources<D3D11_RESOURCE_RANGE_CBV>(ShaderInd, d3d11CBs, Binding);
282
283 if (Slots)
280 if (auto Slots = ResourceCache.BindResources<D3D11_RESOURCE_RANGE_CBV>(ShaderInd, d3d11CBs, BaseBindings))
284281 {
285282 auto SetCBMethod = SetCBMethods[ShaderInd];
286283 (m_pd3d11DeviceContext->*SetCBMethod)(Slots.MinSlot, Slots.MaxSlot - Slots.MinSlot + 1, d3d11CBs + Slots.MinSlot);
287 m_CommittedRes.NumCBs[ShaderInd] = std::max(m_CommittedRes.NumCBs[ShaderInd], Binding);
288 VERIFY_EXPR(Slots.MaxSlot < Binding);
284 m_CommittedRes.NumCBs[ShaderInd] = std::max(m_CommittedRes.NumCBs[ShaderInd], static_cast<Uint8>(Slots.MaxSlot + 1));
289285 }
290286 #ifdef VERIFY_CONTEXT_BINDINGS
291287 if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
295291 #endif
296292 }
297293
294 if (ResourceCache.GetSRVCount(ShaderInd) > 0)
298295 {
299296 auto* d3d11SRVs = m_CommittedRes.d3d11SRVs[ShaderInd];
300297 auto* d3d11SRVRes = m_CommittedRes.d3d11SRVResources[ShaderInd];
301 Uint8 Binding = BaseBindings[D3D11_RESOURCE_RANGE_SRV][ShaderInd];
302 auto Slots = ResourceCache.BindResourceViews<D3D11_RESOURCE_RANGE_SRV>(ShaderInd, d3d11SRVs, d3d11SRVRes, Binding);
303
304 if (Slots)
298 if (auto Slots = ResourceCache.BindResourceViews<D3D11_RESOURCE_RANGE_SRV>(ShaderInd, d3d11SRVs, d3d11SRVRes, BaseBindings))
305299 {
306300 auto SetSRVMethod = SetSRVMethods[ShaderInd];
307301 (m_pd3d11DeviceContext->*SetSRVMethod)(Slots.MinSlot, Slots.MaxSlot - Slots.MinSlot + 1, d3d11SRVs + Slots.MinSlot);
308 m_CommittedRes.NumSRVs[ShaderInd] = std::max(m_CommittedRes.NumSRVs[ShaderInd], Binding);
309 VERIFY_EXPR(Slots.MaxSlot <= Binding);
302 m_CommittedRes.NumSRVs[ShaderInd] = std::max(m_CommittedRes.NumSRVs[ShaderInd], static_cast<Uint8>(Slots.MaxSlot + 1));
310303 }
311304 #ifdef VERIFY_CONTEXT_BINDINGS
312305 if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
316309 #endif
317310 }
318311
312 if (ResourceCache.GetSamplerCount(ShaderInd) > 0)
319313 {
320314 auto* d3d11Samplers = m_CommittedRes.d3d11Samplers[ShaderInd];
321 Uint8 Binding = BaseBindings[D3D11_RESOURCE_RANGE_SAMPLER][ShaderInd];
322 auto Slots = ResourceCache.BindResources<D3D11_RESOURCE_RANGE_SAMPLER>(ShaderInd, d3d11Samplers, Binding);
323
324 if (Slots)
315 if (auto Slots = ResourceCache.BindResources<D3D11_RESOURCE_RANGE_SAMPLER>(ShaderInd, d3d11Samplers, BaseBindings))
325316 {
326317 auto SetSamplerMethod = SetSamplerMethods[ShaderInd];
327318 (m_pd3d11DeviceContext->*SetSamplerMethod)(Slots.MinSlot, Slots.MaxSlot - Slots.MinSlot + 1, d3d11Samplers + Slots.MinSlot);
328 m_CommittedRes.NumSamplers[ShaderInd] = std::max(m_CommittedRes.NumSamplers[ShaderInd], Binding);
329 VERIFY_EXPR(Slots.MaxSlot < Binding);
319 m_CommittedRes.NumSamplers[ShaderInd] = std::max(m_CommittedRes.NumSamplers[ShaderInd], static_cast<Uint8>(Slots.MaxSlot + 1));
330320 }
331321 #ifdef VERIFY_CONTEXT_BINDINGS
332322 if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
336326 #endif
337327 }
338328
339 {
329 if (ResourceCache.GetUAVCount(ShaderInd) > 0)
330 {
331 if (ShaderInd == PSInd && PsUavBindMode != PixelShaderUAVBindMode::Bind)
332 PsUavBindMode = PixelShaderUAVBindMode::Keep;
333
340334 auto* d3d11UAVs = m_CommittedRes.d3d11UAVs[ShaderInd];
341335 auto* d3d11UAVRes = m_CommittedRes.d3d11UAVResources[ShaderInd];
342 Uint8 Binding = BaseBindings[D3D11_RESOURCE_RANGE_UAV][ShaderInd];
343 auto Slots = ResourceCache.BindResourceViews<D3D11_RESOURCE_RANGE_UAV>(ShaderInd, d3d11UAVs, d3d11UAVRes, Binding);
344
345 if (Slots)
346 {
347 if (ShaderInd == PSInd)
348 ClearPixelShaderUAVs = false;
349
350 // Something has changed
336 if (auto Slots = ResourceCache.BindResourceViews<D3D11_RESOURCE_RANGE_UAV>(ShaderInd, d3d11UAVs, d3d11UAVRes, BaseBindings))
337 {
351338 if (ShaderInd == PSInd)
352339 {
353 // Pixel shader UAVs cannot be set independently; they all need to be set at the same time.
354 // https://docs.microsoft.com/en-us/windows/desktop/api/d3d11/nf-d3d11-id3d11devicecontext-omsetrendertargetsandunorderedaccessviews#remarks
355 const auto StartUAVSlot = m_NumBoundRenderTargets;
356 const auto NumUAVSlot = Binding;
357 VERIFY(NumUAVSlot > StartUAVSlot, "Number of UAVs must be greater than the render target count");
358 m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews(
359 D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
360 StartUAVSlot, NumUAVSlot - StartUAVSlot, d3d11UAVs + StartUAVSlot, nullptr);
361 // Clear previously bound UAVs, but do not clear lower slots as if
362 // render target count reduces, we will bind these UAVs in CommitRenderTargets()
363 for (Uint32 uav = NumUAVSlot; uav < m_CommittedRes.NumUAVs[ShaderInd]; ++uav)
364 {
365 d3d11UAVRes[uav] = nullptr;
366 d3d11UAVs[uav] = nullptr;
367 }
368 m_CommittedRes.NumUAVs[ShaderInd] = NumUAVSlot;
340 PsUavBindMode = PixelShaderUAVBindMode::Bind;
369341 }
370342 else if (ShaderInd == CSInd)
371343 {
372344 // This can only be CS
373345 auto SetUAVMethod = SetUAVMethods[ShaderInd];
374346 (m_pd3d11DeviceContext->*SetUAVMethod)(Slots.MinSlot, Slots.MaxSlot - Slots.MinSlot + 1, d3d11UAVs + Slots.MinSlot, nullptr);
375 m_CommittedRes.NumUAVs[ShaderInd] = std::max(m_CommittedRes.NumUAVs[ShaderInd], Binding);
376 VERIFY_EXPR(Slots.MaxSlot < Binding);
347 m_CommittedRes.NumUAVs[ShaderInd] = std::max(m_CommittedRes.NumUAVs[ShaderInd], static_cast<Uint8>(Slots.MaxSlot + 1));
377348 }
378349 else
379350 {
388359 #endif
389360 }
390361 }
391
392 if (ClearPixelShaderUAVs)
362 }
363
364 void DeviceContextD3D11Impl::BindShaderResources()
365 {
366 if ((m_BindInfo.StaleSRBMask & m_BindInfo.ActiveSRBMask) == 0)
367 return;
368
369 TBindingsPerStage Bindings = {};
370 const auto ActiveStages = m_BindInfo.ActiveStages;
371
372 if (m_pPipelineState->GetDesc().IsAnyGraphicsPipeline())
373 Bindings[D3D11_RESOURCE_RANGE_UAV][GetShaderTypeIndex(SHADER_TYPE_PIXEL)] = static_cast<Uint8>(m_pPipelineState->GetGraphicsPipelineDesc().NumRenderTargets);
374
375 PixelShaderUAVBindMode PsUavBindMode = m_CommittedRes.NumUAVs[PSInd] > 0 ?
376 PixelShaderUAVBindMode::Clear :
377 PixelShaderUAVBindMode::Keep;
378
379 auto ActiveSRBMask = Uint32{m_BindInfo.ActiveSRBMask};
380 while (ActiveSRBMask != 0)
381 {
382 Uint32 sign = PlatformMisc::GetLSB(ActiveSRBMask);
383 Uint32 SigBit = (1u << sign);
384 VERIFY_EXPR(sign < m_pPipelineState->GetResourceSignatureCount());
385
386 ActiveSRBMask &= ~SigBit;
387
388 auto* pSRB = m_BindInfo.SRBs[sign];
389 VERIFY_EXPR(pSRB);
390
391 if (m_BindInfo.StaleSRBMask & SigBit)
392 {
393 #ifdef DILIGENT_DEVELOPMENT
394 m_BindInfo.BoundResOffsets[sign] = Bindings;
395 #endif
396 BindCacheResources(pSRB->GetResourceCache(), Bindings, ActiveStages, PsUavBindMode);
397 }
398 pSRB->GetSignature()->ShiftBindings(Bindings);
399 }
400 m_BindInfo.StaleSRBMask &= ~m_BindInfo.ActiveSRBMask;
401
402
403 if (PsUavBindMode == PixelShaderUAVBindMode::Bind)
404 {
405 // Pixel shader UAVs cannot be set independently; they all need to be set at the same time.
406 // https://docs.microsoft.com/en-us/windows/desktop/api/d3d11/nf-d3d11-id3d11devicecontext-omsetrendertargetsandunorderedaccessviews#remarks
407 const auto StartUAVSlot = m_NumBoundRenderTargets;
408
409 const Uint8 NumUAVSlots = Bindings[D3D11_RESOURCE_RANGE_UAV][PSInd];
410 VERIFY(NumUAVSlots > StartUAVSlot, "Number of UAVs must be greater than the render target count");
411 auto* d3d11UAVs = m_CommittedRes.d3d11UAVs[PSInd];
412 auto* d3d11UAVRes = m_CommittedRes.d3d11UAVResources[PSInd];
413 m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews(
414 D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
415 StartUAVSlot, NumUAVSlots - StartUAVSlot, d3d11UAVs + StartUAVSlot, nullptr);
416 // Clear previously bound UAVs, but do not clear lower slots as if
417 // render target count reduces, we will bind these UAVs in CommitRenderTargets()
418 for (Uint32 uav = NumUAVSlots; uav < m_CommittedRes.NumUAVs[PSInd]; ++uav)
419 {
420 d3d11UAVRes[uav] = nullptr;
421 d3d11UAVs[uav] = nullptr;
422 }
423 m_CommittedRes.NumUAVs[PSInd] = NumUAVSlots;
424 }
425 else if (PsUavBindMode == PixelShaderUAVBindMode::Clear)
393426 {
394427 // If pixel shader stage is inactive or does not use UAVs, unbind all committed UAVs.
395428 // This is important as UnbindPixelShaderUAV<> function may need to rebind
408441 0, 0, nullptr, nullptr);
409442 NumCommittedPixelShaderUAVs = 0;
410443 }
411 }
412
413 void DeviceContextD3D11Impl::BindShaderResources()
414 {
415 if ((m_BindInfo.StaleSRBMask & m_BindInfo.ActiveSRBMask) == 0)
416 return;
417
418 TBindingsPerStage Bindings = {};
419 const auto ActiveStages = m_BindInfo.ActiveStages;
420
421 if (m_pPipelineState->GetDesc().IsAnyGraphicsPipeline())
422 Bindings[D3D11_RESOURCE_RANGE_UAV][GetShaderTypeIndex(SHADER_TYPE_PIXEL)] = static_cast<Uint8>(m_pPipelineState->GetGraphicsPipelineDesc().NumRenderTargets);
423
424 auto ActiveSRBMask = Uint32{m_BindInfo.ActiveSRBMask};
425 while (ActiveSRBMask != 0)
426 {
427 Uint32 sign = PlatformMisc::GetLSB(ActiveSRBMask);
428 Uint32 SigBit = (1u << sign);
429 VERIFY_EXPR(sign < m_pPipelineState->GetResourceSignatureCount());
430
431 ActiveSRBMask &= ~SigBit;
432
433 auto* pSRB = m_BindInfo.SRBs[sign];
434 VERIFY_EXPR(pSRB);
435
436 if (m_BindInfo.StaleSRBMask & SigBit)
437 {
438 #ifdef DILIGENT_DEVELOPMENT
439 m_BindInfo.BoundResOffsets[sign] = Bindings;
440 #endif
441 BindCacheResources(pSRB->GetResourceCache(), Bindings, ActiveStages);
442 }
443 pSRB->GetSignature()->ShiftBindings(Bindings);
444 }
445
446 m_BindInfo.StaleSRBMask &= ~m_BindInfo.ActiveSRBMask;
447444 }
448445
449446 #ifdef DILIGENT_DEVELOPMENT