Skip to content

Commit e728641

Browse files
Merge branch 'LogicFixes' into 'main'
[REMIX-4811, REMIX-4789, REMIX-4779, REMIX-4827, REMIX-4823] fixing several Remix Logic bugs See merge request lightspeedrtx/dxvk-remix-nv!1837
2 parents 0a6a03b + d6cff15 commit e728641

33 files changed

+575
-165
lines changed

documentation/components/EqualTo.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Returns true if A is equal to B, false otherwise\.<br/><br/>For floating point v
1515
|----------|--------------|------|---------|---------------|----------|
1616
| a | A | NumberOrVector | Input | 0 | No |
1717
| b | B | NumberOrVector | Input | 0 | No |
18+
| tolerance | Tolerance | Float | Input | 0\.00001 | No |
1819

1920
### A
2021

@@ -26,6 +27,11 @@ The first value to compare\.
2627
The second value to compare\.
2728

2829

30+
### Tolerance
31+
32+
The tolerance for rounding errors\. Math operations with floating point values are not exact, so equality comparisons should allow for slightly different values\. If the difference between A and B is less than Tolerance, the result will be true\.
33+
34+
2935
## Output Properties
3036

3137
| Property | Display Name | Type | IO Type | Default Value | Optional |
@@ -41,12 +47,12 @@ True if A == B, false otherwise
4147

4248
This component supports flexible types. The following type combinations are valid:
4349

44-
| # | a | b | result |
45-
|---|---|---|---|
46-
| 1 | Float | Float | Bool |
47-
| 2 | Float2 | Float2 | Bool |
48-
| 3 | Float3 | Float3 | Bool |
49-
| 4 | Float4 | Float4 | Bool |
50+
| # | a | b | result | tolerance |
51+
|---|---|---|---|---|
52+
| 1 | Float | Float | Bool | Float |
53+
| 2 | Float2 | Float2 | Bool | Float |
54+
| 3 | Float3 | Float3 | Bool | Float |
55+
| 4 | Float4 | Float4 | Bool | Float |
5056

5157
## Usage Notes
5258

documentation/components/MeshHashChecker.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Mesh Hash Checker
22

3-
Detects if a specific mesh is currently being drawn in the scene\.<br/><br/>Checks if a specific mesh hash was processed in the current frame\.
3+
Detects if a specific mesh is currently being drawn in the scene\.<br/><br/>This checks all meshes that the game sends to Remix in the current frame, which will probably include meshes that are off camera or occluded\.
44

55
## Component Information
66

documentation/components/MeshProximity.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Mesh Proximity
22

3-
Measures how far a point is from a mesh's bounding box\. This can be used to determine if the camera is close to a mesh, or inside of a room\.<br/><br/>Calculates the signed distance from a world position to a mesh's bounding box\. Positive values indicate the point is outside the bounding box, negative values indicate it's inside\.<br/><br/>Note that the output is in object space\.
3+
Measures how far a point is from a mesh's bounding box\. This can be used to determine if the camera is close to a mesh, or inside of a room\.<br/><br/>Calculates the signed distance from a world position to a mesh's bounding box\. Positive values indicate the point is outside the bounding box, negative values indicate it's inside\.<br/><br/>Note that the output is in object space, so if the mesh is scaled, the distance may not correspond to world units\.
44

55
## Component Information
66

@@ -21,27 +21,27 @@ Measures how far a point is from a mesh's bounding box\. This can be used to det
2121

2222
### Target
2323

24-
The mesh prim to get bounding box from\. Must be a mesh prim\.
24+
The mesh prim to get bounding box from\. Must be a UsdGeomMesh prim \(the actual geometry\)\.
2525

2626

2727
### World Position
2828

29-
The world space position to test against the mesh bounding box\.
29+
The world space position to test against the mesh bounding box\. This is often the \`Position\` output from the \`Camera\` component, if checking how close the camera is to the mesh\.
3030

3131

3232
### Inactive Distance
3333

34-
The distance inside the bounding box that corresponds to a normalized value of 0\.0\. Positive numbers represent values outside the AABB\.
34+
When the \`World Position\` is this far from the mesh's bounding box, \`Activation Strength\` will be 0\. Positive numbers represent mean \`World Position\` is outside the box, negative numbers mean it is inside the box\.
3535

3636

3737
### Full Activation Distance
3838

39-
The distance inside the bounding box that corresponds to a normalized value of 1\.0\. Positive numbers represent values outside the AABB\.
39+
When the \`World Position\` is this far from the mesh's bounding box, \`Activation Strength\` will be 1\. Positive numbers represent mean \`World Position\` is outside the box, negative numbers mean it is inside the box\.
4040

4141

4242
### Easing Type
4343

44-
The type of easing to apply to the normalized output\.
44+
The type of easing to apply to the \`Activation Strength\` output\.
4545

4646
Underlying Type: `Enum`
4747

@@ -67,12 +67,12 @@ Underlying Type: `Enum`
6767

6868
### Signed Distance
6969

70-
Distance in object space to the nearest bounding box plane\. Positive when outside, negative when inside\. Outputs FLT\_MAX when no valid bounding box is found\.
70+
Distance in object space to the nearest point on the surface of the bounding box\. Positive when outside the bounding box, negative when inside\. Outputs a very large number when no valid bounding box is found\. Because this is in object space, if the object is scaled, the distance may not correspond to world units\.
7171

7272

7373
### Activation Strength
7474

75-
Normalized 0\-1 value: 0 when on bounding box surface, 1 when at max distance inside \(with easing applied\)\.
75+
Normalized 0\-1 value: 0 when \`Signed Distance\` = \`Inactive Distance\`, 1 when it equals \`Full Activation Distance\`\. This is often passed directly to the \`Blend Strength\` of \`Rtx Option Layer Action\` to enable a conf layer when the camera is close to the mesh\.
7676

7777

7878
## Usage Notes

documentation/components/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ This documentation provides detailed information about all available components
6262
| [Fog Hash Checker](FogHashChecker.md) | Detects if a specific fog state is currently active in the scene\.<br/><br/>Checks if a given fog hash matche\.\.\. | 1 |
6363
| [Keyboard Input](KeyboardInput.md) | Detects when keyboard keys are pressed, held, or released\.<br/><br/>Checks the state of a keyboard key or ke\.\.\. | 1 |
6464
| [Light Hash Checker](LightHashChecker.md) | Detects if a specific light is currently active in the scene\.<br/><br/>Checks if a specific light hash is pr\.\.\. | 1 |
65-
| [Mesh Hash Checker](MeshHashChecker.md) | Detects if a specific mesh is currently being drawn in the scene\.<br/><br/>Checks if a specific mesh hash wa\.\.\. | 1 |
65+
| [Mesh Hash Checker](MeshHashChecker.md) | Detects if a specific mesh is currently being drawn in the scene\.<br/><br/>This checks all meshes that the g\.\.\. | 1 |
6666
| [Mesh Proximity](MeshProximity.md) | Measures how far a point is from a mesh's bounding box\. This can be used to determine if the camera \.\.\. | 1 |
6767
| [Ray Mesh Intersection](RayMeshIntersection.md) | Tests if a ray intersects with a mesh\.<br/><br/>Performs a ray\-mesh intersection test\. Currently supports bo\.\.\. | 1 |
6868
| [Read Bone Transform](ReadBoneTransform.md) | Reads the transform \(position, rotation, scale\) of a bone from a skinned mesh\.<br/><br/>Extracts the transfo\.\.\. | 1 |

src/dxvk/rtx_render/graph/components/equal_to.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,20 @@
2828
namespace dxvk {
2929
namespace components {
3030

31+
namespace {
32+
constexpr bool isVectorPropertyType(RtComponentPropertyType type) {
33+
return type == RtComponentPropertyType::Float2 ||
34+
type == RtComponentPropertyType::Float3 ||
35+
type == RtComponentPropertyType::Float4;
36+
}
37+
}
38+
3139
#define LIST_INPUTS(X) \
3240
X(RtComponentPropertyType::NumberOrVector, 0, a, "A","The first value to compare.") \
33-
X(RtComponentPropertyType::NumberOrVector, 0, b, "B","The second value to compare.")
41+
X(RtComponentPropertyType::NumberOrVector, 0, b, "B","The second value to compare.") \
42+
X(RtComponentPropertyType::Float, 0.00001f, tolerance, "Tolerance", "The tolerance for rounding errors."\
43+
" Math operations with floating point values are not exact, so equality comparisons should allow for slightly different values." \
44+
" If the difference between A and B is less than Tolerance, the result will be true.")
3445

3546
#define LIST_STATES(X)
3647

@@ -42,6 +53,7 @@ namespace components {
4253
template <RtComponentPropertyType aPropertyType, RtComponentPropertyType bPropertyType>
4354
class EqualTo : public RtRegisteredComponentBatch<EqualTo<aPropertyType, bPropertyType>> {
4455
private:
56+
static constexpr RtComponentPropertyType tolerancePropertyType = RtComponentPropertyType::Float;
4557
static constexpr RtComponentPropertyType resultPropertyType = RtComponentPropertyType::Bool;
4658
REMIX_COMPONENT_BODY(
4759
/* the Component class name */ EqualTo,
@@ -58,7 +70,14 @@ class EqualTo : public RtRegisteredComponentBatch<EqualTo<aPropertyType, bProper
5870
// This is needed to allow things like Vector3 == int32_t, etc.
5971
#pragma warning(push)
6072
#pragma warning(disable: 4244)
61-
m_result[i] = m_a[i] == m_b[i];
73+
auto diff = m_a[i] - m_b[i];
74+
if constexpr (isVectorPropertyType(aPropertyType)) {
75+
// For vectors, use length squared to avoid sqrt
76+
auto tolSqr = m_tolerance[i] * m_tolerance[i];
77+
m_result[i] = lengthSqr(diff) < tolSqr;
78+
} else {
79+
m_result[i] = std::abs(diff) < m_tolerance[i];
80+
}
6281
#pragma warning(pop)
6382
}
6483
}

src/dxvk/rtx_render/graph/components/mesh_hash_checker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ REMIX_COMPONENT( \
4242
/* the UI name */ "Mesh Hash Checker", \
4343
/* the UI categories */ "Sense", \
4444
/* the doc string */ "Detects if a specific mesh is currently being drawn in the scene.\n\n" \
45-
"Checks if a specific mesh hash was processed in the current frame.", \
45+
"This checks all meshes that the game sends to Remix in the current frame, which will probably include meshes that are off camera or occluded.", \
4646
/* the version number */ 1, \
4747
LIST_INPUTS, LIST_STATES, LIST_OUTPUTS);
4848

src/dxvk/rtx_render/graph/components/mesh_proximity.h

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,29 +36,44 @@ namespace dxvk {
3636
namespace components {
3737

3838
#define LIST_INPUTS(X) \
39-
X(RtComponentPropertyType::Prim, kInvalidPrimTarget, target, "Target", "The mesh prim to get bounding box from. Must be a mesh prim.", \
39+
X(RtComponentPropertyType::Prim, kInvalidPrimTarget, target, "Target", \
40+
"The mesh prim to get bounding box from. Must be a UsdGeomMesh prim (the actual geometry).", \
4041
property.allowedPrimTypes = {PrimType::UsdGeomMesh}) \
41-
X(RtComponentPropertyType::Float3, Vector3(0.0f, 0.0f, 0.0f), worldPosition, "World Position", "The world space position to test against the mesh bounding box.") \
42-
X(RtComponentPropertyType::Float, 1.0f, inactiveDistance, "Inactive Distance", "The distance inside the bounding box that corresponds to a normalized value of 0.0. Positive numbers represent values outside the AABB. ", property.optional = true) \
43-
X(RtComponentPropertyType::Float, 0.0f, fullActivationDistance, "Full Activation Distance", "The distance inside the bounding box that corresponds to a normalized value of 1.0. Positive numbers represent values outside the AABB. ", property.optional = true) \
42+
X(RtComponentPropertyType::Float3, Vector3(0.0f, 0.0f, 0.0f), worldPosition, "World Position", \
43+
"The world space position to test against the mesh bounding box." \
44+
" This is often the `Position` output from the `Camera` component, if checking how close the camera is to the mesh.") \
45+
X(RtComponentPropertyType::Float, 1.0f, inactiveDistance, "Inactive Distance", \
46+
"When the `World Position` is this far from the mesh's bounding box, `Activation Strength` will be 0." \
47+
" Positive numbers represent mean `World Position` is outside the box, negative numbers mean it is inside the box.", \
48+
property.optional = true) \
49+
X(RtComponentPropertyType::Float, 0.0f, fullActivationDistance, "Full Activation Distance", \
50+
"When the `World Position` is this far from the mesh's bounding box, `Activation Strength` will be 1." \
51+
" Positive numbers represent mean `World Position` is outside the box, negative numbers mean it is inside the box.", \
52+
property.optional = true) \
4453
X(RtComponentPropertyType::Enum, static_cast<uint32_t>(InterpolationType::Linear), easingType, "Easing Type", \
45-
"The type of easing to apply to the normalized output.", \
54+
"The type of easing to apply to the `Activation Strength` output. ", \
4655
property.optional = true, \
4756
property.enumValues = kInterpolationTypeEnumValues)
4857

4958
#define LIST_STATES(X)
5059

5160
#define LIST_OUTPUTS(X) \
52-
X(RtComponentPropertyType::Float, 0.0f, signedDistance, "Signed Distance", "Distance in object space to the nearest bounding box plane. Positive when outside, negative when inside. Outputs FLT_MAX when no valid bounding box is found.") \
53-
X(RtComponentPropertyType::Float, 0.0f, activationStrength, "Activation Strength", "Normalized 0-1 value: 0 when on bounding box surface, 1 when at max distance inside (with easing applied).")
61+
X(RtComponentPropertyType::Float, 0.0f, signedDistance, "Signed Distance", \
62+
"Distance in object space to the nearest point on the surface of the bounding box." \
63+
" Positive when outside the bounding box, negative when inside." \
64+
" Outputs a very large number when no valid bounding box is found." \
65+
" Because this is in object space, if the object is scaled, the distance may not correspond to world units.") \
66+
X(RtComponentPropertyType::Float, 0.0f, activationStrength, "Activation Strength", \
67+
"Normalized 0-1 value: 0 when `Signed Distance` = `Inactive Distance`, 1 when it equals `Full Activation Distance`." \
68+
" This is often passed directly to the `Blend Strength` of `Rtx Option Layer Action` to enable a conf layer when the camera is close to the mesh.") \
5469

5570
REMIX_COMPONENT( \
5671
/* the Component name */ MeshProximity, \
5772
/* the UI name */ "Mesh Proximity", \
5873
/* the UI categories */ "Sense", \
5974
/* the doc string */ "Measures how far a point is from a mesh's bounding box. This can be used to determine if the camera is close to a mesh, or inside of a room.\n\n" \
6075
"Calculates the signed distance from a world position to a mesh's bounding box. Positive values indicate the point is outside the bounding box, negative values indicate it's inside.\n\n" \
61-
"Note that the output is in object space.", \
76+
"Note that the output is in object space, so if the mesh is scaled, the distance may not correspond to world units.", \
6277
/* the version number */ 1, \
6378
LIST_INPUTS, LIST_STATES, LIST_OUTPUTS);
6479

src/dxvk/rtx_render/graph/rtx_graph_batch.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,6 @@ namespace {
9898
void RtGraphBatch::Initialize(const RtGraphTopology& topology) {
9999
// NOTE: need to do this separate from the constructor, because the address of `this` changes when it's moved.
100100
ScopedCpuProfileZone();
101-
if (topology.componentSpecs.empty()) {
102-
Logger::err("RtGraphTopology has no component specs");
103-
return;
104-
}
105101

106102
// Store pointer to topology for GUI access (safe because topology lives in stable asset storage)
107103
m_topology = &topology;

src/dxvk/rtx_render/graph/rtx_graph_batch.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,11 @@ class RtGraphBatch {
6767
}
6868

6969
// Safety and validation methods
70-
bool isValid() const {
71-
return !m_componentBatches.empty() && !m_properties.empty();
70+
71+
// Returns true if the graph has no valid components.
72+
// Empty graphs can exist without causing errors, but they won't do anything.
73+
bool isEmpty() const {
74+
return m_componentBatches.empty();
7275
}
7376

7477
bool hasInstance(size_t index) const {

src/dxvk/rtx_render/graph/rtx_graph_gui.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,12 @@ void RtxGraphGUI::showGraphSelector(const SceneManager& sceneManager) {
145145

146146
void RtxGraphGUI::showComponentList() {
147147
if (m_components.empty()) {
148-
ImGui::Text("No components in selected graph instance");
148+
if (m_selectedGraphIsEmpty) {
149+
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.3f, 1.0f), "Empty graph - no valid components found");
150+
ImGui::TextWrapped("This graph has no components. This can happen when all components "
151+
"failed to load, are unsupported, or were filtered out.");
152+
}
153+
ImGui::Text("No graph selected.");
149154
return;
150155
}
151156
if (ImGui::CollapsingHeader("Components:", ImGuiTreeNodeFlags_DefaultOpen)) {
@@ -155,8 +160,8 @@ void RtxGraphGUI::showComponentList() {
155160
for (size_t i = 0; i < m_components.size(); ++i) {
156161
const auto& component = m_components[i];
157162

158-
// Component header with collapsible tree node
159-
std::string headerText = component.typeName;
163+
// Component header with collapsible tree node. Included the index so each section has a unique name.
164+
std::string headerText = component.typeName + " (" + std::to_string(i) + ")";
160165

161166
if (ImGui::CollapsingHeader(headerText.c_str())) {
162167
// Show component description as tooltip on header hover
@@ -230,6 +235,7 @@ void RtxGraphGUI::showComponentList() {
230235
void RtxGraphGUI::updateGraphData(const SceneManager& sceneManager) {
231236
// Clear existing data
232237
m_components.clear();
238+
m_selectedGraphIsEmpty = false;
233239

234240
if (m_selectedInstanceId == kInvalidInstanceId) {
235241
return;
@@ -254,6 +260,13 @@ void RtxGraphGUI::updateGraphData(const SceneManager& sceneManager) {
254260
}
255261

256262
const RtGraphBatch& batch = batchIt->second;
263+
264+
// Handle empty graphs gracefully - they have no components to display
265+
if (batch.isEmpty()) {
266+
m_selectedGraphIsEmpty = true;
267+
return;
268+
}
269+
257270
const auto& componentBatches = batch.getComponentBatches();
258271
const auto& topology = batch.getTopology();
259272
const auto& properties = batch.getProperties();
@@ -346,7 +359,6 @@ std::string RtxGraphGUI::extractGraphInstanceName(const GraphManager& graphManag
346359
return "Instance " + std::to_string(graphInstance.getId()) + " (Hash: " + hashStream.str() + ")";
347360
}
348361

349-
const RtGraphBatch& batch = batchIt->second;
350362
const auto& initialGraphState = graphInstance.getInitialGraphState();
351363

352364
// Use the stored prim path from the topology
@@ -437,6 +449,8 @@ std::string RtxGraphGUI::formatPropertyValue(const RtComponentPropertyValue& val
437449
return ss.str();
438450
} else if constexpr (std::is_same_v<T, std::string>) {
439451
return "\"" + v + "\"";
452+
} else if constexpr (std::is_same_v<T, PrimTarget>) {
453+
return "instance: " + std::to_string(v.instanceId) + ", index: " + std::to_string(v.replacementIndex);
440454
} else {
441455
return "Unknown";
442456
}

0 commit comments

Comments
 (0)