Skip to content

chore(debug): name D3D11 resources for RenderDoc#2209

Merged
doodlum merged 1 commit into
community-shaders:devfrom
alandtse:feat/d3d-resource-names
Apr 26, 2026
Merged

chore(debug): name D3D11 resources for RenderDoc#2209
doodlum merged 1 commit into
community-shaders:devfrom
alandtse:feat/d3d-resource-names

Conversation

@alandtse
Copy link
Copy Markdown
Collaborator

@alandtse alandtse commented Apr 26, 2026

All D3D11 resources created by Community Shaders now carry a descriptive debug name via SetPrivateData(WKPDID_D3DDebugObjectName), so they appear as e.g. "SSGI::Radiance SRV" in RenderDoc instead of generic indices like "Texture #47".

Changes:

  • Buffer.h: add optional name parameter to all wrapper class constructors (ConstantBuffer, StructuredBuffer, Buffer, Texture1D, Texture2D, Texture3D); view creation methods (CreateSRV/UAV/RTV/DSV) automatically append " SRV" / " UAV" etc. to the base name. detail::SetD3DName delegates to Util::SetResourceName via a forward declaration, keeping the GUID definition in one place (D3D.cpp).
  • Util::SetResourceName used directly for raw device->Create* objects (samplers, blend states, depth-stencil states, rasterizer states, raw RTVs/SRVs not owned by a wrapper) across: Deferred, CloudShadows, DynamicCubemaps, VolumetricShadows, ScreenSpaceGI, ScreenSpaceShadows, Skylighting, TerrainBlending, TerrainShadows, LightLimitFix, GrassCollision, HairSpecular, HDRDisplay, IBL, VR, VRStereoOpt, VR::StereoBlend, VR::InSceneOverlay, BackgroundBlur, IconLoader, Utils::UI.
  • .claude/CLAUDE.md: add DRY pitfall note for cross-cutting refactors.

No behaviour change; naming calls are init-time only with zero per-frame overhead.

Summary by CodeRabbit

  • Refactor
    • Enhanced resource naming conventions throughout the graphics framework.
    • Updated buffer and texture constructors to support optional resource labeling parameters.
    • Added systematic naming infrastructure for dynamically created graphics resources across multiple feature modules.
    • Established centralized utility patterns for resource identification.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 26, 2026

📝 Walkthrough

Walkthrough

This PR systematically adds debug naming support for Direct3D 11 resources across the codebase. It extends buffer and texture constructors with optional name parameters, introduces a detail::SetD3DName helper function, and calls Util::SetResourceName throughout resource creation paths to label GPU objects for RenderDoc debugging.

Changes

Cohort / File(s) Summary
Documentation
.claude/CLAUDE.md
Adds two new D3D11 development guidelines: one enforces canonical resource-naming via Util::SetResourceName in Utils/D3D.cpp, and another establishes a DRY rule requiring refactors to use forward declarations instead of duplicating utility patterns.
Buffer & Texture API
src/Buffer.h
Extends constructors for ConstantBuffer, StructuredBuffer, Buffer, Texture1D, Texture2D, and Texture3D with optional name parameter (default nullptr). Adds detail::SetD3DName helper and std::string name_ member storage. Updates view-creation methods (CreateSRV, CreateUAV, CreateRTV, CreateDSV) to auto-name created D3D views using stored name_ plus fixed suffixes.
Deferred Rendering & Core Features
src/Deferred.cpp, src/Features/CloudShadows.cpp, src/Features/DynamicCubemaps.cpp, src/Features/GrassCollision.cpp, src/Features/HDRDisplay.cpp, src/Features/HairSpecular.cpp, src/Features/IBL.cpp, src/Features/LightLimitFix.cpp
Consistently apply resource naming: pass explicit name strings to Buffer/Texture* constructors and call Util::SetResourceName for sampler states and blend/depth-stencil states. Includes Utils/D3D.h where needed.
Advanced Features
src/Features/ScreenSpaceGI.cpp, src/Features/ScreenSpaceShadows.cpp, src/Features/Skylighting.cpp, src/Features/TerrainBlending.cpp, src/Features/TerrainShadows.cpp, src/Features/VR.cpp, src/Features/VR/InSceneOverlay.cpp, src/Features/VR/StereoBlend.cpp, src/Features/VRStereoOptimizations.cpp, src/Features/VolumetricShadows.cpp
Apply debug naming to constant buffers, textures, samplers, and state objects. Per-mip UAVs receive indexed name strings. SRV/UAV creation is immediately followed by Util::SetResourceName calls.
UI & Menu Systems
src/Menu/BackgroundBlur.cpp, src/Menu/IconLoader.cpp, src/Utils/UI.cpp
Add resource naming to blur/window constant buffers, blend states, rasterizer states, loaded textures, and DDS shader resource views using filename/context-based identifiers.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • doodlum
  • jiayev

Poem

🐰 Naming resources now, for clarity's sake,
Every D3D object gets a label awake,
RenderDoc debugs with joy and delight,
GPU resources shine ever so bright!
A hop through the code, and the naming's done right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'chore(debug): name D3D11 resources for RenderDoc' directly and clearly summarizes the main change: adding debug names to D3D11 resources for RenderDoc visualization. It is specific, concise, and accurately represents the primary objective of the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

No actionable suggestions for changed features.

All D3D11 resources created by Community Shaders now carry a
descriptive debug name via SetPrivateData(WKPDID_D3DDebugObjectName),
so they appear as e.g. "SSGI::Radiance SRV" in RenderDoc instead
of generic indices like "Texture community-shaders#47".

Changes:
- Buffer.h: add optional `name` parameter to all wrapper class
  constructors (ConstantBuffer, StructuredBuffer, Buffer, Texture1D,
  Texture2D, Texture3D); view creation methods (CreateSRV/UAV/RTV/DSV)
  automatically append " SRV" / " UAV" etc. to the base name.
  detail::SetD3DName delegates to Util::SetResourceName via a forward
  declaration, keeping the GUID definition in one place (D3D.cpp).
- Util::SetResourceName used directly for raw device->Create* objects
  (samplers, blend states, depth-stencil states, rasterizer states,
  raw RTVs/SRVs not owned by a wrapper) across: Deferred, CloudShadows,
  DynamicCubemaps, VolumetricShadows, ScreenSpaceGI, ScreenSpaceShadows,
  Skylighting, TerrainBlending, TerrainShadows, LightLimitFix,
  GrassCollision, HairSpecular, HDRDisplay, IBL, VR, VRStereoOpt,
  VR::StereoBlend, VR::InSceneOverlay, BackgroundBlur, IconLoader,
  Utils::UI.
- .claude/CLAUDE.md: document D3D resource naming convention and
  add DRY pitfall note for cross-cutting refactors.

No behaviour change; naming calls are init-time only with zero
per-frame overhead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@alandtse alandtse force-pushed the feat/d3d-resource-names branch from e97b661 to 19e53f3 Compare April 26, 2026 09:52
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
src/Buffer.h (1)

128-128: Optional: add explicit for consistency.

StructuredBuffer's 2-required-arg constructor is the only wrapper not marked explicit after this change. Not user-visible, just a small consistency nit alongside ConstantBuffer/Buffer/Texture* which all gained explicit in this PR.

♻️ Optional consistency tweak
-	StructuredBuffer(D3D11_BUFFER_DESC const& a_desc, UINT a_count, const char* name = nullptr) :
+	explicit StructuredBuffer(D3D11_BUFFER_DESC const& a_desc, UINT a_count, const char* name = nullptr) :
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Buffer.h` at line 128, The StructuredBuffer constructor overload
StructuredBuffer(D3D11_BUFFER_DESC const& a_desc, UINT a_count, const char* name
= nullptr) is missing the explicit keyword for consistency with other wrappers;
mark this constructor explicit to prevent unintended implicit conversions and
match ConstantBuffer/Buffer/Texture* constructors.
src/Features/VRStereoOptimizations.cpp (1)

177-177: Consider naming stencilWriteRS for full pass-state visibility.

You named stencilWriteDSS; adding a name for the rasterizer state would complete this stencil pass’s RenderDoc metadata.

Suggested patch
 		DX::ThrowIfFailed(device->CreateRasterizerState(&rsDesc, stencilWriteRS.put()));
+		Util::SetResourceName(stencilWriteRS.get(), "VRStereoOpt::StencilWriteRS");
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Features/VRStereoOptimizations.cpp` at line 177, The stencil pass
currently names only the depth-stencil state (stencilWriteDSS); add a
corresponding SetResourceName call for the rasterizer state (stencilWriteRS) so
RenderDoc shows full pass-state metadata—locate where stencilWriteDSS is named
and call Util::SetResourceName(stencilWriteRS.get(),
"VRStereoOpt::StencilWriteRS") (or similar consistent label) to match naming
convention.
src/Features/IBL.cpp (1)

329-329: Recommend naming envIBLTexture and skyIBLTexture too for full IBL coverage.

In the same setup path, Line 297 and Line 300 still construct unnamed textures.

Suggested patch
-		envIBLTexture = new Texture2D(texDesc);
+		envIBLTexture = new Texture2D(texDesc, "IBL::EnvIBL");
 		envIBLTexture->CreateSRV(srvDesc);
 		envIBLTexture->CreateUAV(uavDesc);
-		skyIBLTexture = new Texture2D(texDesc);
+		skyIBLTexture = new Texture2D(texDesc, "IBL::SkyIBL");
 		skyIBLTexture->CreateSRV(srvDesc);
 		skyIBLTexture->CreateUAV(uavDesc);

Also applies to: 365-365

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Features/IBL.cpp` at line 329, Several IBL textures are constructed
without descriptive names; update the unnamed Texture2D constructions so they
use explicit labels similar to staticDiffuseIBLTexture. Locate the Texture2D
creations (e.g., the existing staticDiffuseIBLTexture =
eastl::make_unique<Texture2D>(... , "IBL::StaticDiffuse")) and change the other
two unnamed instances to create envIBLTexture and skyIBLTexture using
eastl::make_unique<Texture2D>(reinterpret_cast<ID3D11Texture2D*>(pResource),
"IBL::Env") and
eastl::make_unique<Texture2D>(reinterpret_cast<ID3D11Texture2D*>(pResource),
"IBL::Sky") respectively (also apply the same naming fix at the other occurrence
around the later block noted in the comment).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/Buffer.h`:
- Line 128: The StructuredBuffer constructor overload
StructuredBuffer(D3D11_BUFFER_DESC const& a_desc, UINT a_count, const char* name
= nullptr) is missing the explicit keyword for consistency with other wrappers;
mark this constructor explicit to prevent unintended implicit conversions and
match ConstantBuffer/Buffer/Texture* constructors.

In `@src/Features/IBL.cpp`:
- Line 329: Several IBL textures are constructed without descriptive names;
update the unnamed Texture2D constructions so they use explicit labels similar
to staticDiffuseIBLTexture. Locate the Texture2D creations (e.g., the existing
staticDiffuseIBLTexture = eastl::make_unique<Texture2D>(... ,
"IBL::StaticDiffuse")) and change the other two unnamed instances to create
envIBLTexture and skyIBLTexture using
eastl::make_unique<Texture2D>(reinterpret_cast<ID3D11Texture2D*>(pResource),
"IBL::Env") and
eastl::make_unique<Texture2D>(reinterpret_cast<ID3D11Texture2D*>(pResource),
"IBL::Sky") respectively (also apply the same naming fix at the other occurrence
around the later block noted in the comment).

In `@src/Features/VRStereoOptimizations.cpp`:
- Line 177: The stencil pass currently names only the depth-stencil state
(stencilWriteDSS); add a corresponding SetResourceName call for the rasterizer
state (stencilWriteRS) so RenderDoc shows full pass-state metadata—locate where
stencilWriteDSS is named and call Util::SetResourceName(stencilWriteRS.get(),
"VRStereoOpt::StencilWriteRS") (or similar consistent label) to match naming
convention.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 57b9bca5-dfa1-4444-973d-b07d48ee09a7

📥 Commits

Reviewing files that changed from the base of the PR and between 022631b and e97b661.

📒 Files selected for processing (24)
  • .claude/CLAUDE.md
  • extern/CommonLibSSE-NG
  • src/Buffer.h
  • src/Deferred.cpp
  • src/Features/CloudShadows.cpp
  • src/Features/DynamicCubemaps.cpp
  • src/Features/GrassCollision.cpp
  • src/Features/HDRDisplay.cpp
  • src/Features/HairSpecular.cpp
  • src/Features/IBL.cpp
  • src/Features/LightLimitFix.cpp
  • src/Features/ScreenSpaceGI.cpp
  • src/Features/ScreenSpaceShadows.cpp
  • src/Features/Skylighting.cpp
  • src/Features/TerrainBlending.cpp
  • src/Features/TerrainShadows.cpp
  • src/Features/VR.cpp
  • src/Features/VR/InSceneOverlay.cpp
  • src/Features/VR/StereoBlend.cpp
  • src/Features/VRStereoOptimizations.cpp
  • src/Features/VolumetricShadows.cpp
  • src/Menu/BackgroundBlur.cpp
  • src/Menu/IconLoader.cpp
  • src/Utils/UI.cpp

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/Menu/IconLoader.cpp (1)

57-57: Optional: trim filename to a leaf path for RenderDoc readability.

filename here is the full absolute path that was passed into LoadTextureFromFile (e.g. …\Data\…\Icons\Action Icons\save-settings.png), so the resulting debug names will be very long. Using std::filesystem::path(filename).filename().string() (or the relative portion under the icons root) would yield friendlier labels like IconLoader::save-settings.png / IconLoader::save-settings.png SRV without changing behavior.

Also applies to: 79-79

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Menu/IconLoader.cpp` at line 57, The debug resource name uses the full
absolute path in Util::SetResourceName, making RenderDoc labels unwieldy; in the
LoadTextureFromFile call site (where Util::SetResourceName is invoked) trim
filename to its leaf name before passing it to Util::SetResourceName (e.g.
compute std::filesystem::path(filename).filename().string() or the relative path
under your icons root) and use that trimmed string for both the main name and
the SRV variant so labels like "IconLoader::save-settings.png" are emitted;
update both occurrences around the Util::SetResourceName calls (including the
SRV name at the other call site) to use the trimmed filename variable.
src/Features/DynamicCubemaps.cpp (1)

674-708: Several core cubemap textures left unnamed.

The capture/env textures created here (envCaptureTexture, envCaptureRawTexture, envCapturePositionTexture, envCaptureReflectionsTexture, envCaptureRawReflectionsTexture, envCapturePositionReflectionsTexture, envTexture, envReflectionsTexture) still use the no-name Texture2D(texDesc) constructor, while envInferredTexture, bc6hScratchTexture, and the BC6H targets do get explicit names. These eight textures are the ones you most often want to identify in RenderDoc when debugging cubemap capture/inferrence/irradiance, so leaving them anonymous partially defeats the PR's goal for this module.

♻️ Proposed naming additions
-		envCaptureTexture = new Texture2D(texDesc);
+		envCaptureTexture = new Texture2D(texDesc, "DynamicCubemaps::EnvCapture");
 		envCaptureTexture->CreateSRV(srvDesc);
 		envCaptureTexture->CreateUAV(uavDesc);

-		envCaptureRawTexture = new Texture2D(texDesc);
+		envCaptureRawTexture = new Texture2D(texDesc, "DynamicCubemaps::EnvCaptureRaw");
 		envCaptureRawTexture->CreateSRV(srvDesc);
 		envCaptureRawTexture->CreateUAV(uavDesc);

-		envCapturePositionTexture = new Texture2D(texDesc);
+		envCapturePositionTexture = new Texture2D(texDesc, "DynamicCubemaps::EnvCapturePosition");
 		envCapturePositionTexture->CreateSRV(srvDesc);
 		envCapturePositionTexture->CreateUAV(uavDesc);

-		envCaptureReflectionsTexture = new Texture2D(texDesc);
+		envCaptureReflectionsTexture = new Texture2D(texDesc, "DynamicCubemaps::EnvCaptureReflections");
 		envCaptureReflectionsTexture->CreateSRV(srvDesc);
 		envCaptureReflectionsTexture->CreateUAV(uavDesc);

-		envCaptureRawReflectionsTexture = new Texture2D(texDesc);
+		envCaptureRawReflectionsTexture = new Texture2D(texDesc, "DynamicCubemaps::EnvCaptureRawReflections");
 		envCaptureRawReflectionsTexture->CreateSRV(srvDesc);
 		envCaptureRawReflectionsTexture->CreateUAV(uavDesc);

-		envCapturePositionReflectionsTexture = new Texture2D(texDesc);
+		envCapturePositionReflectionsTexture = new Texture2D(texDesc, "DynamicCubemaps::EnvCapturePositionReflections");
 		envCapturePositionReflectionsTexture->CreateSRV(srvDesc);
 		envCapturePositionReflectionsTexture->CreateUAV(uavDesc);
@@
-		envTexture = new Texture2D(texDesc);
+		envTexture = new Texture2D(texDesc, "DynamicCubemaps::EnvTexture");
 		envTexture->CreateSRV(srvDesc);
 		envTexture->CreateUAV(uavDesc);

-		envReflectionsTexture = new Texture2D(texDesc);
+		envReflectionsTexture = new Texture2D(texDesc, "DynamicCubemaps::EnvReflections");
 		envReflectionsTexture->CreateSRV(srvDesc);
 		envReflectionsTexture->CreateUAV(uavDesc);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Features/DynamicCubemaps.cpp` around lines 674 - 708, The eight cubemap
textures (envCaptureTexture, envCaptureRawTexture, envCapturePositionTexture,
envCaptureReflectionsTexture, envCaptureRawReflectionsTexture,
envCapturePositionReflectionsTexture, envTexture, envReflectionsTexture) are
created with the anonymous Texture2D(texDesc) constructor—give each a
descriptive debug name so they show up in RenderDoc; update their construction
to use the same naming approach used for envInferredTexture/bc6hScratchTexture
(e.g., pass a name string into the Texture2D constructor or call the engine's
SetName/SetDebugName method right after creation) so each Texture2D instance is
uniquely named when CreateSRV/CreateUAV are called.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/Features/DynamicCubemaps.cpp`:
- Around line 674-708: The eight cubemap textures (envCaptureTexture,
envCaptureRawTexture, envCapturePositionTexture, envCaptureReflectionsTexture,
envCaptureRawReflectionsTexture, envCapturePositionReflectionsTexture,
envTexture, envReflectionsTexture) are created with the anonymous
Texture2D(texDesc) constructor—give each a descriptive debug name so they show
up in RenderDoc; update their construction to use the same naming approach used
for envInferredTexture/bc6hScratchTexture (e.g., pass a name string into the
Texture2D constructor or call the engine's SetName/SetDebugName method right
after creation) so each Texture2D instance is uniquely named when
CreateSRV/CreateUAV are called.

In `@src/Menu/IconLoader.cpp`:
- Line 57: The debug resource name uses the full absolute path in
Util::SetResourceName, making RenderDoc labels unwieldy; in the
LoadTextureFromFile call site (where Util::SetResourceName is invoked) trim
filename to its leaf name before passing it to Util::SetResourceName (e.g.
compute std::filesystem::path(filename).filename().string() or the relative path
under your icons root) and use that trimmed string for both the main name and
the SRV variant so labels like "IconLoader::save-settings.png" are emitted;
update both occurrences around the Util::SetResourceName calls (including the
SRV name at the other call site) to use the trimmed filename variable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: be996976-92ee-416e-b798-b6ba2fe729e8

📥 Commits

Reviewing files that changed from the base of the PR and between e97b661 and 19e53f3.

📒 Files selected for processing (23)
  • .claude/CLAUDE.md
  • src/Buffer.h
  • src/Deferred.cpp
  • src/Features/CloudShadows.cpp
  • src/Features/DynamicCubemaps.cpp
  • src/Features/GrassCollision.cpp
  • src/Features/HDRDisplay.cpp
  • src/Features/HairSpecular.cpp
  • src/Features/IBL.cpp
  • src/Features/LightLimitFix.cpp
  • src/Features/ScreenSpaceGI.cpp
  • src/Features/ScreenSpaceShadows.cpp
  • src/Features/Skylighting.cpp
  • src/Features/TerrainBlending.cpp
  • src/Features/TerrainShadows.cpp
  • src/Features/VR.cpp
  • src/Features/VR/InSceneOverlay.cpp
  • src/Features/VR/StereoBlend.cpp
  • src/Features/VRStereoOptimizations.cpp
  • src/Features/VolumetricShadows.cpp
  • src/Menu/BackgroundBlur.cpp
  • src/Menu/IconLoader.cpp
  • src/Utils/UI.cpp
✅ Files skipped from review due to trivial changes (13)
  • src/Features/VR/StereoBlend.cpp
  • src/Features/VR/InSceneOverlay.cpp
  • .claude/CLAUDE.md
  • src/Features/ScreenSpaceShadows.cpp
  • src/Features/VRStereoOptimizations.cpp
  • src/Features/HDRDisplay.cpp
  • src/Menu/BackgroundBlur.cpp
  • src/Features/VolumetricShadows.cpp
  • src/Features/IBL.cpp
  • src/Features/LightLimitFix.cpp
  • src/Features/TerrainBlending.cpp
  • src/Features/TerrainShadows.cpp
  • src/Features/ScreenSpaceGI.cpp
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/Features/GrassCollision.cpp
  • src/Features/VR.cpp
  • src/Deferred.cpp
  • src/Buffer.h

@github-actions
Copy link
Copy Markdown

✅ A pre-release build is available for this PR:
Download

@doodlum doodlum merged commit 068f624 into community-shaders:dev Apr 26, 2026
14 checks passed
ParticleTroned pushed a commit to ParticleTroned/skyrim-community-shaders that referenced this pull request May 2, 2026
)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 068f624)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants