From d881696d2e92c157117dbc7f7aa850a6a4a4874a Mon Sep 17 00:00:00 2001 From: Feifan He Date: Thu, 2 Apr 2026 19:42:19 +0800 Subject: [PATCH 01/11] chore(d3d11): remove some unused code --- src/d3d11/d3d11_resource.hpp | 5 - src/d3d11/d3d11_view.hpp | 1 - src/d3d11/dxmt_resource_binding.cpp | 391 ---------------------------- src/d3d11/dxmt_resource_binding.hpp | 32 --- src/d3d11/meson.build | 1 - 5 files changed, 430 deletions(-) delete mode 100644 src/d3d11/dxmt_resource_binding.cpp delete mode 100644 src/d3d11/dxmt_resource_binding.hpp diff --git a/src/d3d11/d3d11_resource.hpp b/src/d3d11/d3d11_resource.hpp index 27b62a438..5cc2daa40 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" @@ -424,10 +423,6 @@ class TResourceViewBase 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; diff --git a/src/d3d11/d3d11_view.hpp b/src/d3d11/d3d11_view.hpp index 5ff154721..e800f2064 100644 --- a/src/d3d11/d3d11_view.hpp +++ b/src/d3d11/d3d11_view.hpp @@ -1,7 +1,6 @@ #pragma once #include "d3d11_1.h" #include "dxmt_buffer.hpp" -#include "dxmt_resource_binding.hpp" #include "dxmt_texture.hpp" struct MTL_RENDER_PASS_ATTACHMENT_DESC { 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', From cb6b12f27968c17553b59258742439d929a63321 Mon Sep 17 00:00:00 2001 From: Feifan He Date: Thu, 2 Apr 2026 20:10:19 +0800 Subject: [PATCH 02/11] !refactor(dxmt): change behavior of `Texture::arrayLength()` and introduce `Texture::miplevelCount()` --- src/dxmt/dxmt_texture.cpp | 12 +----------- src/dxmt/dxmt_texture.hpp | 14 +++++++++++++- 2 files changed, 14 insertions(+), 12 deletions(-) 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); From 3ff734c78230dc88eb4f6203da4ee43b325bf47d Mon Sep 17 00:00:00 2001 From: Feifan He Date: Thu, 2 Apr 2026 20:10:39 +0800 Subject: [PATCH 03/11] feat(dxmt): introduce `ResourceSubsetState` --- src/dxmt/dxmt_subresource.cpp | 70 +++++++++++++++++++++++++++++ src/dxmt/dxmt_subresource.hpp | 83 +++++++++++++++++++++++++++++++++++ src/dxmt/meson.build | 1 + 3 files changed, 154 insertions(+) create mode 100644 src/dxmt/dxmt_subresource.cpp create mode 100644 src/dxmt/dxmt_subresource.hpp 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/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 = [ From 87ae66b5d5e8fcf16b0a3fc3419ee801ae528ca3 Mon Sep 17 00:00:00 2001 From: Feifan He Date: Thu, 2 Apr 2026 20:55:27 +0800 Subject: [PATCH 04/11] refactor(d3d11): devirtualize SRV and UAV common accessors Actually we can just access the data member and get rid of accessors, but it also leads to large amount of noisy changes. Compilers will optimize it as simple data load anyway. --- src/d3d11/d3d11_buffer.cpp | 32 ++++++---------- src/d3d11/d3d11_texture_device.cpp | 26 ++++--------- src/d3d11/d3d11_texture_dynamic.cpp | 12 ++---- src/d3d11/d3d11_texture_linear.cpp | 13 ++----- src/d3d11/d3d11_view.hpp | 58 ++++++++++++++++++++++++----- 5 files changed, 75 insertions(+), 66 deletions(-) diff --git a/src/d3d11/d3d11_buffer.cpp b/src/d3d11/d3d11_buffer.cpp index da41ec382..c1eada4cf 100644 --- a/src/d3d11/d3d11_buffer.cpp +++ b/src/d3d11/d3d11_buffer.cpp @@ -29,45 +29,35 @@ 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_ = resource->buffer_.ptr(); + view_id_ = info.viewKey; + slice_ = {info.byteOffset, info.byteWidth, info.viewElementOffset, info.viewElementWidth }; + } ~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_ = resource->buffer_.ptr(); + view_id_ = info.viewKey; + slice_ = {info.byteOffset, info.byteWidth, info.viewElementOffset, info.viewElementWidth }; + counter_ = std::move(counter); + } }; public: diff --git a/src/d3d11/d3d11_texture_device.cpp b/src/d3d11/d3d11_texture_device.cpp index d52e3da87..7b19b38aa 100644 --- a/src/d3d11/d3d11_texture_device.cpp +++ b/src/d3d11/d3d11_texture_device.cpp @@ -24,38 +24,28 @@ class DeviceTexture : public TResourceBase { using SRVBase = TResourceViewBase>>; class TextureSRV : public SRVBase { - private: - TextureViewKey view_key_; - public: TextureSRV(TextureViewKey view_key, 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->underlying_texture_.ptr(); + this->view_id_ = view_key; + } - 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, 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->underlying_texture_.ptr(); + this->view_id_ = view_key; + } }; using RTVBase = diff --git a/src/d3d11/d3d11_texture_dynamic.cpp b/src/d3d11/d3d11_texture_dynamic.cpp index ba42afa36..9d3bad079 100644 --- a/src/d3d11/d3d11_texture_dynamic.cpp +++ b/src/d3d11/d3d11_texture_dynamic.cpp @@ -29,19 +29,15 @@ class DynamicTexture : public TResourceBase { using SRVBase = TResourceViewBase>>; class TextureSRV : public SRVBase { - private: - TextureViewKey view_key_; - public: TextureSRV(TextureViewKey view_key, 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->underlying_texture_.ptr(); + this->view_id_ = view_key; + } - Rc buffer() final { return {}; }; - Rc texture() final { return this->resource->underlying_texture_; }; - unsigned viewId() final { return view_key_;}; - BufferSlice bufferSlice() final { return {};} }; public: diff --git a/src/d3d11/d3d11_texture_linear.cpp b/src/d3d11/d3d11_texture_linear.cpp index 1de2d4b7f..447ba2f6b 100644 --- a/src/d3d11/d3d11_texture_linear.cpp +++ b/src/d3d11/d3d11_texture_linear.cpp @@ -22,20 +22,15 @@ 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) {} + SRVBase(pDesc, pResource, pDevice) { + this->texture_ = pResource->texture_.ptr(); + this->view_id_ = view_key; + } ~SRV() {} - - Rc buffer() final { return {}; }; - Rc texture() final { return this->resource->texture_; }; - unsigned viewId() final { return view_key;}; - BufferSlice bufferSlice() final { return {};} }; public: diff --git a/src/d3d11/d3d11_view.hpp b/src/d3d11/d3d11_view.hpp index e800f2064..6a966cc4f 100644 --- a/src/d3d11/d3d11_view.hpp +++ b/src/d3d11/d3d11_view.hpp @@ -1,5 +1,5 @@ #pragma once -#include "d3d11_1.h" +#include "d3d11_3.h" #include "dxmt_buffer.hpp" #include "dxmt_texture.hpp" @@ -14,18 +14,56 @@ struct MTL_RENDER_PASS_ATTACHMENT_DESC { namespace dxmt { struct D3D11ShaderResourceView : ID3D11ShaderResourceView1 { - virtual Rc buffer() = 0; - virtual BufferSlice bufferSlice() = 0; - virtual Rc texture() = 0; - virtual unsigned viewId() = 0; + Buffer *buffer_{}; + BufferSlice slice_{}; + Texture *texture_{}; + unsigned view_id_{}; + + Rc + buffer() const { + return buffer_; + }; + BufferSlice + bufferSlice() const { + return slice_; + }; + Rc + texture() const { + return texture_; + }; + unsigned + viewId() const { + return view_id_; + }; }; struct D3D11UnorderedAccessView : ID3D11UnorderedAccessView1 { - virtual Rc buffer() = 0; - virtual BufferSlice bufferSlice() = 0; - virtual Rc texture() = 0; - virtual unsigned viewId() = 0; - virtual Rc counter() = 0; + Buffer *buffer_{}; + BufferSlice slice_{}; + Texture *texture_{}; + unsigned view_id_{}; + Rc counter_; + + 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_; + }; }; struct D3D11RenderTargetView : ID3D11RenderTargetView1 { From 2e941f7657e7263741cab1e2b61827188ad477e3 Mon Sep 17 00:00:00 2001 From: Feifan He Date: Thu, 2 Apr 2026 21:04:16 +0800 Subject: [PATCH 05/11] refactor(d3d11): devirtualize RTV and DSV common accessors Similar to previous commit. --- src/d3d11/d3d11_context_impl.cpp | 2 +- src/d3d11/d3d11_texture_device.cpp | 70 +++++------------------------- src/d3d11/d3d11_view.hpp | 63 ++++++++++++++++++++++----- 3 files changed, 65 insertions(+), 70 deletions(-) diff --git a/src/d3d11/d3d11_context_impl.cpp b/src/d3d11/d3d11_context_impl.cpp index fea482b7a..f30d3150b 100644 --- a/src/d3d11/d3d11_context_impl.cpp +++ b/src/d3d11/d3d11_context_impl.cpp @@ -2474,7 +2474,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; diff --git a/src/d3d11/d3d11_texture_device.cpp b/src/d3d11/d3d11_texture_device.cpp index 7b19b38aa..5e2c41f32 100644 --- a/src/d3d11/d3d11_texture_device.cpp +++ b/src/d3d11/d3d11_texture_device.cpp @@ -51,80 +51,34 @@ class DeviceTexture : public TResourceBase { 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, 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->view_id_ = view_key; + this->format_ = view_format; + this->pass_desc_ = mtl_rtv_desc; + this->texture_ = this->resource->underlying_texture_.ptr(); } }; 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, 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->view_id_ = view_key; + this->format_ = view_format; + this->pass_desc_ = attachment_desc; + this->texture_ = this->resource->underlying_texture_.ptr(); + this->renamable_ = this->resource->renamable_.ptr(); + this->readonly_flags_ = this->desc.Flags; } }; diff --git a/src/d3d11/d3d11_view.hpp b/src/d3d11/d3d11_view.hpp index 6a966cc4f..119cce0e9 100644 --- a/src/d3d11/d3d11_view.hpp +++ b/src/d3d11/d3d11_view.hpp @@ -67,19 +67,60 @@ struct D3D11UnorderedAccessView : ID3D11UnorderedAccessView1 { }; struct D3D11RenderTargetView : ID3D11RenderTargetView1 { - virtual WMTPixelFormat pixelFormat() = 0; - virtual MTL_RENDER_PASS_ATTACHMENT_DESC &description() = 0; - virtual Rc texture() = 0; - virtual unsigned viewId() = 0; + Texture *texture_{}; + unsigned view_id_{}; + MTL_RENDER_PASS_ATTACHMENT_DESC pass_desc_; + WMTPixelFormat format_{}; + + 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_; + }; }; 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; -}; + Texture *texture_{}; + unsigned view_id_{}; + MTL_RENDER_PASS_ATTACHMENT_DESC pass_desc_; + WMTPixelFormat format_{}; + uint32_t readonly_flags_{}; + RenamableTexturePool *renamable_{}; + 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_; + } +}; } From 96e01315d4946d05c046e78514d9709c661b3dbe Mon Sep 17 00:00:00 2001 From: Feifan He Date: Thu, 2 Apr 2026 23:47:06 +0800 Subject: [PATCH 06/11] refactor(d3d11): devirtualize buffer & texture common accessors Similar to previous commits. --- src/d3d11/d3d11_buffer.cpp | 13 --------- src/d3d11/d3d11_resource.hpp | 13 +++++++-- src/d3d11/d3d11_resource_staging.cpp | 24 ---------------- src/d3d11/d3d11_texture_device.cpp | 42 ++++++++++++++-------------- src/d3d11/d3d11_texture_dynamic.cpp | 16 ++++------- src/d3d11/d3d11_texture_linear.cpp | 15 ++++------ 6 files changed, 42 insertions(+), 81 deletions(-) diff --git a/src/d3d11/d3d11_buffer.cpp b/src/d3d11/d3d11_buffer.cpp index c1eada4cf..cab72f036 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 @@ -108,18 +107,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_resource.hpp b/src/d3d11/d3d11_resource.hpp index 5cc2daa40..327ceed84 100644 --- a/src/d3d11/d3d11_resource.hpp +++ b/src/d3d11/d3d11_resource.hpp @@ -129,13 +129,20 @@ 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_{}; + + const Rc &buffer() const { + return buffer_; + } + const Rc &texture() const { + return texture_; + } }; inline Rc 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 5e2c41f32..99790372d 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; @@ -29,7 +28,7 @@ class DeviceTexture : public TResourceBase { const tag_shader_resource_view<>::DESC1 *pDesc, DeviceTexture *pResource, MTLD3D11Device *pDevice) : SRVBase(pDesc, pResource, pDevice) { - this->texture_ = pResource->underlying_texture_.ptr(); + this->texture_ = pResource->texture_.ptr(); this->view_id_ = view_key; } @@ -43,7 +42,7 @@ class DeviceTexture : public TResourceBase { const tag_unordered_access_view<>::DESC1 *pDesc, DeviceTexture *pResource, MTLD3D11Device *pDevice) : UAVBase(pDesc, pResource, pDevice) { - this->texture_ = pResource->underlying_texture_.ptr(); + this->texture_ = pResource->texture_.ptr(); this->view_id_ = view_key; } }; @@ -60,7 +59,7 @@ class DeviceTexture : public TResourceBase { this->view_id_ = view_key; this->format_ = view_format; this->pass_desc_ = mtl_rtv_desc; - this->texture_ = this->resource->underlying_texture_.ptr(); + this->texture_ = this->resource->texture_.ptr(); } }; @@ -76,7 +75,7 @@ class DeviceTexture : public TResourceBase { this->view_id_ = view_key; this->format_ = view_format; this->pass_desc_ = attachment_desc; - this->texture_ = this->resource->underlying_texture_.ptr(); + this->texture_ = this->resource->texture_.ptr(); this->renamable_ = this->resource->renamable_.ptr(); this->readonly_flags_ = this->desc.Flags; } @@ -84,23 +83,27 @@ class DeviceTexture : public TResourceBase { 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_) { @@ -111,9 +114,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 {}; }; @@ -135,7 +135,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; @@ -143,7 +143,7 @@ class DeviceTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = underlying_texture_->createView(descriptor); + TextureViewKey key = this->texture_->createView(descriptor); *ppView = ref(new TextureRTV(key, descriptor.format, &finalDesc, this, this->m_parent, attachment_desc)); return S_OK; }; @@ -164,7 +164,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; @@ -172,7 +172,7 @@ class DeviceTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = underlying_texture_->createView(descriptor); + TextureViewKey key = this->texture_->createView(descriptor); *ppView = ref(new TextureDSV(key, descriptor.format, &finalDesc, this, this->m_parent, attachment_desc)); return S_OK; }; @@ -195,7 +195,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; @@ -203,7 +203,7 @@ class DeviceTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = underlying_texture_->createView(descriptor); + TextureViewKey key = this->texture_->createView(descriptor); *ppView = ref(new TextureSRV(key, &finalDesc, this, this->m_parent)); return S_OK; }; @@ -225,7 +225,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; @@ -233,7 +233,7 @@ class DeviceTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = underlying_texture_->createView(descriptor); + TextureViewKey key = this->texture_->createView(descriptor); *ppView = ref(new TextureUAV(key, &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 9d3bad079..c432a61d5 100644 --- a/src/d3d11/d3d11_texture_dynamic.cpp +++ b/src/d3d11/d3d11_texture_dynamic.cpp @@ -22,7 +22,6 @@ struct Subresource { template class DynamicTexture : public TResourceBase { private: - Rc underlying_texture_; std::vector subresources_; float min_lod = 0.0; @@ -34,7 +33,7 @@ class DynamicTexture : public TResourceBase { const tag_shader_resource_view<>::DESC1 *pDesc, DynamicTexture *pResource, MTLD3D11Device *pDevice) : SRVBase(pDesc, pResource, pDevice) { - this->texture_ = pResource->underlying_texture_.ptr(); + this->texture_ = pResource->texture_.ptr(); this->view_id_ = view_key; } @@ -43,12 +42,9 @@ class DynamicTexture : public TResourceBase { 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 {}; }; @@ -81,7 +77,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; @@ -89,7 +85,7 @@ class DynamicTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = underlying_texture_->createView(descriptor); + TextureViewKey key = this->texture_->createView(descriptor); *ppView = ref(new TextureSRV(key, &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 447ba2f6b..01227e698 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_; @@ -41,7 +40,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); @@ -50,13 +49,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), @@ -66,12 +65,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 { From b80d678d170553ccdf378ac02b5d27cf20cf6f4f Mon Sep 17 00:00:00 2001 From: Feifan He Date: Fri, 3 Apr 2026 00:18:21 +0800 Subject: [PATCH 07/11] feat(d3d11): add necessary data member to resource views for hazard checking --- src/d3d11/d3d11_buffer.cpp | 6 ++- src/d3d11/d3d11_resource.hpp | 25 +++++++------ src/d3d11/d3d11_texture_device.cpp | 57 +++++++++++++++++++---------- src/d3d11/d3d11_texture_dynamic.cpp | 12 ++++-- src/d3d11/d3d11_texture_linear.cpp | 23 +++++++----- src/d3d11/d3d11_view.hpp | 40 ++++++++++++++++++++ 6 files changed, 115 insertions(+), 48 deletions(-) diff --git a/src/d3d11/d3d11_buffer.cpp b/src/d3d11/d3d11_buffer.cpp index cab72f036..3aa09f191 100644 --- a/src/d3d11/d3d11_buffer.cpp +++ b/src/d3d11/d3d11_buffer.cpp @@ -35,9 +35,10 @@ class D3D11Buffer : public TResourceBase { BufferViewInfo const &info ) : SRVBase(pDesc, pResource, pDevice) { - buffer_ = resource->buffer_.ptr(); + buffer_ = pResource->buffer_.ptr(); view_id_ = info.viewKey; slice_ = {info.byteOffset, info.byteWidth, info.viewElementOffset, info.viewElementWidth }; + subset_ = ResourceSubsetState(info.byteOffset, info.byteWidth); } ~TBufferSRV() {} @@ -52,10 +53,11 @@ class D3D11Buffer : public TResourceBase { BufferViewInfo const &info, Rc&& counter ) : UAVBase(pDesc, pResource, pDevice) { - buffer_ = resource->buffer_.ptr(); + 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); } }; diff --git a/src/d3d11/d3d11_resource.hpp b/src/d3d11/d3d11_resource.hpp index 327ceed84..6c42ec237 100644 --- a/src/d3d11/d3d11_resource.hpp +++ b/src/d3d11/d3d11_resource.hpp @@ -136,6 +136,7 @@ struct D3D11ResourceCommon : ID3D11Resource { Rc buffer_{}; Rc texture_{}; + uint32_t bind_flags_{}; const Rc &buffer() const { return buffer_; @@ -170,12 +171,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; @@ -367,10 +370,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) { @@ -427,16 +432,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)); } protected: tag::DESC1 desc; tag::D3D10_IMPL d3d10; - /** - strong ref to resource - */ - Com resource; }; #pragma region Resource Factory diff --git a/src/d3d11/d3d11_texture_device.cpp b/src/d3d11/d3d11_texture_device.cpp index 99790372d..0eaa1c903 100644 --- a/src/d3d11/d3d11_texture_device.cpp +++ b/src/d3d11/d3d11_texture_device.cpp @@ -24,12 +24,17 @@ class DeviceTexture : public TResourceBase { TResourceViewBase>>; class TextureSRV : public SRVBase { public: - TextureSRV(TextureViewKey view_key, + TextureSRV(const TextureViewDescriptor &descriptor, const tag_shader_resource_view<>::DESC1 *pDesc, DeviceTexture *pResource, MTLD3D11Device *pDevice) : SRVBase(pDesc, pResource, pDevice) { this->texture_ = pResource->texture_.ptr(); - this->view_id_ = view_key; + this->view_id_ = this->texture_->createView(descriptor); + this->subset_ = ResourceSubsetState( + &descriptor, + this->texture_->miplevelCount(), + this->texture_->arrayLength() + ); } }; @@ -38,12 +43,17 @@ class DeviceTexture : public TResourceBase { TResourceViewBase>>; class TextureUAV : public UAVBase { public: - TextureUAV(TextureViewKey view_key, + TextureUAV(const TextureViewDescriptor &descriptor, const tag_unordered_access_view<>::DESC1 *pDesc, DeviceTexture *pResource, MTLD3D11Device *pDevice) : UAVBase(pDesc, pResource, pDevice) { this->texture_ = pResource->texture_.ptr(); - this->view_id_ = view_key; + this->view_id_ = this->texture_->createView(descriptor); + this->subset_ = ResourceSubsetState( + &descriptor, + this->texture_->miplevelCount(), + this->texture_->arrayLength() + ); } }; @@ -52,14 +62,19 @@ class DeviceTexture : public TResourceBase { class TextureRTV : public RTVBase { 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) { - this->view_id_ = view_key; + this->texture_ = pResource->texture_.ptr(); + this->view_id_ = this->texture_->createView(descriptor); this->format_ = view_format; this->pass_desc_ = mtl_rtv_desc; - this->texture_ = this->resource->texture_.ptr(); + this->subset_ = ResourceSubsetState( + &descriptor, + this->texture_->miplevelCount(), + this->texture_->arrayLength() + ); } }; @@ -68,16 +83,22 @@ class DeviceTexture : public TResourceBase { class TextureDSV : public DSVBase { 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) { - this->view_id_ = view_key; + this->texture_ = pResource->texture_.ptr(); + this->view_id_ = this->texture_->createView(descriptor); this->format_ = view_format; this->pass_desc_ = attachment_desc; - this->texture_ = this->resource->texture_.ptr(); - this->renamable_ = this->resource->renamable_.ptr(); - this->readonly_flags_ = this->desc.Flags; + 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_ + ); } }; @@ -143,8 +164,7 @@ class DeviceTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = this->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; }; @@ -172,8 +192,7 @@ class DeviceTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = this->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; }; @@ -203,8 +222,7 @@ class DeviceTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = this->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; }; @@ -233,8 +251,7 @@ class DeviceTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = this->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 c432a61d5..abc3d57d7 100644 --- a/src/d3d11/d3d11_texture_dynamic.cpp +++ b/src/d3d11/d3d11_texture_dynamic.cpp @@ -29,12 +29,17 @@ class DynamicTexture : public TResourceBase { TResourceViewBase>>; class TextureSRV : public SRVBase { public: - TextureSRV(TextureViewKey view_key, + TextureSRV(const TextureViewDescriptor &descriptor, const tag_shader_resource_view<>::DESC1 *pDesc, DynamicTexture *pResource, MTLD3D11Device *pDevice) : SRVBase(pDesc, pResource, pDevice) { this->texture_ = pResource->texture_.ptr(); - this->view_id_ = view_key; + this->view_id_ = this->texture_->createView(descriptor); + this->subset_ = ResourceSubsetState( + &descriptor, + this->texture_->miplevelCount(), + this->texture_->arrayLength() + ); } }; @@ -85,8 +90,7 @@ class DynamicTexture : public TResourceBase { if (!ppView) { return S_FALSE; } - TextureViewKey key = this->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 01227e698..8756b013a 100644 --- a/src/d3d11/d3d11_texture_linear.cpp +++ b/src/d3d11/d3d11_texture_linear.cpp @@ -23,10 +23,15 @@ class TDynamicLinearTexture : public TResourceBase { class SRV : public SRVBase { public: SRV(const tag_shader_resource_view<>::DESC1 *pDesc, TDynamicLinearTexture *pResource, MTLD3D11Device *pDevice, - TextureViewKey view_key) : + const TextureViewDescriptor &descriptor) : SRVBase(pDesc, pResource, pDevice) { this->texture_ = pResource->texture_.ptr(); - this->view_id_ = view_key; + this->view_id_ = this->texture_->createView(descriptor); + this->subset_ = ResourceSubsetState( + &descriptor, + this->texture_->miplevelCount(), + this->texture_->arrayLength() + ); } ~SRV() {} @@ -105,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; @@ -144,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 119cce0e9..63d0f1e3d 100644 --- a/src/d3d11/d3d11_view.hpp +++ b/src/d3d11/d3d11_view.hpp @@ -1,6 +1,8 @@ #pragma once +#include "com/com_pointer.hpp" #include "d3d11_3.h" #include "dxmt_buffer.hpp" +#include "dxmt_subresource.hpp" #include "dxmt_texture.hpp" struct MTL_RENDER_PASS_ATTACHMENT_DESC { @@ -13,11 +15,16 @@ struct MTL_RENDER_PASS_ATTACHMENT_DESC { namespace dxmt { +struct D3D11ResourceCommon; + struct D3D11ShaderResourceView : ID3D11ShaderResourceView1 { + Com resource_{}; Buffer *buffer_{}; BufferSlice slice_{}; Texture *texture_{}; unsigned view_id_{}; + ResourceSubsetState subset_{}; + uint32_t bind_flags_{}; Rc buffer() const { @@ -35,14 +42,25 @@ struct D3D11ShaderResourceView : ID3D11ShaderResourceView1 { 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 { + Com resource_{}; Buffer *buffer_{}; BufferSlice slice_{}; Texture *texture_{}; unsigned view_id_{}; Rc counter_; + ResourceSubsetState subset_{}; + uint32_t bind_flags_{}; Rc buffer() const { @@ -64,13 +82,19 @@ struct D3D11UnorderedAccessView : ID3D11UnorderedAccessView1 { counter() const { return counter_; }; + uint32_t bindFlags() const { + return bind_flags_; + } }; struct D3D11RenderTargetView : ID3D11RenderTargetView1 { + 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 { @@ -88,15 +112,21 @@ struct D3D11RenderTargetView : ID3D11RenderTargetView1 { viewId() const { return view_id_; }; + uint32_t bindFlags() const { + return bind_flags_; + } }; struct D3D11DepthStencilView : ID3D11DepthStencilView { + 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 { @@ -122,5 +152,15 @@ struct D3D11DepthStencilView : ID3D11DepthStencilView { 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_); +} + } From 5db4a0ffc1799ac9985fc18ecce209c015fc7cdf Mon Sep 17 00:00:00 2001 From: Feifan He Date: Fri, 3 Apr 2026 21:33:27 +0800 Subject: [PATCH 08/11] feat(d3d11): implement d3d11 hazard tracking for OM & CS --- src/d3d11/d3d11_context_impl.cpp | 311 +++++++++++++++++++++++------- src/d3d11/d3d11_context_state.hpp | 2 + src/d3d11/d3d11_resource.hpp | 8 + src/d3d11/d3d11_view.hpp | 17 ++ 4 files changed, 272 insertions(+), 66 deletions(-) diff --git a/src/d3d11/d3d11_context_impl.cpp b/src/d3d11/d3d11_context_impl.cpp index f30d3150b..fa806475e 100644 --- a/src/d3d11/d3d11_context_impl.cpp +++ b/src/d3d11/d3d11_context_impl.cpp @@ -2374,7 +2374,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 @@ -2525,6 +2575,100 @@ 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; + + // TODO: iterate _hazard_ set rather than _bound_ set (former is a subset) + for (const auto & [Slot, Bound] : SRVs) { + if (CheckOverlap(Bound.SRV.ptr(), pViewOrBuffer)) { + if (SRVs.unbind(Slot)) { + EmitST([=](ArgumentEncodingContext& enc) { + enc.bindBuffer(Slot, {}, 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 +2678,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 +2697,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 +2711,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 +2722,52 @@ 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); + } 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 +3365,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,7 +3423,7 @@ 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); if (!replaced) @@ -3285,69 +3527,6 @@ 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 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 6c42ec237..9a94e41dc 100644 --- a/src/d3d11/d3d11_resource.hpp +++ b/src/d3d11/d3d11_resource.hpp @@ -144,6 +144,14 @@ struct D3D11ResourceCommon : ID3D11Resource { 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 diff --git a/src/d3d11/d3d11_view.hpp b/src/d3d11/d3d11_view.hpp index 63d0f1e3d..41b57c234 100644 --- a/src/d3d11/d3d11_view.hpp +++ b/src/d3d11/d3d11_view.hpp @@ -163,4 +163,21 @@ 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; +} + } From e1d518196f20dd5e41e00ab812fc905400fe041c Mon Sep 17 00:00:00 2001 From: Feifan He Date: Mon, 6 Apr 2026 03:04:51 +0800 Subject: [PATCH 09/11] feat(d3d11): implement d3d11 hazard tracking for IA & SO --- src/d3d11/d3d11_context_impl.cpp | 116 ++++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 8 deletions(-) diff --git a/src/d3d11/d3d11_context_impl.cpp b/src/d3d11/d3d11_context_impl.cpp index fa806475e..bd61b78bd 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); } @@ -2658,6 +2691,39 @@ template class MTLD3D11DeviceContextImplBase : p 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) { + // TODO: iterate _hazard_ set rather than _bound_ set (former is a subset) + for (const auto &[Slot, Bound] : state_.InputAssembler.VertexBuffers) { + 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) { @@ -2755,6 +2821,7 @@ template class MTLD3D11DeviceContextImplBase : p } OMResolveSRVHazard(pUAV); + ResolveIAHazard(pUAV); } else { if (UAVs.unbind(Slot)) { EmitST([=](ArgumentEncodingContext &enc) { @@ -3530,6 +3597,39 @@ template class MTLD3D11DeviceContextImplBase : p #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; + } + } + + return true; + } + void SetVertexBuffers( UINT StartSlot, UINT NumBuffers, ID3D11Buffer *const *ppVertexBuffers, const UINT *pStrides, const UINT *pOffsets @@ -3538,8 +3638,8 @@ 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); if (!replaced) { @@ -3569,7 +3669,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)); From 78cfaf518d431237a3debad4979bfeae0d953ad4 Mon Sep 17 00:00:00 2001 From: Feifan He Date: Mon, 6 Apr 2026 06:05:58 +0800 Subject: [PATCH 10/11] refactor(dxmt): improve binding bitset iteration performance --- src/dxmt/dxmt_binding_set.hpp | 47 +++++++++++++++++++++-------------- src/util/util_bit.hpp | 2 ++ 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/dxmt/dxmt_binding_set.hpp b/src/dxmt/dxmt_binding_set.hpp index c0833eadd..451d9238b 100644 --- a/src/dxmt/dxmt_binding_set.hpp +++ b/src/dxmt/dxmt_binding_set.hpp @@ -59,22 +59,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 +84,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 @@ -157,13 +157,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 +183,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 +210,18 @@ 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; } }; } // namespace dxmt \ No newline at end of file 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; } From 233ab4e413b6d59fb9906e06ca904b297d9b49a4 Mon Sep 17 00:00:00 2001 From: Feifan He Date: Mon, 6 Apr 2026 06:11:42 +0800 Subject: [PATCH 11/11] feat(d3d11, dxmt): record potential hazard info in binding bitset Since not all bound resource may introduce hazard, it would be a even sparser set. --- src/d3d11/d3d11_context_impl.cpp | 13 +++++++------ src/dxmt/dxmt_binding_set.hpp | 16 +++++++++++++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/d3d11/d3d11_context_impl.cpp b/src/d3d11/d3d11_context_impl.cpp index bd61b78bd..b251e3aad 100644 --- a/src/d3d11/d3d11_context_impl.cpp +++ b/src/d3d11/d3d11_context_impl.cpp @@ -2676,8 +2676,8 @@ template class MTLD3D11DeviceContextImplBase : p auto &SRVs = state_.ShaderStages[Stage].SRVs; - // TODO: iterate _hazard_ set rather than _bound_ set (former is a subset) - for (const auto & [Slot, Bound] : 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) { @@ -2710,8 +2710,9 @@ template class MTLD3D11DeviceContextImplBase : p } if (pViewOrBuffer->bindFlags() & D3D11_BIND_VERTEX_BUFFER) { - // TODO: iterate _hazard_ set rather than _bound_ set (former is a subset) - for (const auto &[Slot, Bound] : state_.InputAssembler.VertexBuffers) { + 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, {}); }); @@ -3492,7 +3493,7 @@ template class MTLD3D11DeviceContextImplBase : p auto pView = static_cast(ppShaderResourceViews[slot - StartSlot]); 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; @@ -3641,7 +3642,7 @@ template class MTLD3D11DeviceContextImplBase : p 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); diff --git a/src/dxmt/dxmt_binding_set.hpp b/src/dxmt/dxmt_binding_set.hpp index 451d9238b..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; } @@ -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; } @@ -223,5 +228,14 @@ template class BindingSet { end() const { 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