diff --git a/src/d3d11/d3d11_buffer.cpp b/src/d3d11/d3d11_buffer.cpp index da41ec382..3aa09f191 100644 --- a/src/d3d11/d3d11_buffer.cpp +++ b/src/d3d11/d3d11_buffer.cpp @@ -17,7 +17,6 @@ struct BufferViewInfo { class D3D11Buffer : public TResourceBase { private: - Rc buffer_; #ifdef DXMT_DEBUG std::string debug_name; #endif @@ -29,45 +28,37 @@ class D3D11Buffer : public TResourceBase { using SRVBase = TResourceViewBase>; class TBufferSRV : public SRVBase { - BufferViewInfo info; public: TBufferSRV( const tag_shader_resource_view<>::DESC1 *pDesc, D3D11Buffer *pResource, MTLD3D11Device *pDevice, BufferViewInfo const &info ) : - SRVBase(pDesc, pResource, pDevice), - info(info) {} + SRVBase(pDesc, pResource, pDevice) { + buffer_ = pResource->buffer_.ptr(); + view_id_ = info.viewKey; + slice_ = {info.byteOffset, info.byteWidth, info.viewElementOffset, info.viewElementWidth }; + subset_ = ResourceSubsetState(info.byteOffset, info.byteWidth); + } ~TBufferSRV() {} - - Rc buffer() final { return resource->buffer_; }; - Rc texture() final { return {}; }; - unsigned viewId() final { return info.viewKey;}; - BufferSlice bufferSlice() final { return {info.byteOffset, info.byteWidth, info.viewElementOffset, info.viewElementWidth };} }; using UAVBase = TResourceViewBase>; class UAVWithCounter : public UAVBase { - private: - BufferViewInfo info; - Rc counter_; - public: UAVWithCounter( const tag_unordered_access_view<>::DESC1 *pDesc, D3D11Buffer *pResource, MTLD3D11Device *pDevice, BufferViewInfo const &info, Rc&& counter ) : - UAVBase(pDesc, pResource, pDevice), - info(info), - counter_(std::move(counter)) {} - - Rc buffer() final { return resource->buffer_; }; - Rc texture() final { return {}; }; - unsigned viewId() final { return info.viewKey;}; - BufferSlice bufferSlice() final { return {info.byteOffset, info.byteWidth, info.viewElementOffset, info.viewElementWidth };} - Rc counter() final { return counter_; }; + UAVBase(pDesc, pResource, pDevice) { + buffer_ = pResource->buffer_.ptr(); + view_id_ = info.viewKey; + slice_ = {info.byteOffset, info.byteWidth, info.viewElementOffset, info.viewElementWidth }; + counter_ = std::move(counter); + subset_ = ResourceSubsetState(info.byteOffset, info.byteWidth); + } }; public: @@ -118,18 +109,6 @@ class D3D11Buffer : public TResourceBase { return TResourceBase::QueryInterface(riid, ppvObject); } - Rc - buffer() final { - return buffer_; - }; - Rc - texture() final { - return {}; - }; - BufferSlice - bufferSlice() final { - return {0, desc.ByteWidth, 0, 0}; - } Rc staging(UINT Subresource) final { return nullptr; diff --git a/src/d3d11/d3d11_context_impl.cpp b/src/d3d11/d3d11_context_impl.cpp index fea482b7a..b251e3aad 100644 --- a/src/d3d11/d3d11_context_impl.cpp +++ b/src/d3d11/d3d11_context_impl.cpp @@ -1881,8 +1881,9 @@ template class MTLD3D11DeviceContextImplBase : p IASetIndexBuffer(ID3D11Buffer *pIndexBuffer, DXGI_FORMAT Format, UINT Offset) override { std::lock_guard lock(mutex); - if (auto expected = reinterpret_cast(pIndexBuffer)) { - state_.InputAssembler.IndexBuffer = expected; + auto pBuffer = reinterpret_cast(pIndexBuffer); + if (pBuffer && (pBuffer->bindFlags() & D3D11_BIND_INDEX_BUFFER) && ValidateIAHazard(pBuffer)) { + state_.InputAssembler.IndexBuffer = pBuffer; EmitST([buffer = state_.InputAssembler.IndexBuffer->buffer()](ArgumentEncodingContext &enc) mutable { enc.bindIndexBuffer(forward_rc(buffer)); }); @@ -2143,17 +2144,40 @@ template class MTLD3D11DeviceContextImplBase : p GetSamplers(StartSlot, NumSamplers, ppSamplers); } + bool + ValidateMultiSOTargets(UINT NumBuffers, ID3D11Buffer *const *ppSOTargets) { + for (unsigned i = 0; i < NumBuffers; i++) { + if (auto buffer = ppSOTargets[i]) { + for (unsigned j = 0; j < i; j++) { + if (buffer == ppSOTargets[j]) + return false; + } + } + } + return true; + } + + template + void + SOResolveSRVHazard(TView *pOutputView) { + // well, they do the same thing + OMResolveSRVHazard(pOutputView); + } + void STDMETHODCALLTYPE SOSetTargets(UINT NumBuffers, ID3D11Buffer *const *ppSOTargets, const UINT *pOffsets) override { std::lock_guard lock(mutex); + if (!ValidateMultiSOTargets(NumBuffers, ppSOTargets)) + return; + if (NumBuffers == 0) { NumBuffers = 4; // see msdn description of SOSetTargets } for (unsigned slot = 0; slot < NumBuffers; slot++) { - auto pBuffer = ppSOTargets ? ppSOTargets[slot] : nullptr; - if (pBuffer) { + auto pBuffer = ppSOTargets ? reinterpret_cast(ppSOTargets[slot]) : nullptr; + if (pBuffer && (pBuffer->bindFlags() & D3D11_BIND_STREAM_OUTPUT)) { bool replaced = false; auto &entry = state_.StreamOutput.Targets.bind(slot, {pBuffer}, replaced); if (!replaced) { @@ -2164,8 +2188,17 @@ template class MTLD3D11DeviceContextImplBase : p } continue; } - entry.Buffer = reinterpret_cast(pBuffer); + entry.Buffer = pBuffer; entry.Offset = pOffsets ? pOffsets[slot] : 0; + SOResolveSRVHazard(pBuffer); + ResolveIAHazard(pBuffer); + /** + * We should also unbind output of hazard, but + * - `ValidateMultiSOTargets` checks all SO hazard-free + * - UAV resource cannot be SO at the same time + * - DSV can't even be a buffer + * - RTV is questionable: we don't support buffer-backed RTV at the moment + */ } else { state_.StreamOutput.Targets.unbind(slot); } @@ -2374,7 +2407,57 @@ template class MTLD3D11DeviceContextImplBase : p ) override { std::lock_guard lock(mutex); - SetUnorderedAccessView(StartSlot, NumUAVs, ppUnorderedAccessViews, pUAVInitialCounts); + if (StartSlot + NumUAVs > D3D11_1_UAV_SLOT_COUNT) + return; + if (!ValidateMultiOutput(0, nullptr, NumUAVs, ppUnorderedAccessViews)) + return; + + auto &UAVs = state_.ComputeStageUAV.UAVs; + + for (const auto &[Slot, Bound] : UAVs) { + if (Slot >= StartSlot && Slot < (StartSlot + NumUAVs)) + continue; + for (uint32_t i = 0; i < NumUAVs; i++) { + auto pUAV = static_cast(ppUnorderedAccessViews[i]); + if (CheckOverlap(Bound.View.ptr(), pUAV) && UAVs.unbind(Slot)) { + EmitST([=](ArgumentEncodingContext &enc) { + enc.bindOutputBuffer(Slot, {}, 0, {}, {}); + }); + } + } + } + + for (unsigned Slot = StartSlot; Slot < StartSlot + NumUAVs; Slot++) { + auto pUAV = static_cast(ppUnorderedAccessViews[Slot - StartSlot]); + auto InitialCount = pUAVInitialCounts ? pUAVInitialCounts[Slot - StartSlot] : ~0u; + if (pUAV) { + bool replaced = false; + auto &entry = UAVs.bind(Slot, {pUAV}, replaced); + if (InitialCount != ~0u) { + UpdateUAVCounter(pUAV, InitialCount); + } + if (!replaced) + continue; + entry.View = pUAV; + if (auto buffer = pUAV->buffer()) { + EmitST([=, buffer = std::move(buffer), viewId = pUAV->viewId(), counter = pUAV->counter(), + slice = pUAV->bufferSlice()](ArgumentEncodingContext &enc) mutable { + enc.bindOutputBuffer(Slot, forward_rc(buffer), viewId, forward_rc(counter), slice); + }); + } else { + EmitST([=, texture = pUAV->texture(), viewId = pUAV->viewId()](ArgumentEncodingContext &enc) mutable { + enc.bindOutputTexture(Slot, forward_rc(texture), viewId); + }); + } + ResolveSRVHazard(pUAV); + } else { + if (UAVs.unbind(Slot)) { + EmitST([=](ArgumentEncodingContext &enc) { + enc.bindOutputBuffer(Slot, {}, 0, {}, {}); + }); + } + } + } } void @@ -2474,7 +2557,7 @@ template class MTLD3D11DeviceContextImplBase : p ValidateSetRenderTargets( UINT NumRTVs, ID3D11RenderTargetView *const *ppRenderTargetViews, ID3D11DepthStencilView *pDepthStencilView ) { - MTL_RENDER_PASS_ATTACHMENT_DESC *ref = nullptr; + const MTL_RENDER_PASS_ATTACHMENT_DESC *ref = nullptr; auto dsv = static_cast(pDepthStencilView); UINT render_target_array_length = 0, sample_count = 1, width = 0, height = 0; @@ -2525,6 +2608,134 @@ template class MTLD3D11DeviceContextImplBase : p return true; }; + bool + ValidateMultiOutput( + UINT NumRTVs, ID3D11RenderTargetView *const *ppRTVs, UINT NumUAVs, ID3D11UnorderedAccessView *const *ppUAVs + ) { + if (NumRTVs == D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) + NumRTVs = 0; + if (NumUAVs == D3D11_KEEP_UNORDERED_ACCESS_VIEWS) + NumUAVs = 0; + + for (unsigned i = 0; i < NumRTVs; i++) { + if (auto pRTV = static_cast(ppRTVs[i])) { + for (unsigned j = 0; j < i; j++) { + if (CheckOverlap(pRTV, static_cast(ppRTVs[j]))) + return false; + } + if (pRTV->bindFlags() & D3D11_BIND_UNORDERED_ACCESS) { + for (uint32_t j = 0; j < NumUAVs; j++) { + if (CheckOverlap(pRTV, static_cast(ppUAVs[j]))) + return false; + } + } + } + } + + for (unsigned i = 0; i < NumUAVs; i++) { + if (auto pUAV = static_cast(ppUAVs[i])) { + for (uint32_t j = 0; j < i; j++) { + if (CheckOverlap(pUAV, static_cast(ppUAVs[j]))) + return false; + } + } + } + + return true; + } + + /** + Resolve hazards when OM UAV is updated while RTV is kept + Unbound RTV if a subresource conflict + No DSV check as DSV^UAV = 1 + */ + bool + OMResolveRTVHazard(D3D11UnorderedAccessView *pUAV) { + if (!pUAV || (pUAV->bindFlags() & D3D11_BIND_RENDER_TARGET) == 0) + return false; + + bool hazard = false; + + for (unsigned slot = 0; slot < state_.OutputMerger.NumRTVs; slot++) { + if (CheckOverlap(state_.OutputMerger.RTVs[slot].ptr(), pUAV)) { + state_.OutputMerger.RTVs[slot] = nullptr; + hazard = true; + } + } + + return hazard; + } + + template + bool + ResolveSRVHazard(TViewOrBuffer *pViewOrBuffer) { + if (!pViewOrBuffer || (pViewOrBuffer->bindFlags() & D3D11_BIND_SHADER_RESOURCE) == 0) + return false; + + bool hazard = false; + + auto &SRVs = state_.ShaderStages[Stage].SRVs; + + for (auto it = SRVs.hazard_begin(); it != SRVs.hazard_end(); it++) { + const auto & [Slot, Bound] = *it; + if (CheckOverlap(Bound.SRV.ptr(), pViewOrBuffer)) { + if (SRVs.unbind(Slot)) { + EmitST([=](ArgumentEncodingContext& enc) { + enc.bindBuffer(Slot, {}, 0, {}); + }); + } + hazard = true; + } + } + + return hazard; + } + + template + bool + ResolveIAHazard(TViewOrBuffer *pViewOrBuffer) { + if (!pViewOrBuffer) + return false; + + bool hazard = false; + + if (pViewOrBuffer->bindFlags() & D3D11_BIND_INDEX_BUFFER) { + if (CheckOverlap(state_.InputAssembler.IndexBuffer.ptr(), pViewOrBuffer)) { + state_.InputAssembler.IndexBuffer = nullptr; + state_.InputAssembler.IndexBufferFormat = DXGI_FORMAT_UNKNOWN; + state_.InputAssembler.IndexBufferOffset = 0; + EmitST([](ArgumentEncodingContext &enc) { enc.bindIndexBuffer({}); }); + hazard = true; + } + } + + if (pViewOrBuffer->bindFlags() & D3D11_BIND_VERTEX_BUFFER) { + for (auto it = state_.InputAssembler.VertexBuffers.hazard_begin(); + it != state_.InputAssembler.VertexBuffers.hazard_end(); it++) { + const auto &[Slot, Bound] = *it; + if (CheckOverlap(Bound.Buffer.ptr(), pViewOrBuffer)) { + if (state_.InputAssembler.VertexBuffers.unbind(Slot)) { + EmitST([=](ArgumentEncodingContext &enc) { enc.bindVertexBuffer(Slot, 0, 0, {}); }); + } + hazard = true; + } + } + } + + return hazard; + } + + template + void + OMResolveSRVHazard(TView *pOutputView) { + // FIXME: should compute stage be resolved? + ResolveSRVHazard(pOutputView); + ResolveSRVHazard(pOutputView); + ResolveSRVHazard(pOutputView); + ResolveSRVHazard(pOutputView); + ResolveSRVHazard(pOutputView); + } + void STDMETHODCALLTYPE OMSetRenderTargetsAndUnorderedAccessViews( @@ -2534,6 +2745,8 @@ template class MTLD3D11DeviceContextImplBase : p ) override { std::lock_guard lock(mutex); + if (!ValidateMultiOutput(NumRTVs, ppRenderTargetViews, NumUAVs, ppUnorderedAccessViews)) + return; bool should_invalidate_pass = false; @@ -2551,6 +2764,7 @@ template class MTLD3D11DeviceContextImplBase : p continue; BoundRTVs[rtv_index] = rtv; should_invalidate_pass = true; + OMResolveSRVHazard(rtv); } else { if (BoundRTVs[rtv_index]) { should_invalidate_pass = true; @@ -2564,6 +2778,7 @@ template class MTLD3D11DeviceContextImplBase : p if (state_.OutputMerger.DSV.ptr() != dsv) { state_.OutputMerger.DSV = dsv; should_invalidate_pass = true; + OMResolveSRVHazard(dsv); } } else { if (state_.OutputMerger.DSV) { @@ -2574,7 +2789,53 @@ template class MTLD3D11DeviceContextImplBase : p } if (NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS) { - SetUnorderedAccessView(UAVStartSlot, NumUAVs, ppUnorderedAccessViews, pUAVInitialCounts); + auto MinUAV = NumUAVs ? UAVStartSlot : D3D11_1_UAV_SLOT_COUNT; + auto MaxUAV = NumUAVs ? UAVStartSlot + NumUAVs : 0u; + auto OldMinUAV = std::exchange(state_.OutputMerger.MinUAVBinding, MinUAV); + auto OldMaxUAV = std::exchange(state_.OutputMerger.MaxUAVBinding, MaxUAV); + auto &UAVs = state_.OutputMerger.UAVs; + for (unsigned Slot = std::min(MinUAV, OldMinUAV); Slot < std::max(MaxUAV, OldMaxUAV); Slot++) { + D3D11UnorderedAccessView *pUAV = nullptr; + UINT InitialCount = ~0u; + if (Slot >= UAVStartSlot && Slot < UAVStartSlot + NumUAVs) { + pUAV = static_cast(ppUnorderedAccessViews[Slot - UAVStartSlot]); + InitialCount = pUAVInitialCounts ? pUAVInitialCounts[Slot - UAVStartSlot] : ~0u; + } + if (pUAV) { + bool replaced = false; + auto &entry = UAVs.bind(Slot, {pUAV}, replaced); + if (InitialCount != ~0u) { + UpdateUAVCounter(pUAV, InitialCount); + } + if (!replaced) + continue; + entry.View = pUAV; + if (auto buffer = pUAV->buffer()) { + EmitST([=, buffer = std::move(buffer), viewId = pUAV->viewId(), counter = pUAV->counter(), + slice = pUAV->bufferSlice()](ArgumentEncodingContext &enc) mutable { + enc.bindOutputBuffer(Slot, forward_rc(buffer), viewId, forward_rc(counter), slice); + }); + } else { + EmitST([=, texture = pUAV->texture(), viewId = pUAV->viewId()](ArgumentEncodingContext &enc) mutable { + enc.bindOutputTexture(Slot, forward_rc(texture), viewId); + }); + } + + OMResolveSRVHazard(pUAV); + ResolveIAHazard(pUAV); + } else { + if (UAVs.unbind(Slot)) { + EmitST([=](ArgumentEncodingContext &enc) { + enc.bindOutputBuffer(Slot, {}, 0, {}, {}); + }); + } + } + + // No check on SO as SO^UAV = 1 + + if (NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) + should_invalidate_pass |= OMResolveRTVHazard(pUAV); + } } if (should_invalidate_pass) { @@ -3172,6 +3433,55 @@ template class MTLD3D11DeviceContextImplBase : p } } + template + bool + ValidateSRVHazard(D3D11ShaderResourceView *pView) { + if (pView->hazardsFree()) + return true; + + /** + At the moment, Graphics and Compute handles hazard tracking separately + This might be not enough per D3D11 spec + */ + + if constexpr (Stage == PipelineStage::Compute) { + for (const auto &[Slot, Bound] : state_.ComputeStageUAV.UAVs) { + if (CheckOverlap(Bound.View.ptr(), pView)) + return false; + } + return true; + } else { + // RTV + for (unsigned Slot = 0; Slot < state_.OutputMerger.NumRTVs; Slot++) { + if (state_.OutputMerger.RTVs[Slot] && CheckOverlap(state_.OutputMerger.RTVs[Slot].ptr(), pView)) + return false; + } + + // DSV + if (state_.OutputMerger.DSV && CheckOverlap(state_.OutputMerger.DSV.ptr(), pView)) + return false; + + if (pView->bindFlags() & D3D11_BIND_UNORDERED_ACCESS) { + // UAV + for (unsigned Slot = state_.OutputMerger.NumRTVs; Slot < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; Slot++) { + if (state_.OutputMerger.UAVs.test_bound(Slot) && + CheckOverlap(state_.OutputMerger.UAVs[Slot].View.ptr(), pView)) { + return false; + } + } + } else if (pView->bindFlags() & D3D11_BIND_STREAM_OUTPUT) { + // SO + for (unsigned Slot = 0; Slot < 4; Slot++) { + if (state_.StreamOutput.Targets.test_bound(Slot) && + CheckOverlap(state_.StreamOutput.Targets[Slot].Buffer.ptr(), pView)) + return false; + } + } + + return true; + } + } + template void SetShaderResource(UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView *const *ppShaderResourceViews) { @@ -3181,9 +3491,9 @@ template class MTLD3D11DeviceContextImplBase : p auto &ShaderStage = state_.ShaderStages[Stage]; for (unsigned slot = StartSlot; slot < StartSlot + NumViews; slot++) { auto pView = static_cast(ppShaderResourceViews[slot - StartSlot]); - if (pView) { + if (pView && ValidateSRVHazard(pView)) { bool replaced = false; - auto &entry = ShaderStage.SRVs.bind(slot, {pView}, replaced); + auto &entry = ShaderStage.SRVs.bind(slot, {pView}, replaced, !pView->hazardsFree()); if (!replaced) continue; entry.SRV = pView; @@ -3285,72 +3595,42 @@ template class MTLD3D11DeviceContextImplBase : p }); } - template - void - SetUnorderedAccessView( - UINT StartSlot, UINT NumUAVs, ID3D11UnorderedAccessView *const *ppUnorderedAccessViews, - const UINT *pUAVInitialCounts - ) { - auto &binding_set = Stage == PipelineStage::Compute ? state_.ComputeStageUAV.UAVs : state_.OutputMerger.UAVs; - - // std::erase_if(state_.ComputeStageUAV.UAVs, [&](const auto &item) -> bool - // { - // auto &[slot, bound_uav] = item; - // if (slot < StartSlot || slot >= (StartSlot + NumUAVs)) - // return false; - // for (auto i = 0u; i < NumUAVs; i++) { - // if (auto uav = static_cast( - // ppUnorderedAccessViews[i])) { - // // if (bound_uav.View->GetViewRange().CheckOverlap( - // // uav->GetViewRange())) { - // // return true; - // // } - // } - // } - // return false; - // }); - - for (unsigned slot = StartSlot; slot < StartSlot + NumUAVs; slot++) { - auto pUAV = static_cast(ppUnorderedAccessViews[slot - StartSlot]); - auto InitialCount = pUAVInitialCounts ? pUAVInitialCounts[slot - StartSlot] : ~0u; - if (pUAV) { - bool replaced = false; - auto &entry = binding_set.bind(slot, {pUAV}, replaced); - if (InitialCount != ~0u) { - UpdateUAVCounter(pUAV, InitialCount); - } - if (!replaced) { - continue; - } - entry.View = pUAV; - if (auto buffer = pUAV->buffer()) { - EmitST([=, buffer = std::move(buffer), viewId = pUAV->viewId(), counter = pUAV->counter(), - slice = pUAV->bufferSlice()](ArgumentEncodingContext &enc) mutable { - enc.bindOutputBuffer(slot, forward_rc(buffer), viewId, forward_rc(counter), slice); - }); - } else { - EmitST([=, texture = pUAV->texture(), viewId = pUAV->viewId()](ArgumentEncodingContext &enc) mutable { - enc.bindOutputTexture(slot, forward_rc(texture), viewId); - }); - } - // FIXME: resolve srv hazard: unbind any cs srv that share the resource - // std::erase_if(state_.ShaderStages[5].SRVs, - // [&](const auto &item) -> bool { - // // auto &[slot, bound_srv] = item; - // // if srv conflict with uav, return true - // return false; - // }); - } else { - if (binding_set.unbind(slot)) { - EmitST([=](ArgumentEncodingContext &enc) { enc.bindOutputBuffer(slot, {}, 0, {}, {}); }); +#pragma endregion + +#pragma region InputAssembler + + bool + ValidateIAHazard(D3D11ResourceCommon *pBuffer) { + if (pBuffer->hazardsFree()) + return true; + + /** + At the moment, Graphics and Compute handles hazard tracking separately + This might be not enough per D3D11 spec + + RTV and DSV unchecked because they can't be buffer + */ + + if (pBuffer->bindFlags() & D3D11_BIND_UNORDERED_ACCESS) { + // UAV + for (unsigned Slot = state_.OutputMerger.MinUAVBinding; Slot < state_.OutputMerger.MaxUAVBinding; Slot++) { + if (state_.OutputMerger.UAVs.test_bound(Slot) && + CheckOverlap(state_.OutputMerger.UAVs[Slot].View.ptr(), pBuffer)) { + return false; } } + } else if (pBuffer->bindFlags() & D3D11_BIND_STREAM_OUTPUT) { + // SO + for (unsigned Slot = 0; Slot < 4; Slot++) { + if (state_.StreamOutput.Targets.test_bound(Slot) && + CheckOverlap(state_.StreamOutput.Targets[Slot].Buffer.ptr(), pBuffer)) + return false; + } } - } -#pragma endregion + return true; + } -#pragma region InputAssembler void SetVertexBuffers( UINT StartSlot, UINT NumBuffers, ID3D11Buffer *const *ppVertexBuffers, const UINT *pStrides, const UINT *pOffsets @@ -3359,10 +3639,10 @@ template class MTLD3D11DeviceContextImplBase : p auto &VertexBuffers = state_.InputAssembler.VertexBuffers; for (unsigned slot = StartSlot; slot < StartSlot + NumBuffers; slot++) { - auto pVertexBuffer = ppVertexBuffers[slot - StartSlot]; - if (pVertexBuffer) { + auto pVertexBuffer = reinterpret_cast(ppVertexBuffers[slot - StartSlot]); + if (pVertexBuffer && (pVertexBuffer->bindFlags() & D3D11_BIND_VERTEX_BUFFER) && ValidateIAHazard(pVertexBuffer)) { bool replaced = false; - auto &entry = VertexBuffers.bind(slot, {pVertexBuffer}, replaced); + auto &entry = VertexBuffers.bind(slot, {pVertexBuffer}, replaced, !pVertexBuffer->hazardsFree()); if (!replaced) { if (pStrides && pStrides[slot - StartSlot] != entry.Stride) { VertexBuffers.set_dirty(slot); @@ -3390,7 +3670,7 @@ template class MTLD3D11DeviceContextImplBase : p ERR("SetVertexBuffers: offset is null"); entry.Stride = 0; } - entry.Buffer = reinterpret_cast(pVertexBuffer); + entry.Buffer = pVertexBuffer; EmitST([=, buffer = entry.Buffer->buffer(), offset = entry.Offset, stride = entry.Stride](ArgumentEncodingContext &enc) mutable { enc.bindVertexBuffer(slot, offset, stride, forward_rc(buffer)); diff --git a/src/d3d11/d3d11_context_state.hpp b/src/d3d11/d3d11_context_state.hpp index f5314b049..7cb26ecdc 100644 --- a/src/d3d11/d3d11_context_state.hpp +++ b/src/d3d11/d3d11_context_state.hpp @@ -111,6 +111,8 @@ struct D3D11OutputMergerStageState { UINT NumRTVs; UAVBindingSet UAVs; + UINT MinUAVBinding = D3D11_1_UAV_SLOT_COUNT; + UINT MaxUAVBinding = 0; IMTLD3D11DepthStencilState* DepthStencilState; UINT StencilRef; diff --git a/src/d3d11/d3d11_resource.hpp b/src/d3d11/d3d11_resource.hpp index 27b62a438..9a94e41dc 100644 --- a/src/d3d11/d3d11_resource.hpp +++ b/src/d3d11/d3d11_resource.hpp @@ -8,7 +8,6 @@ #include "com/com_guid.hpp" #include "d3d11_view.hpp" #include "dxgi_resource.hpp" -#include "dxmt_resource_binding.hpp" #include "log/log.hpp" #include "../d3d10/d3d10_buffer.hpp" #include "../d3d10/d3d10_texture.hpp" @@ -130,13 +129,29 @@ struct D3D11ResourceCommon : ID3D11Resource { virtual HRESULT CreateSharedHandle(const SECURITY_ATTRIBUTES *Attributes, DWORD Access, const WCHAR *pName, HANDLE *pNTHandle) = 0; - virtual Rc buffer() = 0; - virtual BufferSlice bufferSlice() = 0; - virtual Rc texture() = 0; virtual Rc staging(UINT Subresource) = 0; virtual Rc dynamicBuffer(UINT *pBufferLength, UINT *pBindFlags) = 0; virtual Rc dynamicLinearTexture(UINT *pBytesPerRow, UINT *pBytesPerImage) = 0; virtual Rc dynamicTexture(UINT Subresource, UINT *pBytesPerRow, UINT *pBytesPerImage) = 0; + + Rc buffer_{}; + Rc texture_{}; + uint32_t bind_flags_{}; + + const Rc &buffer() const { + return buffer_; + } + const Rc &texture() const { + return texture_; + } + uint32_t bindFlags() const { + return bind_flags_; + } + bool + hazardsFree() const { + return (bind_flags_ & (D3D11_BIND_STREAM_OUTPUT | D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_RENDER_TARGET | + D3D11_BIND_DEPTH_STENCIL)) == 0; + } }; inline Rc @@ -164,12 +179,14 @@ GetTexture(ID3D11Resource *pResource) { template class TResourceBase : public MTLD3D11DeviceChild { public: - TResourceBase(const tag::DESC1 &desc, MTLD3D11Device *device) - : MTLD3D11DeviceChild( - device), - desc(desc), - dxgi_resource(new MTLDXGIResource>(this)), - d3d10(reinterpret_cast(this), device->GetImmediateContextPrivate()) {} + TResourceBase(const tag::DESC1 &desc, MTLD3D11Device *device) : + MTLD3D11DeviceChild(device), + desc(desc), + dxgi_resource(new MTLDXGIResource>(this)), + d3d10(reinterpret_cast(this), device->GetImmediateContextPrivate()) { + // D3D11ResourceCommonß::bind_flags_ + this->bind_flags_ = desc.BindFlags; + } template HRESULT ResolveBase(REFIID riid, void **ppvObject) { return E_NOINTERFACE; @@ -361,10 +378,12 @@ class TResourceViewBase TResourceViewBase(const tag::DESC1 *pDesc, tag::RESOURCE_IMPL *pResource, MTLD3D11Device *device) : MTLD3D11DeviceChild(device), - d3d10(static_cast(this)), resource(pResource) { + d3d10(static_cast(this)) { if (pDesc) { desc = *pDesc; } + this->resource_ = pResource; + this->bind_flags_ = this->resource_->bind_flags_; } template HRESULT ResolveBase(REFIID riid, void **ppvObject) { @@ -421,20 +440,12 @@ class TResourceViewBase void STDMETHODCALLTYPE GetDesc1(tag::DESC1 *pDesc) /* override / final */ { *pDesc = desc; } void STDMETHODCALLTYPE GetResource(tag::RESOURCE **ppResource) final { - resource->QueryInterface(IID_PPV_ARGS(ppResource)); + this->resource_->QueryInterface(IID_PPV_ARGS(ppResource)); } - virtual ULONG64 GetUnderlyingResourceId() { return (ULONG64)resource.ptr(); }; - - virtual dxmt::ResourceSubset GetViewRange() { return ResourceSubset(desc); }; - protected: tag::DESC1 desc; tag::D3D10_IMPL d3d10; - /** - strong ref to resource - */ - Com resource; }; #pragma region Resource Factory diff --git a/src/d3d11/d3d11_resource_staging.cpp b/src/d3d11/d3d11_resource_staging.cpp index 322d47756..5ba6cb37a 100644 --- a/src/d3d11/d3d11_resource_staging.cpp +++ b/src/d3d11/d3d11_resource_staging.cpp @@ -20,18 +20,6 @@ class StagingBuffer : public TResourceBase { void OnSetDebugObjectName(LPCSTR Name) override { } - Rc - buffer() final { - return {}; - }; - Rc - texture() final { - return {}; - }; - BufferSlice - bufferSlice() final { - return {}; - } Rc staging(UINT Subresource) final { assert(Subresource == 0); @@ -87,18 +75,6 @@ class StagingTexture : public TResourceBase { } } - Rc - buffer() final { - return {}; - }; - Rc - texture() final { - return {}; - }; - BufferSlice - bufferSlice() final { - return {}; - } Rc staging(UINT Subresource) final { return subresources.at(Subresource); diff --git a/src/d3d11/d3d11_texture_device.cpp b/src/d3d11/d3d11_texture_device.cpp index d52e3da87..0eaa1c903 100644 --- a/src/d3d11/d3d11_texture_device.cpp +++ b/src/d3d11/d3d11_texture_device.cpp @@ -15,7 +15,6 @@ namespace dxmt { template class DeviceTexture : public TResourceBase { private: - Rc underlying_texture_; Rc renamable_; float min_lod = 0.0; D3DKMT_HANDLE local_kmt_ = 0; @@ -24,139 +23,108 @@ class DeviceTexture : public TResourceBase { using SRVBase = TResourceViewBase>>; class TextureSRV : public SRVBase { - private: - TextureViewKey view_key_; - public: - TextureSRV(TextureViewKey view_key, + TextureSRV(const TextureViewDescriptor &descriptor, const tag_shader_resource_view<>::DESC1 *pDesc, DeviceTexture *pResource, MTLD3D11Device *pDevice) - : SRVBase(pDesc, pResource, pDevice), view_key_(view_key) {} + : SRVBase(pDesc, pResource, pDevice) { + this->texture_ = pResource->texture_.ptr(); + this->view_id_ = this->texture_->createView(descriptor); + this->subset_ = ResourceSubsetState( + &descriptor, + this->texture_->miplevelCount(), + this->texture_->arrayLength() + ); + } - Rc buffer() final { return {}; }; - Rc texture() final { return this->resource->underlying_texture_; }; - unsigned viewId() final { return view_key_;}; - BufferSlice bufferSlice() final { return {};} }; using UAVBase = TResourceViewBase>>; class TextureUAV : public UAVBase { - private: - TextureViewKey view_key_; - public: - TextureUAV(TextureViewKey view_key, + TextureUAV(const TextureViewDescriptor &descriptor, const tag_unordered_access_view<>::DESC1 *pDesc, DeviceTexture *pResource, MTLD3D11Device *pDevice) - : UAVBase(pDesc, pResource, pDevice), view_key_(view_key){} - - Rc buffer() final { return {}; }; - Rc texture() final { return this->resource->underlying_texture_; }; - unsigned viewId() final { return view_key_;}; - BufferSlice bufferSlice() final { return {};} - Rc counter() final { return {}; }; + : UAVBase(pDesc, pResource, pDevice) { + this->texture_ = pResource->texture_.ptr(); + this->view_id_ = this->texture_->createView(descriptor); + this->subset_ = ResourceSubsetState( + &descriptor, + this->texture_->miplevelCount(), + this->texture_->arrayLength() + ); + } }; using RTVBase = TResourceViewBase>>; class TextureRTV : public RTVBase { - private: - TextureViewKey view_key_; - WMTPixelFormat view_format_; - MTL_RENDER_PASS_ATTACHMENT_DESC attachment_desc; - public: TextureRTV( - TextureViewKey view_key, WMTPixelFormat view_format, const tag_render_target_view<>::DESC1 *pDesc, + const TextureViewDescriptor &descriptor, WMTPixelFormat view_format, const tag_render_target_view<>::DESC1 *pDesc, DeviceTexture *pResource, MTLD3D11Device *pDevice, const MTL_RENDER_PASS_ATTACHMENT_DESC &mtl_rtv_desc ) : - RTVBase(pDesc, pResource, pDevice), - view_key_(view_key), - view_format_(view_format), - attachment_desc(mtl_rtv_desc) {} - - WMTPixelFormat - pixelFormat() final { - return view_format_; - } - - MTL_RENDER_PASS_ATTACHMENT_DESC &description() final { - return attachment_desc; - }; - - Rc texture() final { - return this->resource->underlying_texture_; - } - - unsigned viewId() final { - return view_key_; + RTVBase(pDesc, pResource, pDevice) { + this->texture_ = pResource->texture_.ptr(); + this->view_id_ = this->texture_->createView(descriptor); + this->format_ = view_format; + this->pass_desc_ = mtl_rtv_desc; + this->subset_ = ResourceSubsetState( + &descriptor, + this->texture_->miplevelCount(), + this->texture_->arrayLength() + ); } }; using DSVBase = TResourceViewBase>>; class TextureDSV : public DSVBase { - private: - TextureViewKey view_key_; - WMTPixelFormat view_format_; - MTL_RENDER_PASS_ATTACHMENT_DESC attachment_desc; - public: TextureDSV( - TextureViewKey view_key, WMTPixelFormat view_format, const tag_depth_stencil_view<>::DESC1 *pDesc, + const TextureViewDescriptor &descriptor, WMTPixelFormat view_format, const tag_depth_stencil_view<>::DESC1 *pDesc, DeviceTexture *pResource, MTLD3D11Device *pDevice, const MTL_RENDER_PASS_ATTACHMENT_DESC &attachment_desc ) : - DSVBase(pDesc, pResource, pDevice), - view_key_(view_key), - view_format_(view_format), - attachment_desc(attachment_desc) {} - - WMTPixelFormat - pixelFormat() final { - return view_format_; - } - - MTL_RENDER_PASS_ATTACHMENT_DESC &description() final { - return attachment_desc; - }; - - UINT readonlyFlags() final { - return this->desc.Flags; - }; - - Rc texture() final { - return this->resource->underlying_texture_; - } - - unsigned viewId() final { - return view_key_; - } - - dxmt::Rc renamable() final { - return this->resource->renamable_; + DSVBase(pDesc, pResource, pDevice) { + this->texture_ = pResource->texture_.ptr(); + this->view_id_ = this->texture_->createView(descriptor); + this->format_ = view_format; + this->pass_desc_ = attachment_desc; + this->renamable_ = pResource->renamable_.ptr(); + this->readonly_flags_ = this->desc.Flags & 0b11; + this->subset_ = ResourceSubsetState( + &descriptor, + this->texture_->miplevelCount(), + this->texture_->arrayLength(), + this->readonly_flags_ + ); } }; public: DeviceTexture(const tag_texture::DESC1 *pDesc, Rc &&u_texture, MTLD3D11Device *pDevice) : - TResourceBase(*pDesc, pDevice), - underlying_texture_(std::move(u_texture)) {} + TResourceBase(*pDesc, pDevice) { + this->texture_ = std::move(u_texture); + } DeviceTexture( const tag_texture::DESC1 *pDesc, Rc &&u_texture, Rc &&renamable, MTLD3D11Device *pDevice ) : TResourceBase(*pDesc, pDevice), - underlying_texture_(std::move(u_texture)), - renamable_(std::move(renamable)) {} + renamable_(std::move(renamable)) { + this->texture_ = std::move(u_texture); + } DeviceTexture( const tag_texture::DESC1 *pDesc, Rc &&u_texture, D3DKMT_HANDLE localHandle, D3DKMT_HANDLE globalHandle, MTLD3D11Device *pDevice ) : TResourceBase(*pDesc, pDevice), - underlying_texture_(std::move(u_texture)), local_kmt_(localHandle), global_kmt_(globalHandle) {} + local_kmt_(localHandle), global_kmt_(globalHandle) { + this->texture_ = std::move(u_texture); + } ~DeviceTexture() { if (local_kmt_) { @@ -167,9 +135,6 @@ class DeviceTexture : public TResourceBase { } } - Rc buffer() final { return {}; }; - Rc texture() final { return this->underlying_texture_; }; - BufferSlice bufferSlice() final { return {};} Rc staging(UINT) final { return nullptr; } Rc dynamicBuffer(UINT*, UINT*) final { return {}; } Rc dynamicLinearTexture(UINT*, UINT*) final { return {}; }; @@ -191,7 +156,7 @@ class DeviceTexture : public TResourceBase { } MTL_RENDER_PASS_ATTACHMENT_DESC attachment_desc; if (FAILED(InitializeAndNormalizeViewDescriptor( - this->m_parent, this->desc.MipLevels, arraySize, this->underlying_texture_.ptr(), finalDesc, + this->m_parent, this->desc.MipLevels, arraySize, this->texture_.ptr(), finalDesc, attachment_desc, descriptor ))) { return E_FAIL; @@ -199,8 +164,7 @@ class DeviceTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = underlying_texture_->createView(descriptor); - *ppView = ref(new TextureRTV(key, descriptor.format, &finalDesc, this, this->m_parent, attachment_desc)); + *ppView = ref(new TextureRTV(descriptor, descriptor.format, &finalDesc, this, this->m_parent, attachment_desc)); return S_OK; }; @@ -220,7 +184,7 @@ class DeviceTexture : public TResourceBase { } MTL_RENDER_PASS_ATTACHMENT_DESC attachment_desc; if (FAILED(InitializeAndNormalizeViewDescriptor( - this->m_parent, this->desc.MipLevels, arraySize, this->underlying_texture_.ptr(), finalDesc, + this->m_parent, this->desc.MipLevels, arraySize, this->texture_.ptr(), finalDesc, attachment_desc, descriptor ))) { return E_FAIL; @@ -228,8 +192,7 @@ class DeviceTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = underlying_texture_->createView(descriptor); - *ppView = ref(new TextureDSV(key, descriptor.format, &finalDesc, this, this->m_parent, attachment_desc)); + *ppView = ref(new TextureDSV(descriptor, descriptor.format, &finalDesc, this, this->m_parent, attachment_desc)); return S_OK; }; @@ -251,7 +214,7 @@ class DeviceTexture : public TResourceBase { arraySize = this->desc.ArraySize; } if (FAILED(InitializeAndNormalizeViewDescriptor( - this->m_parent, this->desc.MipLevels, arraySize, this->underlying_texture_.ptr(), finalDesc, descriptor + this->m_parent, this->desc.MipLevels, arraySize, this->texture_.ptr(), finalDesc, descriptor ))) { ERR("DeviceTexture: Failed to create texture SRV"); return E_FAIL; @@ -259,8 +222,7 @@ class DeviceTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = underlying_texture_->createView(descriptor); - *ppView = ref(new TextureSRV(key, &finalDesc, this, this->m_parent)); + *ppView = ref(new TextureSRV(descriptor, &finalDesc, this, this->m_parent)); return S_OK; }; @@ -281,7 +243,7 @@ class DeviceTexture : public TResourceBase { arraySize = this->desc.ArraySize; } if (FAILED(InitializeAndNormalizeViewDescriptor( - this->m_parent, this->desc.MipLevels, arraySize, this->underlying_texture_.ptr(), finalDesc, descriptor + this->m_parent, this->desc.MipLevels, arraySize, this->texture_.ptr(), finalDesc, descriptor ))) { ERR("DeviceTexture: Failed to create texture UAV"); return E_FAIL; @@ -289,8 +251,7 @@ class DeviceTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = underlying_texture_->createView(descriptor); - *ppView = ref(new TextureUAV(key, &finalDesc, this, this->m_parent)); + *ppView = ref(new TextureUAV(descriptor, &finalDesc, this, this->m_parent)); return S_OK; }; diff --git a/src/d3d11/d3d11_texture_dynamic.cpp b/src/d3d11/d3d11_texture_dynamic.cpp index ba42afa36..abc3d57d7 100644 --- a/src/d3d11/d3d11_texture_dynamic.cpp +++ b/src/d3d11/d3d11_texture_dynamic.cpp @@ -22,37 +22,34 @@ struct Subresource { template class DynamicTexture : public TResourceBase { private: - Rc underlying_texture_; std::vector subresources_; float min_lod = 0.0; using SRVBase = TResourceViewBase>>; class TextureSRV : public SRVBase { - private: - TextureViewKey view_key_; - public: - TextureSRV(TextureViewKey view_key, + TextureSRV(const TextureViewDescriptor &descriptor, const tag_shader_resource_view<>::DESC1 *pDesc, DynamicTexture *pResource, MTLD3D11Device *pDevice) - : SRVBase(pDesc, pResource, pDevice), view_key_(view_key) {} + : SRVBase(pDesc, pResource, pDevice) { + this->texture_ = pResource->texture_.ptr(); + this->view_id_ = this->texture_->createView(descriptor); + this->subset_ = ResourceSubsetState( + &descriptor, + this->texture_->miplevelCount(), + this->texture_->arrayLength() + ); + } - Rc buffer() final { return {}; }; - Rc texture() final { return this->resource->underlying_texture_; }; - unsigned viewId() final { return view_key_;}; - BufferSlice bufferSlice() final { return {};} }; public: DynamicTexture(const tag_texture::DESC1 *pDesc, Rc &&u_texture, MTLD3D11Device *pDevice, std::vector && subresources) : TResourceBase(*pDesc, pDevice), - underlying_texture_(std::move(u_texture)), - subresources_(std::move(subresources)) {} - - Rc buffer() final { return {}; }; - Rc texture() final { return this->underlying_texture_; }; - BufferSlice bufferSlice() final { return {};} + subresources_(std::move(subresources)) { + this->texture_ = std::move(u_texture); + } Rc staging(UINT) final { return nullptr; } Rc dynamicBuffer(UINT*, UINT*) final { return {}; } Rc dynamicLinearTexture(UINT*, UINT*) final { return {}; }; @@ -85,7 +82,7 @@ class DynamicTexture : public TResourceBase { arraySize = this->desc.ArraySize; } if (FAILED(InitializeAndNormalizeViewDescriptor( - this->m_parent, this->desc.MipLevels, arraySize, this->underlying_texture_.ptr(), finalDesc, descriptor + this->m_parent, this->desc.MipLevels, arraySize, this->texture_.ptr(), finalDesc, descriptor ))) { ERR("DynamicTexture: Failed to create texture SRV"); return E_FAIL; @@ -93,8 +90,7 @@ class DynamicTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = underlying_texture_->createView(descriptor); - *ppView = ref(new TextureSRV(key, &finalDesc, this, this->m_parent)); + *ppView = ref(new TextureSRV(descriptor, &finalDesc, this, this->m_parent)); return S_OK; }; diff --git a/src/d3d11/d3d11_texture_linear.cpp b/src/d3d11/d3d11_texture_linear.cpp index 1de2d4b7f..8756b013a 100644 --- a/src/d3d11/d3d11_texture_linear.cpp +++ b/src/d3d11/d3d11_texture_linear.cpp @@ -14,7 +14,6 @@ namespace dxmt { template class TDynamicLinearTexture : public TResourceBase { private: - Rc texture_; Rc dynamic_; size_t bytes_per_image_; size_t bytes_per_row_; @@ -22,20 +21,20 @@ class TDynamicLinearTexture : public TResourceBase { using SRVBase = TResourceViewBase>; class SRV : public SRVBase { - TextureViewKey view_key; - public: SRV(const tag_shader_resource_view<>::DESC1 *pDesc, TDynamicLinearTexture *pResource, MTLD3D11Device *pDevice, - TextureViewKey view_key) : - SRVBase(pDesc, pResource, pDevice), - view_key(view_key) {} + const TextureViewDescriptor &descriptor) : + SRVBase(pDesc, pResource, pDevice) { + this->texture_ = pResource->texture_.ptr(); + this->view_id_ = this->texture_->createView(descriptor); + this->subset_ = ResourceSubsetState( + &descriptor, + this->texture_->miplevelCount(), + this->texture_->arrayLength() + ); + } ~SRV() {} - - Rc buffer() final { return {}; }; - Rc texture() final { return this->resource->texture_; }; - unsigned viewId() final { return view_key;}; - BufferSlice bufferSlice() final { return {};} }; public: @@ -46,7 +45,7 @@ TDynamicLinearTexture( TResourceBase(*pDesc, device), bytes_per_image_(bytes_per_image), bytes_per_row_(bytes_per_row) { - texture_ = new Texture(bytes_per_image, bytes_per_row, descriptor, device->GetMTLDevice()); + this->texture_ = new Texture(bytes_per_image, bytes_per_row, descriptor, device->GetMTLDevice()); Flags flags; if (!this->m_parent->IsTraced() && pDesc->Usage == D3D11_USAGE_DYNAMIC) flags.set(TextureAllocationFlag::CpuWriteCombined); @@ -55,13 +54,13 @@ TDynamicLinearTexture( flags.set(TextureAllocationFlag::GpuReadonly); if (pDesc->Usage != D3D11_USAGE_DYNAMIC) flags.set(TextureAllocationFlag::GpuManaged); - auto allocation = texture_->allocate(flags); - auto _ = texture_->rename(Rc(allocation)); + auto allocation = this->texture_->allocate(flags); + auto _ = this->texture_->rename(Rc(allocation)); D3D11_ASSERT(_.ptr() == nullptr); if (pInitialData) { if (pInitialData->SysMemPitch != bytes_per_row_) { - for (unsigned row = 0; row < texture_->height(); row++) { + for (unsigned row = 0; row < this->texture_->height(); row++) { memcpy( ptr_add(allocation->mappedMemory, row * bytes_per_row_), ptr_add(pInitialData->pSysMem, row * pInitialData->SysMemPitch), @@ -71,12 +70,8 @@ TDynamicLinearTexture( memcpy(allocation->mappedMemory, pInitialData->pSysMem, bytes_per_image); } } - dynamic_ = new DynamicLinearTexture(texture_.ptr(), flags); + dynamic_ = new DynamicLinearTexture(this->texture_.ptr(), flags); } - - Rc buffer() final { return {}; }; - Rc texture() final { return this->texture_; }; - BufferSlice bufferSlice() final { return {};} Rc staging(UINT) final { return nullptr; } Rc dynamicBuffer(UINT*, UINT*) final { return {}; }; Rc dynamicLinearTexture(UINT* pBytesPerRow, UINT* pBytesPerImage) final { @@ -115,16 +110,15 @@ HRESULT STDMETHODCALLTYPE TDynamicLinearTexture::CreateShaderRes return E_FAIL; } - auto view_key = texture_->createView( + auto srv = ref(new SRV( + &finalDesc, this, this->m_parent, {.format = format.PixelFormat, .type = WMTTextureType2D, .firstMiplevel = 0, .miplevelCount = 1, .firstArraySlice = 0, .arraySize = 1} - ); - - auto srv = ref(new SRV(&finalDesc, this, this->m_parent, view_key)); + )); *ppView = srv; return S_OK; @@ -154,16 +148,15 @@ HRESULT STDMETHODCALLTYPE TDynamicLinearTexture::CreateShaderRes return E_FAIL; } - auto view_key = texture_->createView( + auto srv = ref(new SRV( + &finalDesc, this, this->m_parent, {.format = format.PixelFormat, .type = WMTTextureType2D, // since all 1d texture is implemented as 1-row 2d texture .firstMiplevel = 0, .miplevelCount = 1, .firstArraySlice = 0, .arraySize = 1} - ); - - auto srv = ref(new SRV(&finalDesc, this, this->m_parent, view_key)); + )); *ppView = srv; return S_OK; diff --git a/src/d3d11/d3d11_view.hpp b/src/d3d11/d3d11_view.hpp index 5ff154721..41b57c234 100644 --- a/src/d3d11/d3d11_view.hpp +++ b/src/d3d11/d3d11_view.hpp @@ -1,7 +1,8 @@ #pragma once -#include "d3d11_1.h" +#include "com/com_pointer.hpp" +#include "d3d11_3.h" #include "dxmt_buffer.hpp" -#include "dxmt_resource_binding.hpp" +#include "dxmt_subresource.hpp" #include "dxmt_texture.hpp" struct MTL_RENDER_PASS_ATTACHMENT_DESC { @@ -14,35 +15,169 @@ struct MTL_RENDER_PASS_ATTACHMENT_DESC { namespace dxmt { +struct D3D11ResourceCommon; + struct D3D11ShaderResourceView : ID3D11ShaderResourceView1 { - virtual Rc buffer() = 0; - virtual BufferSlice bufferSlice() = 0; - virtual Rc texture() = 0; - virtual unsigned viewId() = 0; + Com resource_{}; + Buffer *buffer_{}; + BufferSlice slice_{}; + Texture *texture_{}; + unsigned view_id_{}; + ResourceSubsetState subset_{}; + uint32_t bind_flags_{}; + + Rc + buffer() const { + return buffer_; + }; + BufferSlice + bufferSlice() const { + return slice_; + }; + Rc + texture() const { + return texture_; + }; + unsigned + viewId() const { + return view_id_; + }; + uint32_t bindFlags() const { + return bind_flags_; + } + bool + hazardsFree() const { + return (bind_flags_ & (D3D11_BIND_STREAM_OUTPUT | D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_RENDER_TARGET | + D3D11_BIND_DEPTH_STENCIL)) == 0; + } }; struct D3D11UnorderedAccessView : ID3D11UnorderedAccessView1 { - virtual Rc buffer() = 0; - virtual BufferSlice bufferSlice() = 0; - virtual Rc texture() = 0; - virtual unsigned viewId() = 0; - virtual Rc counter() = 0; + Com resource_{}; + Buffer *buffer_{}; + BufferSlice slice_{}; + Texture *texture_{}; + unsigned view_id_{}; + Rc counter_; + ResourceSubsetState subset_{}; + uint32_t bind_flags_{}; + + Rc + buffer() const { + return buffer_; + }; + BufferSlice + bufferSlice() const { + return slice_; + }; + Rc + texture() const { + return texture_; + }; + unsigned + viewId() const { + return view_id_; + }; + Rc + counter() const { + return counter_; + }; + uint32_t bindFlags() const { + return bind_flags_; + } }; struct D3D11RenderTargetView : ID3D11RenderTargetView1 { - virtual WMTPixelFormat pixelFormat() = 0; - virtual MTL_RENDER_PASS_ATTACHMENT_DESC &description() = 0; - virtual Rc texture() = 0; - virtual unsigned viewId() = 0; + Com resource_{}; + Texture *texture_{}; + unsigned view_id_{}; + MTL_RENDER_PASS_ATTACHMENT_DESC pass_desc_; + WMTPixelFormat format_{}; + ResourceSubsetState subset_{}; + uint32_t bind_flags_{}; + + WMTPixelFormat + pixelFormat() const { + return format_; + }; + const MTL_RENDER_PASS_ATTACHMENT_DESC & + description() const { + return pass_desc_; + }; + Rc + texture() const { + return texture_; + }; + unsigned + viewId() const { + return view_id_; + }; + uint32_t bindFlags() const { + return bind_flags_; + } }; struct D3D11DepthStencilView : ID3D11DepthStencilView { - virtual WMTPixelFormat pixelFormat() = 0; - virtual MTL_RENDER_PASS_ATTACHMENT_DESC &description() = 0; - virtual UINT readonlyFlags() = 0; - virtual Rc texture() = 0; - virtual Rc renamable() = 0; - virtual unsigned viewId() = 0; + Com resource_{}; + Texture *texture_{}; + unsigned view_id_{}; + MTL_RENDER_PASS_ATTACHMENT_DESC pass_desc_; + WMTPixelFormat format_{}; + uint32_t readonly_flags_{}; + RenamableTexturePool *renamable_{}; + ResourceSubsetState subset_{}; + uint32_t bind_flags_{}; + + WMTPixelFormat + pixelFormat() const { + return format_; + }; + const MTL_RENDER_PASS_ATTACHMENT_DESC & + description() const { + return pass_desc_; + }; + Rc + texture() const { + return texture_; + }; + unsigned + viewId() const { + return view_id_; + }; + UINT + readonlyFlags() { + return readonly_flags_; + } + Rc + renamable() { + return renamable_; + } + uint32_t bindFlags() const { + return bind_flags_; + } }; +template +inline bool +CheckOverlap(const A *pViewA, const B *pViewB) { + return pViewA && pViewB && pViewA->resource_ == pViewB->resource_ && pViewA->subset_.overlapWith(pViewB->subset_); +} + +template +inline bool +CheckOverlap(D3D11ResourceCommon *pBuffer, const View *pView) { + return pBuffer && pView && pBuffer == pView->resource_.ptr(); +} + +template +inline bool +CheckOverlap(const View *pView, D3D11ResourceCommon *pBuffer) { + return pBuffer && pView && pBuffer == pView->resource_.ptr(); +} + +inline bool +CheckOverlap(D3D11ResourceCommon *pBufferA, D3D11ResourceCommon *pBufferB) { + return pBufferA && pBufferB && pBufferA == pBufferB; +} + } diff --git a/src/d3d11/dxmt_resource_binding.cpp b/src/d3d11/dxmt_resource_binding.cpp deleted file mode 100644 index f12c3ea0e..000000000 --- a/src/d3d11/dxmt_resource_binding.cpp +++ /dev/null @@ -1,391 +0,0 @@ -#include "dxmt_resource_binding.hpp" -#include -#include "d3d11_private.h" - -#define ASSUME(x) D3D11_ASSERT(x) - -namespace dxmt { - -ResourceSubset::ResourceSubset(size_t numMips, size_t mostDetailedMipLevel, - size_t numArraySlices, size_t firstArraySlice, - size_t numPlanes, size_t firstPlane) noexcept - : begin_array_(firstArraySlice), - end_array_(firstArraySlice + numArraySlices), - begin_mip_(mostDetailedMipLevel), - end_mip_(numMips + mostDetailedMipLevel), begin_plane_(firstPlane), - end_plane_(firstPlane + numPlanes) {} - -bool ResourceSubset::CheckOverlap(const ResourceSubset& other) const noexcept { - return false; -} - -ResourceSubset::ResourceSubset( - const D3D11_SHADER_RESOURCE_VIEW_DESC &Desc) noexcept - : begin_array_(0), end_array_(1), begin_mip_(0), end_mip_(1), - begin_plane_(0), end_plane_(1) { - switch (Desc.ViewDimension) { - default: - break; - - case (D3D11_SRV_DIMENSION_BUFFER): - case (D3D11_SRV_DIMENSION_BUFFEREX): - break; - - case (D3D11_SRV_DIMENSION_TEXTURE1D): - begin_mip_ = UINT8(Desc.Texture1D.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.Texture1D.MipLevels); - break; - - case (D3D11_SRV_DIMENSION_TEXTURE1DARRAY): - begin_array_ = UINT16(Desc.Texture1DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture1DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture1DArray.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.Texture1DArray.MipLevels); - break; - - case (D3D11_SRV_DIMENSION_TEXTURE2D): - begin_mip_ = UINT8(Desc.Texture2D.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.Texture2D.MipLevels); - break; - - case (D3D11_SRV_DIMENSION_TEXTURE2DARRAY): - begin_array_ = UINT16(Desc.Texture2DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture2DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture2DArray.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.Texture2DArray.MipLevels); - break; - - case (D3D11_SRV_DIMENSION_TEXTURE2DMS): - break; - - case (D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY): - begin_array_ = UINT16(Desc.Texture2DMSArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture2DMSArray.ArraySize); - break; - - case (D3D11_SRV_DIMENSION_TEXTURE3D): - end_array_ = UINT16(-1); // all slices - begin_mip_ = UINT8(Desc.Texture3D.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.Texture3D.MipLevels); - break; - - case (D3D11_SRV_DIMENSION_TEXTURECUBE): - begin_mip_ = UINT8(Desc.TextureCube.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.TextureCube.MipLevels); - begin_array_ = 0; - end_array_ = 6; - break; - - case (D3D11_SRV_DIMENSION_TEXTURECUBEARRAY): - begin_array_ = UINT16(Desc.TextureCubeArray.First2DArrayFace); - end_array_ = UINT16(begin_array_ + Desc.TextureCubeArray.NumCubes * 6); - begin_mip_ = UINT8(Desc.TextureCubeArray.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.TextureCubeArray.MipLevels); - break; - } -} - -ResourceSubset::ResourceSubset( - const D3D11_UNORDERED_ACCESS_VIEW_DESC &Desc) noexcept - : begin_array_(0), end_array_(1), begin_mip_(0), end_mip_(1), - begin_plane_(0), end_plane_(1) { - switch (Desc.ViewDimension) { - default: - ASSUME(0 && "Corrupt Resource Type on Unordered Access View"); - break; - - case (D3D11_UAV_DIMENSION_BUFFER): - break; - - case (D3D11_UAV_DIMENSION_TEXTURE1D): - begin_mip_ = UINT8(Desc.Texture1D.MipSlice); - break; - - case (D3D11_UAV_DIMENSION_TEXTURE1DARRAY): - begin_array_ = UINT16(Desc.Texture1DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture1DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture1DArray.MipSlice); - break; - - case (D3D11_UAV_DIMENSION_TEXTURE2D): - begin_mip_ = UINT8(Desc.Texture2D.MipSlice); - break; - - case (D3D11_UAV_DIMENSION_TEXTURE2DARRAY): - begin_array_ = UINT16(Desc.Texture2DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture2DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture2DArray.MipSlice); - break; - - case (D3D11_UAV_DIMENSION_TEXTURE3D): - begin_array_ = UINT16(Desc.Texture3D.FirstWSlice); - end_array_ = UINT16(begin_array_ + Desc.Texture3D.WSize); - begin_mip_ = UINT8(Desc.Texture3D.MipSlice); - break; - } - - end_mip_ = begin_mip_ + 1; -} - -ResourceSubset::ResourceSubset( - const D3D11_RENDER_TARGET_VIEW_DESC &Desc) noexcept - : begin_array_(0), end_array_(1), begin_mip_(0), end_mip_(1), - begin_plane_(0), end_plane_(1) { - switch (Desc.ViewDimension) { - default: - ASSUME(0 && "Corrupt Resource Type on Render Target View"); - break; - - case (D3D11_RTV_DIMENSION_BUFFER): - break; - - case (D3D11_RTV_DIMENSION_TEXTURE1D): - begin_mip_ = UINT8(Desc.Texture1D.MipSlice); - break; - - case (D3D11_RTV_DIMENSION_TEXTURE1DARRAY): - begin_array_ = UINT16(Desc.Texture1DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture1DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture1DArray.MipSlice); - break; - - case (D3D11_RTV_DIMENSION_TEXTURE2D): - begin_mip_ = UINT8(Desc.Texture2D.MipSlice); - break; - - case (D3D11_RTV_DIMENSION_TEXTURE2DMS): - break; - - case (D3D11_RTV_DIMENSION_TEXTURE2DARRAY): - begin_array_ = UINT16(Desc.Texture2DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture2DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture2DArray.MipSlice); - break; - - case (D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY): - begin_array_ = UINT16(Desc.Texture2DMSArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture2DMSArray.ArraySize); - break; - - case (D3D11_RTV_DIMENSION_TEXTURE3D): - begin_array_ = UINT16(Desc.Texture3D.FirstWSlice); - end_array_ = UINT16(begin_array_ + Desc.Texture3D.WSize); - begin_mip_ = UINT8(Desc.Texture3D.MipSlice); - break; - } - - end_mip_ = begin_mip_ + 1; -} - -ResourceSubset::ResourceSubset( - const D3D11_SHADER_RESOURCE_VIEW_DESC1 &Desc) noexcept - : begin_array_(0), end_array_(1), begin_mip_(0), end_mip_(1), - begin_plane_(0), end_plane_(1) { - switch (Desc.ViewDimension) { - default: - break; - - case (D3D11_SRV_DIMENSION_BUFFER): - case (D3D11_SRV_DIMENSION_BUFFEREX): - break; - - case (D3D11_SRV_DIMENSION_TEXTURE1D): - begin_mip_ = UINT8(Desc.Texture1D.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.Texture1D.MipLevels); - break; - - case (D3D11_SRV_DIMENSION_TEXTURE1DARRAY): - begin_array_ = UINT16(Desc.Texture1DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture1DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture1DArray.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.Texture1DArray.MipLevels); - break; - - case (D3D11_SRV_DIMENSION_TEXTURE2D): - begin_mip_ = UINT8(Desc.Texture2D.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.Texture2D.MipLevels); - begin_plane_ = UINT8(Desc.Texture2D.PlaneSlice); - end_plane_ = UINT8(Desc.Texture2D.PlaneSlice + 1); - break; - - case (D3D11_SRV_DIMENSION_TEXTURE2DARRAY): - begin_array_ = UINT16(Desc.Texture2DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture2DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture2DArray.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.Texture2DArray.MipLevels); - begin_plane_ = UINT8(Desc.Texture2DArray.PlaneSlice); - end_plane_ = UINT8(Desc.Texture2DArray.PlaneSlice + 1); - break; - - case (D3D11_SRV_DIMENSION_TEXTURE2DMS): - break; - - case (D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY): - begin_array_ = UINT16(Desc.Texture2DMSArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture2DMSArray.ArraySize); - break; - - case (D3D11_SRV_DIMENSION_TEXTURE3D): - end_array_ = UINT16(-1); // all slices - begin_mip_ = UINT8(Desc.Texture3D.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.Texture3D.MipLevels); - break; - - case (D3D11_SRV_DIMENSION_TEXTURECUBE): - begin_mip_ = UINT8(Desc.TextureCube.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.TextureCube.MipLevels); - begin_array_ = 0; - end_array_ = 6; - break; - - case (D3D11_SRV_DIMENSION_TEXTURECUBEARRAY): - begin_array_ = UINT16(Desc.TextureCubeArray.First2DArrayFace); - end_array_ = UINT16(begin_array_ + Desc.TextureCubeArray.NumCubes * 6); - begin_mip_ = UINT8(Desc.TextureCubeArray.MostDetailedMip); - end_mip_ = UINT8(begin_mip_ + Desc.TextureCubeArray.MipLevels); - break; - } -} - -ResourceSubset::ResourceSubset( - const D3D11_UNORDERED_ACCESS_VIEW_DESC1 &Desc) noexcept - : begin_array_(0), end_array_(1), begin_mip_(0), end_mip_(1), - begin_plane_(0), end_plane_(1) { - switch (Desc.ViewDimension) { - default: - ASSUME(0 && "Corrupt Resource Type on Unordered Access View"); - break; - - case (D3D11_UAV_DIMENSION_BUFFER): - break; - - case (D3D11_UAV_DIMENSION_TEXTURE1D): - begin_mip_ = UINT8(Desc.Texture1D.MipSlice); - break; - - case (D3D11_UAV_DIMENSION_TEXTURE1DARRAY): - begin_array_ = UINT16(Desc.Texture1DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture1DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture1DArray.MipSlice); - break; - - case (D3D11_UAV_DIMENSION_TEXTURE2D): - begin_mip_ = UINT8(Desc.Texture2D.MipSlice); - begin_plane_ = UINT8(Desc.Texture2D.PlaneSlice); - end_plane_ = UINT8(Desc.Texture2D.PlaneSlice + 1); - break; - - case (D3D11_UAV_DIMENSION_TEXTURE2DARRAY): - begin_array_ = UINT16(Desc.Texture2DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture2DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture2DArray.MipSlice); - begin_plane_ = UINT8(Desc.Texture2DArray.PlaneSlice); - end_plane_ = UINT8(Desc.Texture2DArray.PlaneSlice + 1); - break; - - case (D3D11_UAV_DIMENSION_TEXTURE3D): - begin_array_ = UINT16(Desc.Texture3D.FirstWSlice); - end_array_ = UINT16(begin_array_ + Desc.Texture3D.WSize); - begin_mip_ = UINT8(Desc.Texture3D.MipSlice); - break; - } - - end_mip_ = begin_mip_ + 1; -} - -ResourceSubset::ResourceSubset( - const D3D11_RENDER_TARGET_VIEW_DESC1 &Desc) noexcept - : begin_array_(0), end_array_(1), begin_mip_(0), end_mip_(1), - begin_plane_(0), end_plane_(1) { - switch (Desc.ViewDimension) { - default: - ASSUME(0 && "Corrupt Resource Type on Render Target View"); - break; - - case (D3D11_RTV_DIMENSION_BUFFER): - break; - - case (D3D11_RTV_DIMENSION_TEXTURE1D): - begin_mip_ = UINT8(Desc.Texture1D.MipSlice); - break; - - case (D3D11_RTV_DIMENSION_TEXTURE1DARRAY): - begin_array_ = UINT16(Desc.Texture1DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture1DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture1DArray.MipSlice); - break; - - case (D3D11_RTV_DIMENSION_TEXTURE2D): - begin_mip_ = UINT8(Desc.Texture2D.MipSlice); - begin_plane_ = UINT8(Desc.Texture2D.PlaneSlice); - end_plane_ = UINT8(Desc.Texture2D.PlaneSlice + 1); - break; - - case (D3D11_RTV_DIMENSION_TEXTURE2DMS): - break; - - case (D3D11_RTV_DIMENSION_TEXTURE2DARRAY): - begin_array_ = UINT16(Desc.Texture2DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture2DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture2DArray.MipSlice); - begin_plane_ = UINT8(Desc.Texture2DArray.PlaneSlice); - end_plane_ = UINT8(Desc.Texture2DArray.PlaneSlice + 1); - break; - - case (D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY): - begin_array_ = UINT16(Desc.Texture2DMSArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture2DMSArray.ArraySize); - break; - - case (D3D11_RTV_DIMENSION_TEXTURE3D): - begin_array_ = UINT16(Desc.Texture3D.FirstWSlice); - end_array_ = UINT16(begin_array_ + Desc.Texture3D.WSize); - begin_mip_ = UINT8(Desc.Texture3D.MipSlice); - break; - } - - end_mip_ = begin_mip_ + 1; -} - -ResourceSubset::ResourceSubset( - const D3D11_DEPTH_STENCIL_VIEW_DESC &Desc) noexcept - : begin_array_(0), end_array_(1), begin_mip_(0), end_mip_(1), - begin_plane_(0), end_plane_(1) { - switch (Desc.ViewDimension) { - default: - ASSUME(0 && "Corrupt Resource Type on Depth Stencil View"); - break; - - case (D3D11_DSV_DIMENSION_TEXTURE1D): - begin_mip_ = UINT8(Desc.Texture1D.MipSlice); - break; - - case (D3D11_DSV_DIMENSION_TEXTURE1DARRAY): - begin_array_ = UINT16(Desc.Texture1DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture1DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture1DArray.MipSlice); - break; - - case (D3D11_DSV_DIMENSION_TEXTURE2D): - begin_mip_ = UINT8(Desc.Texture2D.MipSlice); - break; - - case (D3D11_DSV_DIMENSION_TEXTURE2DMS): - break; - - case (D3D11_DSV_DIMENSION_TEXTURE2DARRAY): - begin_array_ = UINT16(Desc.Texture2DArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture2DArray.ArraySize); - begin_mip_ = UINT8(Desc.Texture2DArray.MipSlice); - break; - - case (D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY): - begin_array_ = UINT16(Desc.Texture2DMSArray.FirstArraySlice); - end_array_ = UINT16(begin_array_ + Desc.Texture2DMSArray.ArraySize); - break; - } - - end_mip_ = begin_mip_ + 1; -} - -} // namespace dxmt \ No newline at end of file diff --git a/src/d3d11/dxmt_resource_binding.hpp b/src/d3d11/dxmt_resource_binding.hpp deleted file mode 100644 index 0dca1ccd5..000000000 --- a/src/d3d11/dxmt_resource_binding.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "d3d11_3.h" - -namespace dxmt { - -class ResourceSubset { -public: - ResourceSubset(size_t numMips, size_t mostDetailedMipLevel, - size_t numArraySlices, size_t firstArraySlice, - size_t numPlanes, size_t firstPlane) noexcept; - - ResourceSubset(const D3D11_SHADER_RESOURCE_VIEW_DESC &Desc) noexcept; - ResourceSubset(const D3D11_UNORDERED_ACCESS_VIEW_DESC &Desc) noexcept; - ResourceSubset(const D3D11_RENDER_TARGET_VIEW_DESC &Desc) noexcept; - - ResourceSubset(const D3D11_SHADER_RESOURCE_VIEW_DESC1 &Desc) noexcept; - ResourceSubset(const D3D11_UNORDERED_ACCESS_VIEW_DESC1 &Desc) noexcept; - ResourceSubset(const D3D11_RENDER_TARGET_VIEW_DESC1 &Desc) noexcept; - ResourceSubset(const D3D11_DEPTH_STENCIL_VIEW_DESC &Desc) noexcept; - - bool CheckOverlap(const ResourceSubset &other) const noexcept; - -private: - size_t begin_array_; - size_t end_array_; - size_t begin_mip_; - size_t end_mip_; - size_t begin_plane_; - size_t end_plane_; -}; -} // namespace dxmt \ No newline at end of file diff --git a/src/d3d11/meson.build b/src/d3d11/meson.build index a6c82fb39..948db2a53 100644 --- a/src/d3d11/meson.build +++ b/src/d3d11/meson.build @@ -18,7 +18,6 @@ d3d11_src = [ 'd3d11_texture_linear.cpp', 'd3d11_texture_dynamic.cpp', 'd3d11_resource_staging.cpp', - 'dxmt_resource_binding.cpp', 'd3d11_pipeline.cpp', 'd3d11_pipeline_gs.cpp', 'd3d11_pipeline_ts.cpp', diff --git a/src/dxmt/dxmt_binding_set.hpp b/src/dxmt/dxmt_binding_set.hpp index c0833eadd..eb92d55fb 100644 --- a/src/dxmt/dxmt_binding_set.hpp +++ b/src/dxmt/dxmt_binding_set.hpp @@ -14,6 +14,7 @@ Element is required to be move-assignable template class BindingSet { bit::bitset dirty; bit::bitset bound; + bit::bitset hazard; std::array storage; public: @@ -22,6 +23,7 @@ template class BindingSet { BindingSet(BindingSet &&move) : storage(std::move(move.storage)) { bound = move.bound; dirty = move.bound; // intended behavior + hazard = move.hazard; }; BindingSet & @@ -29,6 +31,7 @@ template class BindingSet { storage = std::move(move.storage); bound = move.bound; dirty = move.bound; // intended behavior + hazard = move.hazard; return *this; } @@ -59,22 +62,22 @@ template class BindingSet { } constexpr bool - any_dirty_masked(uint16_t mask) noexcept { + any_dirty_masked(uint16_t mask) const noexcept { return (dirty.qword(0) & (uint64_t)mask) != 0; } constexpr bool - any_dirty_masked(uint64_t mask) noexcept { + any_dirty_masked(uint64_t mask) const noexcept { return (dirty.qword(0) & mask) != 0; } constexpr bool - any_dirty_masked(uint64_t mask_hi, uint64_t mask_lo) noexcept { + any_dirty_masked(uint64_t mask_hi, uint64_t mask_lo) const noexcept { return ((dirty.qword(0) & mask_lo) | (dirty.qword(1) & mask_hi)) != 0; } constexpr bool - all_bound_masked(uint32_t mask) noexcept { + all_bound_masked(uint32_t mask) const noexcept { return (bound.qword(0) & mask) == mask; } @@ -84,9 +87,9 @@ template class BindingSet { } constexpr uint32_t - max_binding_64() noexcept { - auto qword = dirty.qword(0); - return qword == 0 ? 0 : 64 - __builtin_clzll(qword); + max_binding_64() const noexcept { + uint64_t qword = dirty.qword(0); + return 64u - bit::tzcnt(qword); } inline void @@ -121,13 +124,14 @@ template class BindingSet { (so no initialization overhead if no replacement) */ inline Element & - bind(size_t slot, Element &&element, bool &replacement) { + bind(size_t slot, Element &&element, bool &replacement, bool hazard = true) { if (bound.get(slot)) { if (redunant_binding_trait::is_redunant(storage[slot], element)) { return storage[slot]; } } else { bound.set(slot, true); + this->hazard.set(slot, hazard); } // new (storage.data() + slot) Element(std::forward(element)); // std::construct_at(storage.data() + slot, std::forward(element)); @@ -149,6 +153,7 @@ template class BindingSet { // at bind() storage[slot] = {}; bound.set(slot, false); + hazard.set(slot, false); dirty.set(slot, true); return true; } @@ -157,13 +162,23 @@ template class BindingSet { class bound_iterator { const BindingSet &binding_set; + const bit::bitset &bits; size_t current; void advance_to_next() { - while (current < NumElements && !binding_set.bound.get(current)) { - ++current; + while (current < NumElements) { + auto qword_index = current / 64; + auto tz = bit::tzcnt(uint64_t(bits.qword(qword_index) & ~((1ull << (current % 64)) - 1ull))); + if (tz < 64) { + current = qword_index * 64 + tz; + return; + } + current = (qword_index + 1) * 64; + continue; } + // just in case, clamp it + current = NumElements; } public: @@ -173,7 +188,10 @@ template class BindingSet { using pointer = void; using reference = std::pair; - bound_iterator(const BindingSet &set, size_t start) : binding_set(set), current(start) { + bound_iterator(const BindingSet &set, const bit::bitset &bits, size_t start) : + binding_set(set), + bits(bits), + current(start) { advance_to_next(); } @@ -197,22 +215,27 @@ template class BindingSet { } bool - operator==(const bound_iterator &other) const { - return current == other.current; - } - bool - operator!=(const bound_iterator &other) const { - return !(*this == other); + operator!=(uint64_t index) const { + return current != index; } }; bound_iterator begin() const { - return bound_iterator(*this, 0); + return bound_iterator(*this, bound, 0); } - bound_iterator + uint64_t end() const { - return bound_iterator(*this, NumElements); + return NumElements; + } + + bound_iterator + hazard_begin() const { + return bound_iterator(*this, hazard, 0); + } + uint64_t + hazard_end() const { + return NumElements; } }; } // namespace dxmt \ No newline at end of file diff --git a/src/dxmt/dxmt_subresource.cpp b/src/dxmt/dxmt_subresource.cpp new file mode 100644 index 000000000..8ce5cfa2c --- /dev/null +++ b/src/dxmt/dxmt_subresource.cpp @@ -0,0 +1,70 @@ +#include "dxmt_subresource.hpp" +#include "dxmt_texture.hpp" + +namespace dxmt { + +unsigned +getPlanarCount(WMTPixelFormat format) { + switch (format) { + case WMTPixelFormatX32G8X32: + case WMTPixelFormatR32X8X32: + case WMTPixelFormatDepth32Float_Stencil8: + case WMTPixelFormatDepth24Unorm_Stencil8: + case WMTPixelFormatX32_Stencil8: + case WMTPixelFormatX24_Stencil8: + return 2; + default: + break; + } + return 1; +} + +unsigned +getPlanarMask(WMTPixelFormat format) { + switch (format) { + case WMTPixelFormatX32G8X32: + return 0b10; + case WMTPixelFormatR32X8X32: + return 0b01; + case WMTPixelFormatDepth32Float_Stencil8: + case WMTPixelFormatDepth24Unorm_Stencil8: + return 0b11; + case WMTPixelFormatX32_Stencil8: + case WMTPixelFormatX24_Stencil8: + return 0b10; + default: + break; + } + return 1; +} + +ResourceSubsetState::ResourceSubsetState( + const TextureViewDescriptor *desc, uint32_t total_mip_count, uint32_t total_array_size, uint32_t ignore_planar_mask +) { + auto total_planar = getPlanarCount(desc->format); + auto planar_mask = getPlanarMask(desc->format) & ~ignore_planar_mask; + if (total_planar * total_mip_count * total_array_size <= 62) { + encoded_tag = 0b11; + uint64_t bits = 0; + for (auto planar = 0u; planar < total_planar; planar++) { + // unsigned int bit-fields promote to int if narrower than int + for (auto slice = desc->firstArraySlice; slice < unsigned(desc->firstArraySlice + desc->arraySize); slice++) { + for (auto level = desc->firstMiplevel; level < unsigned(desc->firstMiplevel + desc->miplevelCount); level++) { + if ((1 << planar) & planar_mask) + bits |= 1ull << (planar * total_array_size * total_mip_count + slice * total_mip_count + level); + } + } + } + texture_bitmask.mask = bits; + } else { + encoded_tag = 0b10; + + texture.mip_start = desc->firstMiplevel; + texture.mip_end = desc->firstMiplevel + desc->miplevelCount; + texture.array_start = desc->firstArraySlice; + texture.array_end = desc->firstArraySlice + desc->arraySize; + texture.planar_mask = planar_mask; + } +} + +} // namespace dxmt diff --git a/src/dxmt/dxmt_subresource.hpp b/src/dxmt/dxmt_subresource.hpp new file mode 100644 index 000000000..7f476e352 --- /dev/null +++ b/src/dxmt/dxmt_subresource.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include +#include + +namespace dxmt { + +struct TextureViewDescriptor; + +class ResourceSubsetState { +public: + struct BufferSlice { + uint64_t tag : 2; + uint64_t offset : 31; + uint64_t length : 31; + }; + + struct TextureBitmaskSubset { + uint64_t tag : 2; + uint64_t mask : 62; + }; + + struct TextureSubset { + uint64_t tag : 2; + uint64_t planar_mask : 30; + uint64_t mip_start : 4; + uint64_t array_start : 12; + uint64_t mip_end : 4; + uint64_t array_end : 12; + }; + + inline bool + overlapWith(const ResourceSubsetState &other) const { + if (encoded_tag && other.encoded_tag && encoded_tag != other.encoded_tag) + return false; + + if (encoded_tag == 0b01) { + return (buffer.offset < other.buffer.offset + other.buffer.length) && + (other.buffer.offset < buffer.offset + buffer.length); + } else if (encoded_tag == 0b11) { + return texture_bitmask.mask & other.texture_bitmask.mask; + } else if (encoded_tag == 0b10) { + return (texture.planar_mask & other.texture.planar_mask) && + (texture.mip_start < other.texture.mip_end) && + (other.texture.mip_start < texture.mip_end) && + (texture.array_start < other.texture.array_end) && + (other.texture.array_start < texture.array_end); + } + return true; + } + + ResourceSubsetState() { + // whole resource + encoded_tag = 0; + } + + ResourceSubsetState(uint32_t buffer_offset, uint32_t buffer_length) { + encoded_tag = 0b01; + buffer.offset = buffer_offset; + buffer.length = buffer_length; + } + + /** + NOTE: we assume the view format is in the same 'format family' of resource allocation format, so that we can conclude + the total planar count from view format. This is not really the case for video format (e.g. NV12, YUY2), where the + view format can be ordinary format like RG8 or R16 + So don't use this constructor for video textures/views (which is not implemented yet). + */ + ResourceSubsetState(const TextureViewDescriptor *desc, uint32_t total_mip_count, uint32_t total_array_size, uint32_t ignore_planar_mask = 0); + +private: + union { + BufferSlice buffer; + TextureBitmaskSubset texture_bitmask; + TextureSubset texture; + struct { + uint64_t encoded_tag : 2; + uint64_t reserved : 62; + }; + }; +}; + +}; // namespace dxmt \ No newline at end of file diff --git a/src/dxmt/dxmt_texture.cpp b/src/dxmt/dxmt_texture.cpp index bf79e19c0..150578c25 100644 --- a/src/dxmt/dxmt_texture.cpp +++ b/src/dxmt/dxmt_texture.cpp @@ -113,23 +113,13 @@ Texture::Texture(const WMTTextureInfo &descriptor, WMT::Device device) : info_(descriptor), device_(device) { - uint32_t arraySize = info_.array_length; - switch (info_.type) { - case WMTTextureTypeCubeArray: - case WMTTextureTypeCube: - arraySize = arraySize * 6; - break; - default: - break; - } - viewDescriptors_.push_back({ .format = info_.pixel_format, .type = info_.type, .firstMiplevel = 0, .miplevelCount = info_.mipmap_level_count, .firstArraySlice = 0, - .arraySize = arraySize, + .arraySize = arrayLength(), }); version_ = 1; } diff --git a/src/dxmt/dxmt_texture.hpp b/src/dxmt/dxmt_texture.hpp index ccf28379b..05bba14b6 100644 --- a/src/dxmt/dxmt_texture.hpp +++ b/src/dxmt/dxmt_texture.hpp @@ -194,10 +194,17 @@ class Texture { } /** - \warning for cube texture, arrayLength() returns 1, while arrayLength(0) returns 6" + \warning for cube texture, this would be multiple of 6. */ unsigned arrayLength() const { + switch (info_.type) { + case WMTTextureTypeCubeArray: + case WMTTextureTypeCube: + return info_.array_length * 6; + default: + break; + } return info_.array_length; } @@ -207,6 +214,11 @@ class Texture { return viewDescriptors_[view].arraySize; } + unsigned + miplevelCount() const { + return info_.mipmap_level_count; + } + Rc allocate(Flags flags); Rc import(mach_port_t mach_port); diff --git a/src/dxmt/meson.build b/src/dxmt/meson.build index 124772694..76bfa96f7 100644 --- a/src/dxmt/meson.build +++ b/src/dxmt/meson.build @@ -18,6 +18,7 @@ dxmt_src = [ 'dxmt_resource_initializer.cpp', 'dxmt_shader_cache.cpp', 'dxmt_scaler.cpp', + 'dxmt_subresource.cpp', ] dxmt_shaders = [ diff --git a/src/util/util_bit.hpp b/src/util/util_bit.hpp index 2b6d9705d..527635b0e 100644 --- a/src/util/util_bit.hpp +++ b/src/util/util_bit.hpp @@ -327,6 +327,8 @@ template class bitset { constexpr uint64_t &qword(uint64_t idx) { return m_qwords[idx]; } + constexpr uint64_t qword(uint64_t idx) const { return m_qwords[idx]; } + constexpr size_t bitCount() { return Bits; } constexpr size_t qwordCount() { return Qwords; }