Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for D3D11 #1698

Open
wants to merge 54 commits into
base: dev
Choose a base branch
from
Open

Initial support for D3D11 #1698

wants to merge 54 commits into from

Conversation

dgraves
Copy link
Contributor

@dgraves dgraves commented Aug 30, 2024

This is the code that was originally submitted as #1267, adding support for D3D11, rebased on the latest dev branch with some additional bug fixes and enhancements.

dgraves and others added 26 commits August 30, 2024 09:01
Ensure that anonymous union names processed by CppHeaderParser are
globally unique to avoid conflicts between anonymous unions defined in
separate header files.
Updates to DX12 code generators to enable support for DX11, starting
with the generated encoding code. Adds the DX11 header files for
versions up to 11.0, 11.1, and 11.2 to the list of files to be processed
by the DX code generator. Includes updates for DX11-specific syntax,
types, and SAL annotations.
Ignore anonymous structs when generating API calls to process struct
types.
Add D3D11_VIDEO_PROCESSOR_COLOR_SPACE to BIT_FIELD_LIST.
- Handle union decoding, with unions being treated as structs.
- Handle 'get' functions that retrieve objects without returning an
  HRESULT value.
- Handle object mapping for structs that contain arrays of objects.
Add DX11 bitmask enums to the enum to string code generator's BITS_LIST
list.
- Add DX11 dispatch table
- Support encoding for API calls that create objects without returning
  an HRESULT value
- Add info structures for D3D11 objects
- Add a non-const overload for UnwrapObjects.
Custom encoding and decoding for unions and API calls receive resource
data, requiring a special data size calculation.
- Add JSON conversion routine for HandlePointerDecoder value types,
  operating on a const reference.
Update code generation to allocate output data for output pointers.
Implement the same GetOutputPointer and AllocateOutputData interface
used with PointerDecoder for replay of API calls with output parameters
to BasicStringDecoder for D3D11 API calls that return strings with
output parameters.
Update the DX code generators to treat INOUT parameters as OUT
parameters. All INOUT parameters are pointers to integers that specify
and retrieve sizes for variable length arrays, where the input is the
size of the array and the output is the total number of items copied to
the array.
D3D output parameters with a SAL labl including the text
'result_bytebuffer' and a size appear similar to arrays of bytes but are
really a pointer to memory allocated internally by the implementation
with the specified size. For this case, the following adjustments are
made for capture and replay, where capture will continue to record the
content of the retrieved memory and replay will allocate and retrieve a
single pointer to the memory.
- Update encoding for this case, where the type is void**, to
  dereference the pointer when invoking EncodeVoidArray.
- Update replay to decode the array of bytes, but allocate a single
  pointer parameter for API call replay, using PointerDecoder<uint8_,
  void*> to represent the parameter.
With D3D12, all functions that retrieve a COM object also return
HRESULT. With D3D11, there are some functions that retrieve a COM object
while returning void. The code generator has been updated to handle this
case, generating calls to AddObject() for the COM objects retrieved by
functions that don't return an HRESULT value.
Implement the proxy d3d11.dll, with intialization and release functions
added to the core d3d12_capture.dll module.
Add the D3D11 API ID to the decoder's list of supported API IDs.
Add capture/replay support for resource uploads.
Add Map/Unmap overrides to track mapped resource pointers.
If GetData returned S_OK at capture and S_FALSE at replay, continue
calling GetData until it returns S_OK or an error code.
- Add d3d11_3.h to codegen header list.
- Add custom struct encoders for new union types.
- Add custom API call encode/decode for new resource creation functions.
- Add d3d11_4.h to codegen header list.
- Update enum to string generator to handle an aliasing case with YUV
  and RGB flags.
Add custom d3d11 object wrapper generator for the ID3D11Resource object,
which can be retrieved from a view and must be wrapped.
Update D3D12 repolay code generator to apply the same variable sized
output array adjustment that is used for Vulkan. For API calls that have
an optional output array parameter and a porinter to an integer size
parameter, when the array parameter is NULL, store the retrieved size in
the calling objects info struct, and then when the API call is made with
a non-NULL array parameter, specify the size stored in the info struct
when allocating the output array.
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 246453.

@dgraves
Copy link
Contributor Author

dgraves commented Aug 30, 2024

This branch includes all of the changes that I am currently using with D3D11 capture. Some of them apply more generally to D3D, which I will try to break out into separate PRs.

Add support for arrays of COM pointers to the replay consumer code
generator:
- Handle output arrays of COM pointers, adding them to the object table.
- Support variable length arrays of output COM pointers.
Update code generation to add a null check when dereferencing
a pointer to an array size when encoding array data during capture and
allocating array memory during replay. Added for cases where both the
variable length array parameter and its associated size parameter are
optional and are allowed to be null.
- Add external object handling for the software rendering module handle
  parameter from D3D11CreateDevice, warning when the handle is not null.
- Silence the CreateSwapchain warning that is printed when the IUnknown
  pointer cannot be converted to a D3D12 queue, if it is an ID3D11Device
  object.
ID3D11View_Wrapper now holds an internal reference to its associated
ID3D11Resource_wrapper, ensuring the wrapper is always valid so that
the data stored in the wrapper is not lost if the resource is released
and then later retrieved with ID3D11View::GetResource().
Update object array size assert to check both that the size parameter
matches the decoded array size, or that the size parameter is -1, which
has a special meaning for D3D11 APIs such as
OMSetRenderTargetsAndUnorderedAccessViews to indicate that the RTVs and
DSV should be preserved.
- Store the ID3D11Device pointer in the swap chain info struct for
  D3D11.
- Support internal reference counts for swap chain images acquired from
  swap chains chreated with the DISCARD and SEQUENTIAL swap effects.
- Handle different FLIP_DISCARD behavior for D3D11, which behaves the
  same way as DISCARD.
- Adjust child image tracking for cases that only allow the image at
  index 0 to be acquired (DISCARD and D3D11+FLIP_DISCARD).
When a texture is created with MipLevels = 0, a full set of subtextures
will be generated. The following has been added to support this case:
- New utility function to calculate the number of mip levels from the
  texture creation parameters when MipLevels is specified as 0.
- Updated utility functions that calculate the total number of
  subresources and individual subresource sizes from texture creation
  parameters to compute the total number of mip levels when MipLevels =
  0.
Update capture to support the following mapped mempry case:
- Game calls Map with WRITE_DISCARD flag without ever calling Unmap,
  calling Map to retrieve a new allocation when the previous allocation
  is full.

This involves the following:
- Process mapped memory before draw/dispatch to ensure any writes are
  properly recorded.
- On repeated calls to Map with WRITE_DISCARD, update the entry for the
  resource in the mapped memory tracker for the new allocation
  returned by the driver.
Add initialization for swapchain objects created by
D3D11CreateDeviceAndSwapChain.
- Add custom post call capture action to pre-acquire swapchain images.
- Add replay override to initialize swapchain info.
Force enable the D3D11 debug layer for capture and replay, based on
the associated capture/replay debug option.
Update ProcessFillMemoryCommand() to support copies for 1D, 2D, and 3D
textures with different capture and replay row and/or depth alignments.
- Adds a new DX11ImageRenderer class to generate screenshots for DX11
  captures. Code that is common to both DX11 and DX12 screenshots was
  moved from the existing DX12ImageRenderer class to a shared base class
  that both DX11ImageRenderer and DX12ImageRenderer inherit from.
- Updates both the capture and replay code responsible for generating
  DX12 screenshots to also support DX11 screenshots. The API to use for
  screenshot generation is determined based on the IDXGISwapChain
  creation parameters, which either include a ID3D12CommandQueue for
  DX12 or an ID3D11Device for DX11.
Leave the persistent memory allocated for the D3D11_WRITE_DISCARD and
D3D11_WRITE_NO_OVERWRITE DX11 map modes in the memory tracking table
until the resources are released. Adds support for updating the
mapped memory ID and pointer stored by PageGuardManager for use with
DX11 resources mapped with the D3D11_MAP_DISCARD flag, which can
return a new allocation for the resource.
- Use separate values for the memory ID written to the capture file
  and the key used with the PageGuardManager table, allowing the ID to
  be updated without needing to add/remove the entry (the ID written
  to the capture file used to be the key).
- Add a new PageGuardManager function to update the memory ID and
  pointer associated with a Resource, used to update the Resource entry
  with the new memory pointer returned with D3D11_MAP_DISCARD.
Update ID3D11Device::CheckFeatureSupport encoding and decoding with
special case processing for the pFeatureSupportData parameter, which has
a void* type with the actual type determined by the accompanying
D3D11_FEATURE parameter. The implementation matches the custom
implementations created for ID3D12Device and IDXGIFactory5.
Specify the API ID to use with metadata encoding as a parameter to the
functions that write metadata instead of as a class member to support
the use of multiple APIs from a single application.
- Write adapter and driver metadata for DX11 at device creation.
- Update gfxrecon-info to collect and display DX11 info.
- Collect all gfxrecon-info stats from a single pass.
- Specify DX11 API ID for adatper metadata.
Adds a new DxFeatureDataDecoder type to encapsulate the
PointerDecoder<T> and StructPointerDecoder<T> types needed to decode
the CheckFeatureSupport pFeatureSupportData parameter in a generic type
that can be provided to DX consumers. Provides the same pointer decoder
interface as PointerDecoder/StructPointerDecoder for managing pointer
data, as well as functions for accessing the internal
PointerDecoder/StructPointerDecoder with a specific type. Also allows
the output allocation to be performed by the consumer instead of the
decoder, which matches the standard consumer behavior.
- Look for the renamed system DLL in the same folder as the capture DLL,
  instead of the same folder as the target executable, before attempting
  to copy and rename the DLL found in the system folder. This allows the
  capture DLL to be installed in locations other than the folder
  containing the target executable.
- Use the shell API to retrieve the path to the system folder, relying
  on the WIN32 API to translate the returned path to the appropriate
  path for the architecture of the current process. This repalces code
  that tried to determine if it should use \Windows\System32 or
  \Windows\SysWOW64 as the system folder. For ARM devices, there are
  additional folders that need to be considered.
- Only copy the D3D12 redist DLL when initializing the D3D12 DLL, not
  when initializing the DXGI and D3D11 DLLs. The redist DLL copy is now
  generic, with the redist DLL name specified by the DLL being
  initialized.
When IDXGISwapChain::ResizeBuffers is called with a width or height
value that is equal to 0, that dimension will be resized to match the
dimension of the client area of the target window. For this case, replay
was resizing the window to have a width/height of 0, resulting in the
client area no longer being visible. This change specifies the
width/height of the window's client area to Window::SetSize, instead of
0, when width/height are 0.
When IDXGISwapChain::ResizeBuffers is called with a width or height
value that is equal to 0, that dimension will be resized to match the
dimension of the client area of the target window. When the stats
consumer used by gfxrecon-info processesed a ResizeBuffers call with
width and height equal to zero, it reported the swap chain size as 0x0.
The stats conusmer has been updated to ignore the ResizeBuffers width
and height with a value of zero when determining swap chain size.
Enable DX11 support for the replay --dx12-override-object-names option.
When ID3D11DeviceContext::UpdateSubresource is called from a deferred
context with a driver that does not support command lists and the
pDstBox parameter is non-null and the pDstBox parameter specifies a
non-zero start offset for the update, the application is required to
subtract the offset from the pSrcData parameter. Capture and replay have
been updated to account for this adjustment. Note that this adjustment
is not required for ID3D11DeviceContext1::UpdateSubresource1.
When calculating the subresource size for block compressed 1D and 3D
textures, apply the same pixel-to-block width/height conversion that
is performed for 2D textures.
Adds a custom mapped memory tracker for DX11 deferred contexts, which
only support mapping resources with the D3D11_MAP_WRITE_DISCARD and
D3D11_MAP_WRITE_NO_OVERWRITE map types. Because these map types only
support writing to mapped memory, meaning that shadow memory would not
need to be synchronized with driver memory for reads, this custom memory
tracker can use write watch with shadow allocations. Write watch-based
tracking eliminates the need for a single exception handler that must be
shared by all contexts, which is required when using guard pages,
allowing each deferred context to have its own independent instance of
the memory tracker. The immediate context continues to use the original
guard page memory tracking as it must process both read and write
operations.
Remove an unconditional cast of the object returned by
IDXGISwapChain::GetBuffer to ID3D12Resource, as this method may return
other resource types.
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 246475.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4734 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4734 failed.

@bradgrantham-lunarg bradgrantham-lunarg added P1 Prevents an important capture from being replayed d3d11 labels Oct 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
d3d11 P1 Prevents an important capture from being replayed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants