Skip to content

Commit 2319c9e

Browse files
committed
Merge branch 'dev/adunn/precision_vertex_cap' into 'main'
Significantly improve precision issues in vertex shader based games See merge request lightspeedrtx/dxvk-remix-nv!1667
2 parents 08cb9cc + 0c328a7 commit 2319c9e

File tree

6 files changed

+361
-193
lines changed

6 files changed

+361
-193
lines changed

src/d3d9/d3d9_rtx.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,7 @@ namespace dxvk {
131131
void D3D9Rtx::prepareVertexCapture(const int vertexIndexOffset) {
132132
ScopedCpuProfileZone();
133133

134-
struct CapturedVertex {
135-
Vector4 position;
136-
Vector4 texcoord0;
137-
Vector4 normal0;
138-
};
134+
static_assert(sizeof CapturedVertex == 48, "The injected shader code is expecting this exact structure size to work correctly, see emitVertexCaptureWrite in dxso_compiler.cpp");
139135

140136
auto BoundShaderHas = [&](const D3D9CommonShader* shader, DxsoUsage usage, bool inOut)-> bool {
141137
if (shader == nullptr)
@@ -173,23 +169,28 @@ namespace dxvk {
173169
}
174170

175171
// Check if we should/can get normals. We don't see a lot of games sending normals to pixel shader, so we must capture from the IA output (or Vertex input)
176-
if (BoundShaderHas(vertexShader, DxsoUsage::Normal, true) && useVertexCapturedNormals()) {
172+
if ((BoundShaderHas(vertexShader, DxsoUsage::Normal, false) || BoundShaderHas(vertexShader, DxsoUsage::Normal, true)) && useVertexCapturedNormals()) {
177173
const uint32_t normalOffset = offsetof(CapturedVertex, normal0);
178174
geoData.normalBuffer = RasterBuffer(slice, normalOffset, stride, VK_FORMAT_R32G32B32_SFLOAT);
179175
assert(geoData.normalBuffer.offset() % 4 == 0);
180176
} else {
181177
geoData.normalBuffer = RasterBuffer();
182178
}
183179

184-
auto constants = m_vsVertexCaptureData->allocSlice();
180+
// Check if we should/can get colors
181+
if (BoundShaderHas(vertexShader, DxsoUsage::Color, false) && d3d9State().pixelShader.ptr() == nullptr) {
182+
const uint32_t colorOffset = offsetof(CapturedVertex, color0);
183+
geoData.color0Buffer = RasterBuffer(slice, colorOffset, stride, VK_FORMAT_B8G8R8A8_UNORM);
184+
assert(geoData.color0Buffer.offset() % 4 == 0);
185+
}
185186

186-
// NOTE: May be better to move reverse transformation to end of frame, because this won't work if there hasnt been a FF draw this frame to scrape the matrix from...
187-
const Matrix4& ObjectToProjection = m_activeDrawCallState.transformData.viewToProjection * m_activeDrawCallState.transformData.worldToView * m_activeDrawCallState.transformData.objectToWorld;
187+
auto constants = m_vsVertexCaptureData->allocSlice();
188188

189-
// Set constants required for vertex shader injection
190-
D3D9RtxVertexCaptureData& data = *(D3D9RtxVertexCaptureData*) constants.mapPtr;
191-
// Apply an inverse transform to get positions in object space (what renderer expects)
192-
data.projectionToWorld = inverse(ObjectToProjection);
189+
// Upload
190+
auto& data = *reinterpret_cast<D3D9RtxVertexCaptureData*>(constants.mapPtr);
191+
data.invProj = inverse(m_activeDrawCallState.transformData.viewToProjection);
192+
data.viewToWorld = inverseAffine(m_activeDrawCallState.transformData.worldToView);
193+
data.worldToObject = inverseAffine(m_activeDrawCallState.transformData.objectToWorld);
193194
data.normalTransform = m_activeDrawCallState.transformData.objectToWorld;
194195
data.baseVertex = (uint32_t)std::max(0, vertexIndexOffset);
195196

src/d3d9/d3d9_state.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,32 @@ namespace dxvk {
3131
};
3232

3333
// NV-DXVK start: vertex shader data capture implementation
34+
// NOTE: Padding exists to ensure we get vectorized loads for these attributes
35+
struct CapturedVertex {
36+
Vector3 position;
37+
uint32_t pad0;
38+
Vector2 texcoord0;
39+
uint32_t pad1;
40+
uint32_t pad2;
41+
Vector3 normal0;
42+
uint32_t color0;
43+
};
44+
45+
enum class CapturedVertexMembers {
46+
Position = 0,
47+
Texcoord0,
48+
Normal0,
49+
Color0,
50+
51+
MemberCount
52+
};
53+
3454
struct D3D9RtxVertexCaptureData {
3555
Matrix4 normalTransform;
36-
Matrix4 projectionToWorld;
3756
Matrix4 customWorldToProjection;
57+
Matrix4 invProj;
58+
Matrix4 viewToWorld;
59+
Matrix4 worldToObject;
3860
uint32_t baseVertex = 0;
3961
float jitterX;
4062
float jitterY;
@@ -43,8 +65,10 @@ namespace dxvk {
4365

4466
enum class D3D9RtxVertexCaptureMembers {
4567
NormalTransform = 0,
46-
ProjectionToWorld,
4768
CustomWorldToProjection,
69+
InvProj,
70+
ViewToWorld,
71+
WorldToObject,
4872
BaseVertex,
4973
JitterX,
5074
JitterY,

0 commit comments

Comments
 (0)