From 11e910b9eb6f8ae412be1932d9ee2b4e38613db7 Mon Sep 17 00:00:00 2001 From: Alex Dunn Date: Thu, 4 Jan 2024 19:15:25 -0800 Subject: [PATCH] [REMIX-2454] Simplify decal handling --- src/d3d9/d3d9_rtx.cpp | 2 +- src/dxvk/imgui/dxvk_imgui.cpp | 34 --- src/dxvk/rtx_render/rtx_debug_view.cpp | 2 + src/dxvk/rtx_render/rtx_dlss.cpp | 3 +- src/dxvk/rtx_render/rtx_instance_manager.cpp | 247 ++---------------- src/dxvk/rtx_render/rtx_instance_manager.h | 10 +- src/dxvk/rtx_render/rtx_materials.h | 7 +- src/dxvk/rtx_render/rtx_ngx_wrapper.cpp | 1 - src/dxvk/rtx_render/rtx_ngx_wrapper.h | 1 - src/dxvk/rtx_render/rtx_options.h | 34 +-- .../rtx_render/rtx_pathtracer_gbuffer.cpp | 13 +- .../rtx_pathtracer_integrate_direct.cpp | 2 +- .../rtx_pathtracer_integrate_indirect.cpp | 13 +- src/dxvk/rtx_render/rtx_resources.cpp | 19 +- src/dxvk/rtx_render/rtx_resources.h | 8 +- .../rtx_render/rtx_restir_gi_rayquery.cpp | 11 +- src/dxvk/rtx_render/rtx_rtxdi_rayquery.cpp | 19 +- .../rtx/algorithm/geometry_resolver.slangh | 31 ++- .../algorithm/geometry_resolver_state.slangh | 13 +- .../rtx/algorithm/integrator_indirect.slangh | 10 +- src/dxvk/shaders/rtx/algorithm/resolve.slangh | 102 +++++--- .../shaders/rtx/concept/surface/surface.h | 2 + .../rtx/concept/surface/surface_create.slangh | 2 +- .../decal_material_interaction.slangh | 31 +++ .../pass/gbuffer/gbuffer_binding_indices.h | 7 +- .../rtx/pass/gbuffer/gbuffer_bindings.slangh | 17 +- .../integrate_indirect_binding_indices.h | 7 +- .../integrate_indirect_bindings.slangh | 6 - .../shaders/rtx/utility/debug_view_indices.h | 2 + 29 files changed, 231 insertions(+), 425 deletions(-) diff --git a/src/d3d9/d3d9_rtx.cpp b/src/d3d9/d3d9_rtx.cpp index 5b16b62a1..3d6948a70 100644 --- a/src/d3d9/d3d9_rtx.cpp +++ b/src/d3d9/d3d9_rtx.cpp @@ -21,7 +21,7 @@ namespace dxvk { const uint32_t kRenderTargetIndex = 0; #define CATEGORIES_REQUIRE_DRAW_CALL InstanceCategories::Sky, InstanceCategories::Terrain - #define CATEGORIES_REQUIRE_GEOMETRY_COPY InstanceCategories::DecalStatic, InstanceCategories::DecalDynamic, InstanceCategories::DecalNoOffset, InstanceCategories::Terrain, InstanceCategories::WorldUI + #define CATEGORIES_REQUIRE_GEOMETRY_COPY InstanceCategories::Terrain, InstanceCategories::WorldUI D3D9Rtx::D3D9Rtx(D3D9DeviceEx* d3d9Device) : m_rtStagingData(d3d9Device->GetDXVKDevice(), (VkMemoryPropertyFlagBits) (VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) diff --git a/src/dxvk/imgui/dxvk_imgui.cpp b/src/dxvk/imgui/dxvk_imgui.cpp index 3abedbfa7..7e4036efd 100644 --- a/src/dxvk/imgui/dxvk_imgui.cpp +++ b/src/dxvk/imgui/dxvk_imgui.cpp @@ -152,9 +152,6 @@ namespace dxvk { {"beamtextures", "Beam Texture (optional)", &RtxOptions::Get()->beamTexturesObject()}, {"lightconvertertextures", "Add Light to Textures (optional)", &RtxOptions::Get()->lightConverterObject()}, {"decaltextures", "Decal Texture (optional)", &RtxOptions::Get()->decalTexturesObject()}, - {"dynamicdecaltextures", "Dynamic Decal Texture", &RtxOptions::Get()->dynamicDecalTexturesObject()}, - {"singleoffsetdecaltextures", "Single Offset Decal Texture", &RtxOptions::Get()->singleOffsetDecalTexturesObject()}, - {"nonoffsetdecaltextures", "Non-Offset Decal Texture", &RtxOptions::Get()->nonOffsetDecalTexturesObject()}, {"cutouttextures", "Legacy Cutout Texture (optional)", &RtxOptions::Get()->cutoutTexturesObject()}, {"terraintextures", "Terrain Texture", &RtxOptions::Get()->terrainTexturesObject()}, {"watertextures", "Water Texture (optional)", &RtxOptions::Get()->animatedWaterTexturesObject()}, @@ -1952,24 +1949,6 @@ namespace dxvk { ImGui::Indent(); } - if (IMGUI_ADD_TOOLTIP(ImGui::CollapsingHeader("Dynamic Decal Textures", collapsingHeaderClosedFlags), RtxOptions::Get()->dynamicDecalTexturesDescription())) { - ImGui::Unindent(); - showTextureSelectionGrid(ctx, "dynamicdecaltextures", numThumbnailsPerRow, thumbnailSize); - ImGui::Indent(); - } - - if (IMGUI_ADD_TOOLTIP(ImGui::CollapsingHeader("Single Offset Decal Textures", collapsingHeaderClosedFlags), RtxOptions::Get()->singleOffsetDecalTexturesDescription())) { - ImGui::Unindent(); - showTextureSelectionGrid(ctx, "singleoffsetdecaltextures", numThumbnailsPerRow, thumbnailSize); - ImGui::Indent(); - } - - if (IMGUI_ADD_TOOLTIP(ImGui::CollapsingHeader("Non-Offset Decal Textures", collapsingHeaderClosedFlags), RtxOptions::Get()->nonOffsetDecalTexturesDescription())) { - ImGui::Unindent(); - showTextureSelectionGrid(ctx, "nonoffsetdecaltextures", numThumbnailsPerRow, thumbnailSize); - ImGui::Indent(); - } - if (IMGUI_ADD_TOOLTIP(ImGui::CollapsingHeader("Legacy Cutout Textures (optional)", collapsingHeaderClosedFlags), RtxOptions::Get()->cutoutTexturesDescription())) { ImGui::Unindent(); showTextureSelectionGrid(ctx, "cutouttextures", numThumbnailsPerRow, thumbnailSize); @@ -2791,19 +2770,6 @@ namespace dxvk { ImGui::DragInt("Min Prims in Static BLAS", &RtxOptions::Get()->minPrimsInStaticBLASObject(), 1.f, 100, 0); ImGui::Checkbox("Portals: Virtual Instance Matching", &RtxOptions::Get()->useRayPortalVirtualInstanceMatchingObject()); ImGui::Checkbox("Portals: Fade In Effect", &RtxOptions::Get()->enablePortalFadeInEffectObject()); - - if (ImGui::CollapsingHeader("Decals", collapsingHeaderClosedFlags)) { - ImGui::Indent(); - - ImGui::TextWrapped("Warning: changes to these parameters will only apply to new geometry. Existing geometry needs to be invalidated by either a game reload or gameplay and/or camera view change if the game uses runtime or view dependent geometry batching per draw call."); - - ImGui::DragFloat("Offset Multiplier [m]", &RtxOptions::Decals::offsetMultiplierMetersObject(), 0.0001f, 0.f, 0.f, "%.5f"); - ImGui::DragInt("Base Offset Index", &RtxOptions::Decals::baseOffsetIndexObject(), 1.f, 1, 1000); - ImGui::DragInt("Max Offset Index", &RtxOptions::Decals::maxOffsetIndexObject(), 1.f, 1, 10000); - ImGui::DragInt("Offset Increase Between Decal Draw Calls", &RtxOptions::Decals::offsetIndexIncreaseBetweenDrawCallsObject(), 1.f, 1, 1000); - ImGui::Unindent(); - } - ImGui::Unindent(); } diff --git a/src/dxvk/rtx_render/rtx_debug_view.cpp b/src/dxvk/rtx_render/rtx_debug_view.cpp index a6b9c564e..654e9be14 100644 --- a/src/dxvk/rtx_render/rtx_debug_view.cpp +++ b/src/dxvk/rtx_render/rtx_debug_view.cpp @@ -178,6 +178,8 @@ namespace dxvk { {DEBUG_VIEW_PRIMARY_USE_ALTERNATE_DISOCCLUSION_THRESHOLD, "Primary Use Alternate Disocclusion Threshold"}, + {DEBUG_VIEW_PRIMARY_DECAL_ALBEDO, "Primary Decal Albedo" }, + {DEBUG_VIEW_PRIMARY_SPECULAR_ALBEDO, "Primary Specular Albedo"}, {DEBUG_VIEW_SECONDARY_SPECULAR_ALBEDO, "Secondary Specular Albedo"}, diff --git a/src/dxvk/rtx_render/rtx_dlss.cpp b/src/dxvk/rtx_render/rtx_dlss.cpp index e2e662392..906450108 100644 --- a/src/dxvk/rtx_render/rtx_dlss.cpp +++ b/src/dxvk/rtx_render/rtx_dlss.cpp @@ -219,7 +219,7 @@ namespace dxvk { rtOutput.m_compositeOutput.view(Resources::AccessType::Read), rtOutput.m_primaryScreenSpaceMotionVector.view, rtOutput.m_primaryDepth.view, - rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view, + rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read), rtOutput.m_primaryAlbedo.view, rtOutput.m_sharedBiasCurrentColorMask.view(Resources::AccessType::Read) }; @@ -276,7 +276,6 @@ namespace dxvk { &rtOutput.m_primaryAlbedo, // pDiffuseAlbedo specularAlbedoInput, // pSpecularAlbedo &autoExposure.getExposureTexture(), // pExposure - &rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal(), // pPosition normalsInput, // pNormals &rtOutput.m_primaryPerceptualRoughness, // pRoughness &rtOutput.m_sharedBiasCurrentColorMask.resource(Resources::AccessType::Read),// pBiasCurrentColorMask diff --git a/src/dxvk/rtx_render/rtx_instance_manager.cpp b/src/dxvk/rtx_render/rtx_instance_manager.cpp index 2e82b98e1..f96f1b93f 100644 --- a/src/dxvk/rtx_render/rtx_instance_manager.cpp +++ b/src/dxvk/rtx_render/rtx_instance_manager.cpp @@ -120,9 +120,7 @@ namespace dxvk { , m_geometryFlags(src.m_geometryFlags) , m_objectToWorldMirrored(src.m_objectToWorldMirrored) , m_firstBillboard(src.m_firstBillboard) - , m_billboardCount(src.m_billboardCount) - , m_lastDecalOffsetVertexDataVersion(src.m_lastDecalOffsetVertexDataVersion) - , m_currentDecalOffsetDifference(src.m_currentDecalOffsetDifference) { + , m_billboardCount(src.m_billboardCount) { // Members for which state carry over is intentionally skipped /* m_isMarkedForGC @@ -255,7 +253,6 @@ namespace dxvk { : CommonDeviceObject(device) , m_pResourceCache(pResourceCache) { m_previousViewModelState = RtxOptions::ViewModel::enable(); - m_currentDecalOffsetIndex = RtxOptions::Decals::baseOffsetIndex(); } InstanceManager::~InstanceManager() { @@ -339,9 +336,10 @@ namespace dxvk { void InstanceManager::onFrameEnd() { m_viewModelCandidates.clear(); m_playerModelInstances.clear(); - m_currentDecalOffsetIndex = RtxOptions::Decals::baseOffsetIndex(); resetSurfaceIndices(); m_billboards.clear(); + // reset decal counter + m_decalSortOrderCounter = 0; } RtInstance* InstanceManager::processSceneObject( @@ -964,13 +962,24 @@ namespace dxvk { // with different flags, and the instance manager can match an old instance of a geometry to a new one with different draw mode. currentInstance.m_vkInstance.flags = determineInstanceFlags(drawCall, worldToProjection, currentInstance.surface); + // Apply the decal sort index for this instance so we can approximate order correctness on the GPU in AHS + if (currentInstance.surface.alphaState.isDecal) { + currentInstance.surface.decalSortOrder = m_decalSortOrderCounter++; +#if !NDEBUG + if (m_decalSortOrderCounter > 255) { + ONCE(Logger::err("Too many decals in this scene to sort correctly, may see some decal corruption issues.")); + } +#endif + } + // Update the geometry and instance flags if ( - !currentInstance.surface.alphaState.isFullyOpaque && currentInstance.surface.alphaState.isParticle || + (!currentInstance.surface.alphaState.isFullyOpaque && currentInstance.surface.alphaState.isParticle) || + (!currentInstance.surface.alphaState.isFullyOpaque && currentInstance.surface.alphaState.isDecal) || // Note: include alpha blended geometry on the player model into the unordered TLAS. This is hacky as there might be // suitable geometry outside of the player model, but we don't have a way to distinguish it from alpha blended geometry // that should be alpha tested instead, like some metallic stairs in Portal -- those should be resolved normally. - !currentInstance.surface.alphaState.isFullyOpaque && !currentInstance.surface.alphaState.isBlendingDisabled && currentInstance.m_isPlayerModel || + (!currentInstance.surface.alphaState.isFullyOpaque && !currentInstance.surface.alphaState.isBlendingDisabled && currentInstance.m_isPlayerModel) || currentInstance.surface.alphaState.emissiveBlend ) { // Alpha-blended and emissive particles go to the separate "unordered" TLAS as non-opaque geometry @@ -994,9 +1003,6 @@ namespace dxvk { } else if (material.getType() == RtSurfaceMaterialType::RayPortal) { // Portals go to the primary TLAS as opaque. currentInstance.m_geometryFlags = VK_GEOMETRY_OPAQUE_BIT_KHR; - } else if (currentInstance.surface.alphaState.isDecal) { - // Consider all decals as non opaque objects - currentInstance.m_geometryFlags = 0; } else if (currentInstance.surface.isClipPlaneEnabled) { // Use non-opaque hits to process clip planes on visibility rays. // To handle cases when the same *static* object is used both with and without clip planes, @@ -1074,13 +1080,6 @@ namespace dxvk { // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkGeometryInstanceFlagBitsNV.html currentInstance.m_objectToWorldMirrored = isMirrorTransform(transform); - // Offset decals along their normals. - // Do this *after* the instance transform is updated above. - if (alphaState.isDecal || currentInstance.m_isWorldSpaceUI) { - // In the event this modifies the CPU draw call geometry, the change will be applied next frame. - applyDecalOffsets(currentInstance, drawCall.getGeometryData()); - } - bool billboardsGotGenerated = false; currentInstance.m_billboardCount = 0; @@ -1688,220 +1687,6 @@ namespace dxvk { instance->m_surfaceIndex = BINDING_INDEX_INVALID; } - // This function goes over all decals and offsets each one along its normal. - // The offset is different per-decal and generally grows with every draw call and every decal in a draw call, - // only wrapping around to start offset index when some limit is reached. - // This offsetting takes care of procedural decals that are entirely coplanar, which doesn't work with - // ray tracing because we want to hit every decal with a closest-hit shader, and without offsets we can't do that. - // Some map geometry has static decals that are tessellated as odd non-quad meshes, but they still need to be offset, - // so the second part of this function takes care of that. - void InstanceManager::applyDecalOffsets(RtInstance& instance, const RasterGeometry& geometryData) { - if (RtxOptions::Decals::offsetMultiplierMeters() == 0.f) { - return; - } - - if (instance.testCategoryFlags(InstanceCategories::DecalNoOffset)) - return; - - constexpr int indicesPerTriangle = 3; - - // Check if this is a supported geometry first - if (geometryData.indexCount < indicesPerTriangle || geometryData.indexBuffer.indexType() != VK_INDEX_TYPE_UINT16) - return; - - const bool hasDecalBeenOffset = geometryData.hashes[HashComponents::VertexPosition] == instance.m_lastDecalOffsetVertexDataVersion; - - // Exit if this instance has already been processed in its current version and the decal offset paramterization matches that of the last time it was offset - // to prevent applying offsets to the same geometry multiple times. - // This fixes the chamber information panels in Portal when you reload the same map multiple times in a row. - // TODO: Move this to geom utils, only do on build - if (hasDecalBeenOffset) { - // Apply the decal offset difference that was applied to this instance previously to the global offset index - m_currentDecalOffsetIndex += instance.m_currentDecalOffsetDifference - + RtxOptions::Decals::offsetIndexIncreaseBetweenDrawCalls(); - if (m_currentDecalOffsetIndex > RtxOptions::Decals::maxOffsetIndex()) { - m_currentDecalOffsetIndex = RtxOptions::Decals::baseOffsetIndex(); - } - return; - } - - const GeometryBufferData bufferData(geometryData); - - // Check if the necessary buffers exist - if (!bufferData.indexData || !bufferData.positionData) - return; - - const bool isSingleOffsetDecalBatch = instance.testCategoryFlags(InstanceCategories::DecalSingleOffset); - const uint32_t currentOffsetDecalBatchStartIndex = m_currentDecalOffsetIndex; - const float offsetMultiplier = RtxOptions::Decals::offsetMultiplierMeters() * RtxOptions::Get()->getMeterToWorldUnitScale(); - - auto getNextOffset = [this, &instance, isSingleOffsetDecalBatch, offsetMultiplier]() { - const float offset = m_currentDecalOffsetIndex * offsetMultiplier; - - // Increment decal index and wrap it around to avoid moving them too far away from walls - if (!isSingleOffsetDecalBatch && ++m_currentDecalOffsetIndex > RtxOptions::Decals::maxOffsetIndex()) { - m_currentDecalOffsetIndex = RtxOptions::Decals::baseOffsetIndex(); - } - - return offset; - }; - - if (instance.testCategoryFlags(InstanceCategories::DecalDynamic)) { - // It's a dynamic decal. Find all triangle quads and offset each quad individually. - int fanStartIndexOffset = 0; - bool fanNormalFound = false; - Vector3 normal; - - // Go over all quads in this draw call. - // Note: decals are often batched into a few draw calls, and we want to offset each decal separately. - for (int indexOffset = 0; indexOffset + indicesPerTriangle <= geometryData.indexCount; indexOffset += indicesPerTriangle) { - // Load indices for the current triangle - uint16_t indices[indicesPerTriangle]; - for (size_t idx = 0; idx < indicesPerTriangle; ++idx) { - indices[idx] = bufferData.getIndex(idx + indexOffset); - } - - if (!fanNormalFound) { - // Load the triangle vertices - Vector3 triangleVertices[indicesPerTriangle]; - for (int idx = 0; idx < indicesPerTriangle; ++idx) { - triangleVertices[idx] = bufferData.getPosition(indices[idx]); - } - - // Compute the edges - const Vector3 xVector = triangleVertices[2] - triangleVertices[1]; - const Vector3 yVector = triangleVertices[1] - triangleVertices[0]; - - // Compute the normal, set the valid flag if the triangle is not degenerate - normal = cross(xVector, yVector); - const float normalLength = length(normal); - if (normalLength > 0.f) { - normal /= normalLength; - fanNormalFound = true; - } - } - - // Detect if this triangle is the last one in a triangle fan - const bool endOfStream = indexOffset + indicesPerTriangle * 2 > geometryData.indexCount; - const bool endOfFan = endOfStream || - (bufferData.getIndex(indexOffset + indicesPerTriangle) != indices[0]) || - (bufferData.getIndex(indexOffset + indicesPerTriangle + 1) != indices[2]); - if (!endOfFan) - continue; - - if (fanNormalFound) { - // Compute the offset - const Vector3 positionOffset = normal * getNextOffset(); - - // Apply the offset to all vertices of the triangle fan - bufferData.getPosition(bufferData.getIndex(fanStartIndexOffset)) += positionOffset; - bufferData.getPosition(bufferData.getIndex(fanStartIndexOffset + 1)) += positionOffset; - for (int i = fanStartIndexOffset; i <= indexOffset; i += indicesPerTriangle) { - bufferData.getPosition(bufferData.getIndex(i + 2)) += positionOffset; - } - } - - fanStartIndexOffset = indexOffset + indicesPerTriangle; - fanNormalFound = false; - } - } - else { - // Maybe it's a BSP decal with irregular geometry? - Vector3 decalNormal; - bool decalNormalFound = false; - - // This set contains all indices of vertices that are used in a planar decal. The topology is unknown, - // so a set is necessary to avoid offsetting some vertices more than once. - // Use a static set to avoid freeing and re-allocating its memory on each decal. - // Note: this makes the function not thread-safe, but that's OK - static std::unordered_set planeIndices; - - // Go over all triangles and see if they are coplanar - for (int indexOffset = 0; indexOffset + indicesPerTriangle <= geometryData.indexCount; indexOffset += indicesPerTriangle) { - // Load the triangle vertices - uint16_t triangleIndices[indicesPerTriangle]; - Vector3 worldVertices[indicesPerTriangle]; - for (size_t idx = 0; idx < indicesPerTriangle; ++idx) { - triangleIndices[idx] = bufferData.getIndex(idx + indexOffset); - worldVertices[idx] = bufferData.getPosition(triangleIndices[idx]); - } - - // Compute the edges - const Vector3 xVector = worldVertices[2] - worldVertices[1]; - const Vector3 yVector = worldVertices[1] - worldVertices[0]; - - // Compute the normal, skip the triangle if it's degenerate - Vector3 normal = cross(xVector, yVector); - const float normalLength = length(normal); - if (normalLength == 0.f) - continue; - normal /= normalLength; - - if (decalNormalFound) { - // If this is not the first valid triangle, compare its normal to a previously found one - const float dotNormals = dot(decalNormal, normal); - constexpr float kDegreesToRadians = float(M_PI / 180.0); - static const float kCosParallelThreshold = cos(5.f * kDegreesToRadians); - - // Not coplanar - offset the previous plane and reset - if (dotNormals < kCosParallelThreshold) { - const Vector3 positionOffset = normal * getNextOffset(); - - for (uint16_t idx : planeIndices) { - bufferData.getPosition(idx) += positionOffset; - } - - planeIndices.clear(); - decalNormalFound = false; - } - } - else { - // If this is a valid triangle, store its normal and indices - decalNormalFound = true; - decalNormal = normal; - } - - for (size_t idx = 0; idx < indicesPerTriangle; ++idx) { - planeIndices.insert(triangleIndices[idx]); - } - } - - // Offset the last (or the only) plane at the end of the loop - if (decalNormalFound) { - const Vector3 positionOffset = decalNormal * getNextOffset(); - - for (uint16_t idx : planeIndices) { - bufferData.getPosition(idx) += positionOffset; - } - } - - planeIndices.clear(); - } - - // Record the geometry hash to mark this decal is offsetted - instance.m_lastDecalOffsetVertexDataVersion = geometryData.hashes[HashComponents::VertexPosition]; - - // Increment the decal index now if it is a single offset decal batch - if (isSingleOffsetDecalBatch) { - ++m_currentDecalOffsetIndex; - } - - const int32_t currentDecalOffsetDifference = static_cast(m_currentDecalOffsetIndex) - currentOffsetDecalBatchStartIndex; - - // Set to wrap around limit if wrap around (i.e. negative offset index difference is seen) occured - instance.m_currentDecalOffsetDifference = instance.m_currentDecalOffsetDifference < 1 - ? RtxOptions::Decals::maxOffsetIndex() - : currentDecalOffsetDifference; - - // We're done processing all the batched decals for the current instance. - // Apply the custom offsetting between decal draw calls. - // -1 since the offset index has already been incremented after calculating offset for the previous decal - m_currentDecalOffsetIndex += RtxOptions::Decals::offsetIndexIncreaseBetweenDrawCalls() - 1; - if (m_currentDecalOffsetIndex > RtxOptions::Decals::maxOffsetIndex()) { - m_currentDecalOffsetIndex = RtxOptions::Decals::baseOffsetIndex(); - } - } - inline bool isFpSpecial(float x) { const uint32_t u = *(uint32_t*) &x; return (u & 0x7f800000) == 0x7f800000; diff --git a/src/dxvk/rtx_render/rtx_instance_manager.h b/src/dxvk/rtx_render/rtx_instance_manager.h index e4d92073b..ac6cda524 100644 --- a/src/dxvk/rtx_render/rtx_instance_manager.h +++ b/src/dxvk/rtx_render/rtx_instance_manager.h @@ -178,10 +178,6 @@ class RtInstance { uint32_t m_firstBillboard = 0; uint32_t m_billboardCount = 0; - // Used decal offsetting parameters - XXH64_hash_t m_lastDecalOffsetVertexDataVersion = kEmptyHash; - uint32_t m_currentDecalOffsetDifference = UINT32_MAX; - CategoryFlags m_categoryFlags; public: @@ -300,8 +296,8 @@ class InstanceManager : public CommonDeviceObject { bool m_previousViewModelState = false; RtInstance* targetInstance = nullptr; - uint32_t m_currentDecalOffsetIndex; - + uint32_t m_decalSortOrderCounter = 0; // monotonically incrementing value indicating the draw call order of this decal on the frame + // Controls active portal space for which virtual view model or player model instances have been generated for. // Negative values mean there is no portal that's close enough to the camera. int m_virtualInstancePortalIndex = 0; @@ -329,8 +325,6 @@ class InstanceManager : public CommonDeviceObject { // Modifies an instance given active developer options. Returns true if the instance was modified bool applyDeveloperOptions(RtInstance& currentInstance, const DrawCallState& drawCall); - void applyDecalOffsets(RtInstance& instance, const RasterGeometry& geometryData); - void createBillboards(RtInstance& instance, const Vector3& cameraViewDirection); void createBeams(RtInstance& instance); diff --git a/src/dxvk/rtx_render/rtx_materials.h b/src/dxvk/rtx_render/rtx_materials.h index 796d3e554..912f4021b 100644 --- a/src/dxvk/rtx_render/rtx_materials.h +++ b/src/dxvk/rtx_render/rtx_materials.h @@ -228,8 +228,10 @@ struct RtSurface { writeGPUHelper(data, offset, clipPlane); - // 16 bytes padding - writeGPUPadding<16>(data, offset); + writeGPUHelperExplicit<1>(data, offset, decalSortOrder); + + // 15 bytes padding + writeGPUPadding<15>(data, offset); assert(offset - oldOffset == kSurfaceGPUSize); } @@ -322,6 +324,7 @@ struct RtSurface { XXH64_hash_t associatedGeometryHash; // NOTE: This is used for the debug view uint32_t objectPickingValue = 0; // NOTE: a value to fill GBUFFER_BINDING_PRIMARY_OBJECT_PICKING_OUTPUT + uint32_t decalSortOrder = 0; // see: InstanceManager::m_decalSortOrderCounter }; // Shared Material Defaults/Limits diff --git a/src/dxvk/rtx_render/rtx_ngx_wrapper.cpp b/src/dxvk/rtx_render/rtx_ngx_wrapper.cpp index 237024890..2e3bb135c 100644 --- a/src/dxvk/rtx_render/rtx_ngx_wrapper.cpp +++ b/src/dxvk/rtx_render/rtx_ngx_wrapper.cpp @@ -403,7 +403,6 @@ namespace dxvk const Resources::Resource* pDiffuseAlbedo, const Resources::Resource* pSpecularAlbedo, const Resources::Resource* pExposure, - const Resources::Resource* pPosition, const Resources::Resource* pNormals, const Resources::Resource* pRoughness, const Resources::Resource* pBiasCurrentColorMask, diff --git a/src/dxvk/rtx_render/rtx_ngx_wrapper.h b/src/dxvk/rtx_render/rtx_ngx_wrapper.h index 60a042720..684bcd8a4 100644 --- a/src/dxvk/rtx_render/rtx_ngx_wrapper.h +++ b/src/dxvk/rtx_render/rtx_ngx_wrapper.h @@ -145,7 +145,6 @@ namespace dxvk { const Resources::Resource* pDiffuseAlbedo, const Resources::Resource* pSpecularAlbedo, const Resources::Resource* pExposure, - const Resources::Resource* pPosition, const Resources::Resource* pNormals, const Resources::Resource* pRoughness, const Resources::Resource* pBiasCurrentColorMask, diff --git a/src/dxvk/rtx_render/rtx_options.h b/src/dxvk/rtx_render/rtx_options.h index 9c49fef61..e9b50569b 100644 --- a/src/dxvk/rtx_render/rtx_options.h +++ b/src/dxvk/rtx_render/rtx_options.h @@ -554,21 +554,6 @@ namespace dxvk { "This is generally needed as albedo values for decals may be fairly low when dealing with opaque surfaces, but the translucent diffuse layer requires a fairly high albedo value to result in an expected look.\n" "The need for this option could be avoided by simply authoring decals applied to translucent materials with a higher albedo to begin with, but sometimes applications may share decals between different material types."); - struct Decals { - friend class RtxOptions; - friend class ImGUI; - - RTX_OPTION("rtx.decals", float, offsetMultiplierMeters, 0.00003f, - "[meters] Distance along a normal to offset between two adjacent decal offset indices to prevent coplanar rendering issues such as Z-fighting.\n" - "This value is multiplied by a decal offset index. The value should be kept small so as not make decals appear floating in front of their target backgrounds."); - RTX_OPTION("rtx.decals", uint32_t, baseOffsetIndex, 1, "Offset index of a first decal."); - RTX_OPTION("rtx.decals", uint32_t, maxOffsetIndex, 256, - "Max decal offset index. The offset index wraps around when this value is reached and is set to baseOffsetIndex again.\n" - "The value should be kept small so as not to offset decals too far from their target backgrounds."); - RTX_OPTION("rtx.decals", uint32_t, offsetIndexIncreaseBetweenDrawCalls, 1, "Index offset increase between decal draw calls. This can be useful to increase if default index of 1 is not enough to move decals from different draw calls apart enough."); - - }; - RTX_OPTION("rtx", float, worldSpaceUiBackgroundOffset, -0.01f, "Distance along normal to offset objects rendered as worldspace UI, specifically for the background of screens."); // Light Selection/Sampling Options @@ -1114,6 +1099,25 @@ namespace dxvk { GeometryHashGenerationRule = createRule("Geometry generation", geometryGenerationHashRuleString()); GeometryAssetHashRule = createRule("Geometry asset", geometryAssetHashRuleString()); + + // We deprecated dynamicDecalTextures, singleOffsetDecalTextures, nonOffsetDecalTextures with this change + // and replaced all decal texture lists with just a single list. + // TODO(REMIX-2554): Design a general deprecation solution for configs that are no longer required. + if (dynamicDecalTextures().size() > 0) { + decalTexturesRef().insert(dynamicDecalTextures().begin(), dynamicDecalTextures().end()); + dynamicDecalTexturesRef().clear(); + Logger::info("[Deprecated Config] rtx.dynamicDecalTextures has been deprecated, we have moved all your texture's from this list to rtx.decalTextures, no further action is required from you. Please re-save your rtx config to get rid of this message."); + } + if (singleOffsetDecalTextures().size() > 0) { + decalTexturesRef().insert(singleOffsetDecalTextures().begin(), singleOffsetDecalTextures().end()); + singleOffsetDecalTexturesRef().clear(); + Logger::info("[Deprecated Config] rtx.singleOffsetDecalTextures has been deprecated, we have moved all your texture's from this list to rtx.decalTextures, no further action is required from you. Please re-save your rtx config to get rid of this message."); + } + if (nonOffsetDecalTextures().size() > 0) { + decalTexturesRef().insert(nonOffsetDecalTextures().begin(), nonOffsetDecalTextures().end()); + nonOffsetDecalTexturesRef().clear(); + Logger::info("[Deprecated Config] rtx.nonOffsetDecalTextures has been deprecated, we have moved all your texture's from this list to rtx.decalTextures, no further action is required from you. Please re-save your rtx config to get rid of this message."); + } } void updateUpscalerFromDlssPreset(); diff --git a/src/dxvk/rtx_render/rtx_pathtracer_gbuffer.cpp b/src/dxvk/rtx_render/rtx_pathtracer_gbuffer.cpp index a215614dc..109cf8fb8 100644 --- a/src/dxvk/rtx_render/rtx_pathtracer_gbuffer.cpp +++ b/src/dxvk/rtx_render/rtx_pathtracer_gbuffer.cpp @@ -90,7 +90,6 @@ namespace dxvk { RW_TEXTURE2D(GBUFFER_BINDING_PRIMARY_HIT_DISTANCE_OUTPUT) RW_TEXTURE2D(GBUFFER_BINDING_PRIMARY_VIEW_DIRECTION_OUTPUT) RW_TEXTURE2D(GBUFFER_BINDING_PRIMARY_CONE_RADIUS_OUTPUT) - RW_TEXTURE2D(GBUFFER_BINDING_PRIMARY_WORLD_POSITION_OUTPUT) RW_TEXTURE2D(GBUFFER_BINDING_PRIMARY_POSITION_ERROR_OUTPUT) RW_TEXTURE2D(GBUFFER_BINDING_PRIMARY_OBJECT_PICKING_OUTPUT) @@ -116,10 +115,9 @@ namespace dxvk { SAMPLER2D(GBUFFER_BINDING_SKYMATTE) SAMPLERCUBE(GBUFFER_BINDING_SKYPROBE) - RW_TEXTURE2D(GBUFFER_BINDING_DECAL_MATERIAL_STORAGE) RW_TEXTURE2D(GBUFFER_BINDING_REFLECTION_PSR_DATA_STORAGE_0) + RW_TEXTURE2D(GBUFFER_BINDING_PRIMARY_WORLD_POSITION_OUTPUT) - RW_TEXTURE2D(GBUFFER_BINDING_DECAL_EMISSIVE_RADIANCE_STORAGE) RW_TEXTURE2D(GBUFFER_BINDING_REFLECTION_PSR_DATA_STORAGE_1) RW_TEXTURE2D(GBUFFER_BINDING_REFLECTION_PSR_DATA_STORAGE_2) @@ -218,7 +216,6 @@ namespace dxvk { ctx->bindResourceView(GBUFFER_BINDING_PRIMARY_HIT_DISTANCE_OUTPUT, rtOutput.m_primaryHitDistance.view, nullptr); ctx->bindResourceView(GBUFFER_BINDING_PRIMARY_VIEW_DIRECTION_OUTPUT, rtOutput.m_primaryViewDirection.view, nullptr); ctx->bindResourceView(GBUFFER_BINDING_PRIMARY_CONE_RADIUS_OUTPUT, rtOutput.m_primaryConeRadius.view, nullptr); - ctx->bindResourceView(GBUFFER_BINDING_PRIMARY_WORLD_POSITION_OUTPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view, nullptr); ctx->bindResourceView(GBUFFER_BINDING_PRIMARY_POSITION_ERROR_OUTPUT, rtOutput.m_primaryPositionError.view, nullptr); ctx->bindResourceView(GBUFFER_BINDING_PRIMARY_SURFACE_FLAGS_OUTPUT, rtOutput.m_primarySurfaceFlags.view, nullptr); ctx->bindResourceView(GBUFFER_BINDING_PRIMARY_DISOCCLUSION_THRESHOLD_MIX_OUTPUT, rtOutput.m_primaryDisocclusionThresholdMix.view, nullptr); @@ -241,15 +238,9 @@ namespace dxvk { ctx->bindResourceView(GBUFFER_BINDING_SECONDARY_WORLD_POSITION_OUTPUT, rtOutput.m_secondaryWorldPositionWorldTriangleNormal.view(Resources::AccessType::Write), nullptr); ctx->bindResourceView(GBUFFER_BINDING_ALPHA_BLEND_GBUFFER_OUTPUT, rtOutput.m_alphaBlendGBuffer.view, nullptr); - // Note: m_decalMaterial and m_gbufferPSRData[0] are aliased and both used in the G-buffer passes. - // - m_decalMaterial is used as intermediate storage in each G-buffer pass, but the data doesn't enter or leave the passes; - // - m_gbufferPSRData[] are used as outputs in the primary rays pass and inputs in the PSR passes. - // The decal textures are overwritten in the first (reflection) PSR pass, so that pass must use the PSR data aliased with decals as input. - ctx->bindResourceView(GBUFFER_BINDING_DECAL_MATERIAL_STORAGE, rtOutput.m_decalMaterial.view(Resources::AccessType::Write), nullptr); ctx->bindResourceView(GBUFFER_BINDING_REFLECTION_PSR_DATA_STORAGE_0, rtOutput.m_gbufferPSRData[0].view(Resources::AccessType::Write), nullptr); + ctx->bindResourceView(GBUFFER_BINDING_PRIMARY_WORLD_POSITION_OUTPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Write), nullptr); - // Note: m_decalEmissiveRadiance and m_gbufferPSRData[1] are aliased, see the comment above. - ctx->bindResourceView(GBUFFER_BINDING_DECAL_EMISSIVE_RADIANCE_STORAGE, rtOutput.m_decalEmissiveRadiance.view(Resources::AccessType::Write), nullptr); ctx->bindResourceView(GBUFFER_BINDING_REFLECTION_PSR_DATA_STORAGE_1, rtOutput.m_gbufferPSRData[1].view(Resources::AccessType::Write), nullptr); // Note: m_gbufferPSRData[2..6] are aliased with various radiance textures that are used later as integrator outputs. diff --git a/src/dxvk/rtx_render/rtx_pathtracer_integrate_direct.cpp b/src/dxvk/rtx_render/rtx_pathtracer_integrate_direct.cpp index 5262e66b9..496be4467 100644 --- a/src/dxvk/rtx_render/rtx_pathtracer_integrate_direct.cpp +++ b/src/dxvk/rtx_render/rtx_pathtracer_integrate_direct.cpp @@ -134,7 +134,7 @@ namespace dxvk { ctx->bindResourceView(INTEGRATE_DIRECT_BINDING_PRIMARY_ALBEDO_INPUT, rtOutput.m_primaryAlbedo.view, nullptr); ctx->bindResourceView(INTEGRATE_DIRECT_BINDING_PRIMARY_VIEW_DIRECTION_INPUT, rtOutput.m_primaryViewDirection.view, nullptr); ctx->bindResourceView(INTEGRATE_DIRECT_BINDING_PRIMARY_CONE_RADIUS_INPUT, rtOutput.m_primaryConeRadius.view, nullptr); - ctx->bindResourceView(INTEGRATE_DIRECT_BINDING_PRIMARY_WORLD_POSITION_WORLD_TRIANGLE_NORMAL_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view, nullptr); + ctx->bindResourceView(INTEGRATE_DIRECT_BINDING_PRIMARY_WORLD_POSITION_WORLD_TRIANGLE_NORMAL_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read), nullptr); ctx->bindResourceView(INTEGRATE_DIRECT_BINDING_PRIMARY_POSITION_ERROR_INPUT, rtOutput.m_primaryPositionError.view, nullptr); ctx->bindResourceBuffer(INTEGRATE_DIRECT_BINDING_PRIMARY_RTXDI_RESERVOIR, DxvkBufferSlice(rtOutput.m_rtxdiReservoirBuffer, 0, rtOutput.m_rtxdiReservoirBuffer->info().size)); diff --git a/src/dxvk/rtx_render/rtx_pathtracer_integrate_indirect.cpp b/src/dxvk/rtx_render/rtx_pathtracer_integrate_indirect.cpp index 5c712b93e..d7af6e211 100644 --- a/src/dxvk/rtx_render/rtx_pathtracer_integrate_indirect.cpp +++ b/src/dxvk/rtx_render/rtx_pathtracer_integrate_indirect.cpp @@ -91,9 +91,6 @@ namespace dxvk { TEXTURE2D(INTEGRATE_INDIRECT_BINDING_SECONDARY_HIT_DISTANCE_INPUT) TEXTURE2D(INTEGRATE_INDIRECT_BINDING_LAST_COMPOSITE_INPUT) - RW_TEXTURE2D(INTEGRATE_INDIRECT_BINDING_DECAL_MATERIAL_STORAGE) - RW_TEXTURE2D(INTEGRATE_INDIRECT_BINDING_DECAL_EMISSIVE_RADIANCE_STORAGE) - RW_TEXTURE2D(INTEGRATE_INDIRECT_BINDING_INDIRECT_RADIANCE_HIT_DISTANCE_OUTPUT) RW_STRUCTURED_BUFFER(INTEGRATE_INDIRECT_BINDING_RESTIR_GI_RESERVOIR_OUTPUT) RW_TEXTURE2D(INTEGRATE_INDIRECT_BINDING_RESTIR_GI_RADIANCE_OUTPUT) @@ -272,12 +269,12 @@ namespace dxvk { ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_PRIMARY_CONE_RADIUS_INPUT, rtOutput.m_primaryConeRadius.view, nullptr); ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_SECONDARY_CONE_RADIUS_INPUT, rtOutput.m_secondaryConeRadius.view(Resources::AccessType::Read), nullptr); - ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_PRIMARY_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view, nullptr); + ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_PRIMARY_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read), nullptr); ctx->bindResourceBuffer(INTEGRATE_INDIRECT_BINDING_PRIMARY_RTXDI_RESERVOIR, DxvkBufferSlice(rtOutput.m_rtxdiReservoirBuffer, 0, rtOutput.m_rtxdiReservoirBuffer->info().size)); ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_RAY_ORIGIN_DIRECTION_INPUT, rtOutput.m_indirectRayOriginDirection.view(Resources::AccessType::Read), nullptr); ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_FIRST_HIT_PERCEPTUAL_ROUGHNESS_INPUT, rtOutput.m_indirectFirstHitPerceptualRoughness.view(Resources::AccessType::Read), nullptr); ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_LAST_GBUFFER_INPUT, rtOutput.m_gbufferLast.view, nullptr); - ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_PREV_WORLD_POSITION_INPUT, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().view, nullptr); + ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_PREV_WORLD_POSITION_INPUT, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().matchesWriteFrameIdx(frameIdx - 1)), nullptr); ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_VOLUME_FILTERED_RADIANCE_INPUT, rtOutput.m_volumeFilteredRadiance.view, nullptr); ctx->bindResourceSampler(INTEGRATE_INDIRECT_BINDING_VOLUME_FILTERED_RADIANCE_INPUT, linearClampSampler); @@ -290,9 +287,6 @@ namespace dxvk { ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_LAST_COMPOSITE_INPUT, rtOutput.m_lastCompositeOutput.view(Resources::AccessType::Read, isLastCompositeOutputValid), nullptr); ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_FIRST_SAMPLED_LOBE_DATA_INPUT, rtOutput.m_indirectFirstSampledLobeData.view(Resources::AccessType::Read), nullptr); - // Storage resources - ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_DECAL_MATERIAL_STORAGE, rtOutput.m_decalMaterial.view(Resources::AccessType::Write), nullptr); - // Output resources ctx->bindResourceBuffer(INTEGRATE_INDIRECT_BINDING_RESTIR_GI_RESERVOIR_OUTPUT, DxvkBufferSlice(rtOutput.m_restirGIReservoirBuffer, 0, rtOutput.m_restirGIReservoirBuffer->info().size)); ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_RESTIR_GI_RADIANCE_OUTPUT, rtOutput.m_restirGIRadiance.view(Resources::AccessType::Write), nullptr); @@ -309,7 +303,6 @@ namespace dxvk { // Aliased resources // m_indirectRadiance writes the actual output carried forward and therefore it must be bound with write access last ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_THROUGHPUT_CONE_RADIUS_INPUT, rtOutput.m_indirectThroughputConeRadius.view(Resources::AccessType::Read), nullptr); - ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_DECAL_EMISSIVE_RADIANCE_STORAGE, rtOutput.m_decalEmissiveRadiance.view(Resources::AccessType::Write), nullptr); ctx->bindResourceView(INTEGRATE_INDIRECT_BINDING_INDIRECT_RADIANCE_HIT_DISTANCE_OUTPUT, rtOutput.m_indirectRadianceHitDistance.view(Resources::AccessType::Write), nullptr); DebugView& debugView = ctx->getDevice()->getCommon()->metaDebugView(); @@ -369,7 +362,7 @@ namespace dxvk { ctx->bindResourceView(INTEGRATE_NEE_BINDING_PRIMARY_ALBEDO_INPUT, rtOutput.m_primaryAlbedo.view, nullptr); ctx->bindResourceView(INTEGRATE_NEE_BINDING_PRIMARY_VIEW_DIRECTION_INPUT, rtOutput.m_primaryViewDirection.view, nullptr); ctx->bindResourceView(INTEGRATE_NEE_BINDING_PRIMARY_CONE_RADIUS_INPUT, rtOutput.m_primaryConeRadius.view, nullptr); - ctx->bindResourceView(INTEGRATE_NEE_BINDING_PRIMARY_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view, nullptr); + ctx->bindResourceView(INTEGRATE_NEE_BINDING_PRIMARY_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read), nullptr); ctx->bindResourceView(INTEGRATE_NEE_BINDING_PRIMARY_POSITION_ERROR_INPUT, rtOutput.m_primaryPositionError.view, nullptr); ctx->bindResourceView(INTEGRATE_NEE_BINDING_INDIRECT_RADIANCE_HIT_DISTANCE_INPUT, rtOutput.m_indirectRadianceHitDistance.view(Resources::AccessType::Read), nullptr); ctx->bindResourceView(INTEGRATE_NEE_BINDING_HIT_GEOMETRY_INPUT, rtOutput.m_restirGIHitGeometry.view, nullptr); diff --git a/src/dxvk/rtx_render/rtx_resources.cpp b/src/dxvk/rtx_render/rtx_resources.cpp index 915bc1a49..349e9b79b 100644 --- a/src/dxvk/rtx_render/rtx_resources.cpp +++ b/src/dxvk/rtx_render/rtx_resources.cpp @@ -335,9 +335,12 @@ namespace dxvk { // Alias resources that alias to different resources frame to frame m_raytracingOutput.m_secondaryConeRadius = AliasedResource(m_raytracingOutput.getCurrentRtxdiConfidence(), ctx, m_downscaledExtent, VK_FORMAT_R16_SFLOAT, "Secondary Cone Radius"); m_raytracingOutput.m_sharedIntegrationSurfacePdf = AliasedResource(m_raytracingOutput.getCurrentRtxdiIlluminance(), ctx, m_downscaledExtent, VK_FORMAT_R16_SFLOAT, "Shared Integration Surface PDF"); + m_raytracingOutput.m_gbufferPSRData[0] = AliasedResource(m_raytracingOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal(), ctx, m_downscaledExtent, VK_FORMAT_R32G32B32A32_SFLOAT, "GBuffer PSR Data 0"); + assert( m_raytracingOutput.m_secondaryConeRadius.sharesTheSameView(m_raytracingOutput.getCurrentRtxdiConfidence()) && m_raytracingOutput.m_sharedIntegrationSurfacePdf.sharesTheSameView(m_raytracingOutput.getCurrentRtxdiIlluminance()) && + m_raytracingOutput.m_gbufferPSRData[0].sharesTheSameView(m_raytracingOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal()) && "New view for an aliased resource was created on the fly. Avoid doing that or ensure it has no negative side effects."); } @@ -787,8 +790,8 @@ namespace dxvk { m_raytracingOutput.m_primaryHitDistance = createImageResource(ctx, "primary hit distance", m_downscaledExtent, VK_FORMAT_R32_SFLOAT); m_raytracingOutput.m_primaryViewDirection = createImageResource(ctx, "primary view direction", m_downscaledExtent, VK_FORMAT_R16G16_SNORM); m_raytracingOutput.m_primaryConeRadius = createImageResource(ctx, "primary cone radius", m_downscaledExtent, VK_FORMAT_R16_SFLOAT); - m_raytracingOutput.m_primaryWorldPositionWorldTriangleNormal[0] = createImageResource(ctx, "primary world position world triangle normal 0", m_downscaledExtent, VK_FORMAT_R32G32B32A32_SFLOAT); - m_raytracingOutput.m_primaryWorldPositionWorldTriangleNormal[1] = createImageResource(ctx, "primary world position world triangle normal 1", m_downscaledExtent, VK_FORMAT_R32G32B32A32_SFLOAT); + m_raytracingOutput.m_primaryWorldPositionWorldTriangleNormal[0] = AliasedResource(ctx, m_downscaledExtent, VK_FORMAT_R32G32B32A32_SFLOAT, "primary world position world triangle normal 0"); + m_raytracingOutput.m_primaryWorldPositionWorldTriangleNormal[1] = AliasedResource(ctx, m_downscaledExtent, VK_FORMAT_R32G32B32A32_SFLOAT, "primary world position world triangle normal 1"); m_raytracingOutput.m_primaryPositionError = createImageResource(ctx, "primary position error", m_downscaledExtent, VK_FORMAT_R32_SFLOAT); m_raytracingOutput.m_primaryRtxdiIlluminance[0] = AliasedResource(ctx, m_downscaledExtent, VK_FORMAT_R16_SFLOAT, "Primary RTXDI Illuminance [0]"); @@ -817,11 +820,9 @@ namespace dxvk { m_raytracingOutput.m_secondaryViewDirection = AliasedResource(ctx, m_downscaledExtent, VK_FORMAT_R16G16_SNORM, "Secondary View Direction", allowCompatibleFormatAliasing); m_raytracingOutput.m_secondaryWorldPositionWorldTriangleNormal = AliasedResource(ctx, m_downscaledExtent, VK_FORMAT_R32G32B32A32_SFLOAT, "Secondary World Position World Triangle Normal", allowCompatibleFormatAliasing); m_raytracingOutput.m_secondaryPositionError = AliasedResource(ctx, m_downscaledExtent, VK_FORMAT_R32_SFLOAT, "Secondary Position Error", allowCompatibleFormatAliasing); - m_raytracingOutput.m_decalMaterial = AliasedResource(ctx, m_downscaledExtent, VK_FORMAT_R32G32B32A32_UINT, "Decal Material"); - m_raytracingOutput.m_decalEmissiveRadiance = AliasedResource(ctx, m_downscaledExtent, VK_FORMAT_R16G16B16A16_SFLOAT, "Decal Emissive Radiance", allowCompatibleFormatAliasing); m_raytracingOutput.m_alphaBlendGBuffer = createImageResource(ctx, "alpha blend gbuffer", m_downscaledExtent, VK_FORMAT_R32G32B32A32_UINT); m_raytracingOutput.m_alphaBlendRadiance = AliasedResource(m_raytracingOutput.m_secondaryVirtualMotionVector, ctx, m_downscaledExtent, VK_FORMAT_R16G16B16A16_SFLOAT, "Alpha Blend Radiance"); - m_raytracingOutput.m_indirectRadianceHitDistance = AliasedResource(m_raytracingOutput.m_decalEmissiveRadiance, ctx, m_downscaledExtent, VK_FORMAT_R16G16B16A16_SFLOAT, "Indirect Radiance Hit Distance"); + m_raytracingOutput.m_indirectRadianceHitDistance = AliasedResource(ctx, m_downscaledExtent, VK_FORMAT_R16G16B16A16_SFLOAT, "Indirect Radiance Hit Distance", allowCompatibleFormatAliasing); // Denoiser input and output (Primary/Secondary Surfaces with Direct/Indirect or Combined Radiance) // Note: A single texture is aliased for both the noisy output from the integration pass and the denoised result from NRD. @@ -832,8 +833,7 @@ namespace dxvk { m_raytracingOutput.m_secondaryCombinedDiffuseRadiance = AliasedResource(ctx, m_downscaledExtent, VK_FORMAT_R16G16B16A16_SFLOAT, "Secondary Combined Diffuse Radiance", allowCompatibleFormatAliasing); m_raytracingOutput.m_secondaryCombinedSpecularRadiance = AliasedResource(ctx, m_downscaledExtent, VK_FORMAT_R16G16B16A16_SFLOAT, "Secondary Combined Specular Radiance", allowCompatibleFormatAliasing); - m_raytracingOutput.m_gbufferPSRData[0] = AliasedResource(m_raytracingOutput.m_decalMaterial, ctx, m_downscaledExtent, VK_FORMAT_R32G32B32A32_UINT, "GBuffer PSR Data 0"); - m_raytracingOutput.m_gbufferPSRData[1] = AliasedResource(m_raytracingOutput.m_decalEmissiveRadiance, ctx, m_downscaledExtent, VK_FORMAT_R32G32_UINT, "GBuffer PSR Data 1"); + m_raytracingOutput.m_gbufferPSRData[1] = AliasedResource(m_raytracingOutput.m_primaryIndirectDiffuseRadiance, ctx, m_downscaledExtent, VK_FORMAT_R32G32_UINT, "GBuffer PSR Data 1", allowCompatibleFormatAliasing); m_raytracingOutput.m_gbufferPSRData[2] = AliasedResource(m_raytracingOutput.m_primaryDirectDiffuseRadiance, ctx, m_downscaledExtent, VK_FORMAT_R32G32_UINT, "GBuffer PSR Data 2"); m_raytracingOutput.m_gbufferPSRData[3] = AliasedResource(m_raytracingOutput.m_primaryDirectSpecularRadiance, ctx, m_downscaledExtent, VK_FORMAT_R32G32_UINT, "GBuffer PSR Data 3"); m_raytracingOutput.m_gbufferPSRData[4] = AliasedResource(m_raytracingOutput.m_primaryIndirectSpecularRadiance, ctx, m_downscaledExtent, VK_FORMAT_R32G32_UINT, "GBuffer PSR Data 4"); @@ -843,8 +843,9 @@ namespace dxvk { m_raytracingOutput.m_indirectRayOriginDirection = AliasedResource( m_raytracingOutput.m_secondaryWorldPositionWorldTriangleNormal, ctx, m_downscaledExtent, VK_FORMAT_R32G32B32A32_SFLOAT, "Indirect Ray Origin Direction"); m_raytracingOutput.m_indirectThroughputConeRadius = AliasedResource( - m_raytracingOutput.m_decalEmissiveRadiance, ctx, m_downscaledExtent, VK_FORMAT_R16G16B16A16_SFLOAT, "Indirect Throughput Cone Radius"); - m_raytracingOutput.m_indirectFirstSampledLobeData = AliasedResource(m_raytracingOutput.m_secondaryPositionError, ctx, m_downscaledExtent, VK_FORMAT_R32_UINT, "Indirect First Sampled Lobe Data"); + m_raytracingOutput.m_indirectRadianceHitDistance, ctx, m_downscaledExtent, VK_FORMAT_R16G16B16A16_SFLOAT, "Indirect Throughput Cone Radius", allowCompatibleFormatAliasing); + m_raytracingOutput.m_indirectFirstSampledLobeData = AliasedResource( + m_raytracingOutput.m_secondaryPositionError, ctx, m_downscaledExtent, VK_FORMAT_R32_UINT, "Indirect First Sampled Lobe Data"); m_raytracingOutput.m_indirectFirstHitPerceptualRoughness = AliasedResource( m_raytracingOutput.m_secondaryPerceptualRoughness, ctx, m_downscaledExtent, VK_FORMAT_R8_UNORM, "Indirect First Hit Perceptual Roughness"); m_raytracingOutput.m_bsdfFactor = createImageResource(ctx, "bsdf factor", m_downscaledExtent, VK_FORMAT_R16G16_SFLOAT); diff --git a/src/dxvk/rtx_render/rtx_resources.h b/src/dxvk/rtx_render/rtx_resources.h index f08c5fc53..d89cd630f 100644 --- a/src/dxvk/rtx_render/rtx_resources.h +++ b/src/dxvk/rtx_render/rtx_resources.h @@ -263,7 +263,7 @@ namespace dxvk Resource m_primaryHitDistance; Resource m_primaryViewDirection; Resource m_primaryConeRadius; - Resource m_primaryWorldPositionWorldTriangleNormal[2]; + AliasedResource m_primaryWorldPositionWorldTriangleNormal[2]; Resource m_primaryPositionError; AliasedResource m_primaryRtxdiIlluminance[2]; Resource m_primaryRtxdiTemporalPosition; @@ -286,8 +286,6 @@ namespace dxvk AliasedResource m_secondaryConeRadius; AliasedResource m_secondaryWorldPositionWorldTriangleNormal; AliasedResource m_secondaryPositionError; - AliasedResource m_decalMaterial; - AliasedResource m_decalEmissiveRadiance; Resource m_alphaBlendGBuffer; AliasedResource m_alphaBlendRadiance; @@ -354,8 +352,8 @@ namespace dxvk const AliasedResource& getPreviousRtxdiIlluminance() const { return m_primaryRtxdiIlluminance[!m_swapTextures]; } const AliasedResource& getCurrentRtxdiConfidence() const { return m_rtxdiConfidence[m_swapTextures]; } const AliasedResource& getPreviousRtxdiConfidence() const { return m_rtxdiConfidence[!m_swapTextures]; } - const Resource& getCurrentPrimaryWorldPositionWorldTriangleNormal() const { return m_primaryWorldPositionWorldTriangleNormal[m_swapTextures]; } - const Resource& getPreviousPrimaryWorldPositionWorldTriangleNormal() const { return m_primaryWorldPositionWorldTriangleNormal[!m_swapTextures]; } + const AliasedResource& getCurrentPrimaryWorldPositionWorldTriangleNormal() const { return m_primaryWorldPositionWorldTriangleNormal[m_swapTextures]; } + const AliasedResource& getPreviousPrimaryWorldPositionWorldTriangleNormal() const { return m_primaryWorldPositionWorldTriangleNormal[!m_swapTextures]; } const Resource& getCurrentVolumeReservoirs() const { return m_volumeReservoirs[m_swapTextures]; } const Resource& getPreviousVolumeReservoirs() const { return m_volumeReservoirs[!m_swapTextures]; } const Resource& getCurrentVolumeAccumulatedRadiance() const { return m_volumeAccumulatedRadiance[m_swapTextures]; } diff --git a/src/dxvk/rtx_render/rtx_restir_gi_rayquery.cpp b/src/dxvk/rtx_render/rtx_restir_gi_rayquery.cpp index 47c326684..983be7e17 100644 --- a/src/dxvk/rtx_render/rtx_restir_gi_rayquery.cpp +++ b/src/dxvk/rtx_render/rtx_restir_gi_rayquery.cpp @@ -205,6 +205,7 @@ namespace dxvk { ScopedGpuProfileZone(ctx, "ReSTIR GI"); + const uint32_t frameIdx = ctx->getDevice()->getCurrentFrameId(); const auto& numRaysExtent = rtOutput.m_compositeOutputExtent; VkExtent3D workgroups = util::computeBlockCount(numRaysExtent, VkExtent3D { 16, 8, 1 }); @@ -219,8 +220,8 @@ namespace dxvk { ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_HIT_DISTANCE_INPUT, rtOutput.m_primaryHitDistance.view, nullptr); ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_ALBEDO_INPUT, rtOutput.m_primaryAlbedo.view, nullptr); ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_BASE_REFLECTIVITY_INPUT, rtOutput.m_primaryBaseReflectivity.view(Resources::AccessType::Read), nullptr); - ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view, nullptr); - ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_PREV_WORLD_POSITION_INPUT, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().view, nullptr); + ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read), nullptr); + ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_PREV_WORLD_POSITION_INPUT, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().matchesWriteFrameIdx(frameIdx - 1)), nullptr); ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_VIEW_DIRECTION_INPUT, rtOutput.m_primaryViewDirection.view, nullptr); ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_CONE_RADIUS_INPUT, rtOutput.m_primaryConeRadius.view, nullptr); ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_LAST_GBUFFER, rtOutput.m_gbufferLast.view, nullptr); @@ -246,8 +247,8 @@ namespace dxvk { ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_HIT_DISTANCE_INPUT, rtOutput.m_primaryHitDistance.view, nullptr); ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_ALBEDO_INPUT, rtOutput.m_primaryAlbedo.view, nullptr); ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_BASE_REFLECTIVITY_INPUT, rtOutput.m_primaryBaseReflectivity.view(Resources::AccessType::Read), nullptr); - ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view, nullptr); - ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_PREV_WORLD_POSITION_INPUT, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().view, nullptr); + ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read), nullptr); + ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_PREV_WORLD_POSITION_INPUT, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().matchesWriteFrameIdx(frameIdx - 1)), nullptr); ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_VIEW_DIRECTION_INPUT, rtOutput.m_primaryViewDirection.view, nullptr); ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_CONE_RADIUS_INPUT, rtOutput.m_primaryConeRadius.view, nullptr); ctx->bindResourceView(RESTIR_GI_REUSE_BINDING_LAST_GBUFFER, rtOutput.m_gbufferLast.view, nullptr); @@ -283,7 +284,7 @@ namespace dxvk { ctx->bindResourceView(RESTIR_GI_FINAL_SHADING_BINDING_PRIMARY_ALBEDO_INPUT, rtOutput.m_primaryAlbedo.view, nullptr); ctx->bindResourceView(RESTIR_GI_FINAL_SHADING_BINDING_PRIMARY_VIEW_DIRECTION_INPUT, rtOutput.m_primaryViewDirection.view, nullptr); ctx->bindResourceView(RESTIR_GI_FINAL_SHADING_BINDING_PRIMARY_CONE_RADIUS_INPUT, rtOutput.m_primaryConeRadius.view, nullptr); - ctx->bindResourceView(RESTIR_GI_FINAL_SHADING_BINDING_PRIMARY_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view, nullptr); + ctx->bindResourceView(RESTIR_GI_FINAL_SHADING_BINDING_PRIMARY_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read), nullptr); ctx->bindResourceView(RESTIR_GI_FINAL_SHADING_BINDING_PRIMARY_POSITION_ERROR_INPUT, rtOutput.m_primaryPositionError.view, nullptr); ctx->bindResourceView(RESTIR_GI_FINAL_SHADING_BINDING_PRIMARY_BASE_REFLECTIVITY_INPUT_OUTPUT, rtOutput.m_primaryBaseReflectivity.view(Resources::AccessType::ReadWrite), nullptr); diff --git a/src/dxvk/rtx_render/rtx_rtxdi_rayquery.cpp b/src/dxvk/rtx_render/rtx_rtxdi_rayquery.cpp index 6cd7e28fd..5c983d2df 100644 --- a/src/dxvk/rtx_render/rtx_rtxdi_rayquery.cpp +++ b/src/dxvk/rtx_render/rtx_rtxdi_rayquery.cpp @@ -232,11 +232,13 @@ namespace dxvk { if (!RtxOptions::Get()->useRTXDI()) return; + const uint32_t frameIdx = ctx->getDevice()->getCurrentFrameId(); + const auto& numRaysExtent = rtOutput.m_compositeOutputExtent; VkExtent3D workgroups = util::computeBlockCount(numRaysExtent, VkExtent3D{ 16, 8, 1 }); ctx->bindCommonRayTracingResources(rtOutput); - + { ScopedGpuProfileZone(ctx, "RTXDI Initial & Temporal Reuse"); @@ -248,8 +250,8 @@ namespace dxvk { ctx->bindResourceView(RTXDI_REUSE_BINDING_ALBEDO_INPUT, rtOutput.m_primaryAlbedo.view, nullptr); // Note: Texture contains Base Reflectivity here (due to being before the demodulate pass) ctx->bindResourceView(RTXDI_REUSE_BINDING_BASE_REFLECTIVITY_INPUT, rtOutput.m_primaryBaseReflectivity.view(Resources::AccessType::Read), nullptr); - ctx->bindResourceView(RTXDI_REUSE_BINDING_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view, nullptr); - ctx->bindResourceView(RTXDI_REUSE_BINDING_PREV_WORLD_POSITION_INPUT, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().view, nullptr); + ctx->bindResourceView(RTXDI_REUSE_BINDING_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read), nullptr); + ctx->bindResourceView(RTXDI_REUSE_BINDING_PREV_WORLD_POSITION_INPUT, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().matchesWriteFrameIdx(frameIdx - 1)), nullptr); ctx->bindResourceView(RTXDI_REUSE_BINDING_WS_MVEC_INPUT_OUTPUT, rtOutput.m_primaryVirtualMotionVector.view, nullptr); ctx->bindResourceView(RTXDI_REUSE_BINDING_SS_MVEC_INPUT, rtOutput.m_primaryScreenSpaceMotionVector.view, nullptr); ctx->bindResourceView(RTXDI_REUSE_BINDING_VIEW_DIRECTION_INPUT, rtOutput.m_primaryViewDirection.view, nullptr); @@ -269,8 +271,7 @@ namespace dxvk { } { - ScopedGpuProfileZone(ctx, "RTXDI Spatial Reuse"); - + ScopedGpuProfileZone(ctx, "RTXDI Spatial Reuse"); // Note: Primary buffers bound as these exhibit coherency for RTXDI and denoising. ctx->bindResourceBuffer(RTXDI_REUSE_BINDING_RTXDI_RESERVOIR, DxvkBufferSlice(rtOutput.m_rtxdiReservoirBuffer, 0, rtOutput.m_rtxdiReservoirBuffer->info().size)); ctx->bindResourceView(RTXDI_REUSE_BINDING_WORLD_SHADING_NORMAL_INPUT, rtOutput.m_primaryWorldShadingNormal.view, nullptr); @@ -278,8 +279,8 @@ namespace dxvk { ctx->bindResourceView(RTXDI_REUSE_BINDING_HIT_DISTANCE_INPUT, rtOutput.m_primaryHitDistance.view, nullptr); ctx->bindResourceView(RTXDI_REUSE_BINDING_ALBEDO_INPUT, rtOutput.m_primaryAlbedo.view, nullptr); ctx->bindResourceView(RTXDI_REUSE_BINDING_BASE_REFLECTIVITY_INPUT, rtOutput.m_primaryBaseReflectivity.view(Resources::AccessType::Read), nullptr); - ctx->bindResourceView(RTXDI_REUSE_BINDING_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view, nullptr); - ctx->bindResourceView(RTXDI_REUSE_BINDING_PREV_WORLD_POSITION_INPUT, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().view, nullptr); + ctx->bindResourceView(RTXDI_REUSE_BINDING_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read), nullptr); + ctx->bindResourceView(RTXDI_REUSE_BINDING_PREV_WORLD_POSITION_INPUT, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().matchesWriteFrameIdx(frameIdx - 1)), nullptr); ctx->bindResourceView(RTXDI_REUSE_BINDING_WS_MVEC_INPUT_OUTPUT, rtOutput.m_primaryVirtualMotionVector.view, nullptr); ctx->bindResourceView(RTXDI_REUSE_BINDING_SS_MVEC_INPUT, rtOutput.m_primaryScreenSpaceMotionVector.view, nullptr); ctx->bindResourceView(RTXDI_REUSE_BINDING_VIEW_DIRECTION_INPUT, rtOutput.m_primaryViewDirection.view, nullptr); @@ -317,8 +318,8 @@ namespace dxvk { ScopedGpuProfileZone(ctx, "Compute Gradients"); ctx->bindResourceBuffer(RTXDI_COMPUTE_GRADIENTS_BINDING_RTXDI_RESERVOIR, DxvkBufferSlice(rtOutput.m_rtxdiReservoirBuffer, 0, rtOutput.m_rtxdiReservoirBuffer->info().size)); - ctx->bindResourceView(RTXDI_COMPUTE_GRADIENTS_BINDING_CURRENT_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view, nullptr); - ctx->bindResourceView(RTXDI_COMPUTE_GRADIENTS_BINDING_PREVIOUS_WORLD_POSITION_INPUT, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().view, nullptr); + ctx->bindResourceView(RTXDI_COMPUTE_GRADIENTS_BINDING_CURRENT_WORLD_POSITION_INPUT, rtOutput.getCurrentPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read), nullptr); + ctx->bindResourceView(RTXDI_COMPUTE_GRADIENTS_BINDING_PREVIOUS_WORLD_POSITION_INPUT, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().view(Resources::AccessType::Read, rtOutput.getPreviousPrimaryWorldPositionWorldTriangleNormal().matchesWriteFrameIdx(frameIdx - 1)), nullptr); ctx->bindResourceView(RTXDI_COMPUTE_GRADIENTS_BINDING_CONE_RADIUS_INPUT, rtOutput.m_primaryConeRadius.view, nullptr); ctx->bindResourceView(RTXDI_COMPUTE_GRADIENTS_BINDING_MVEC_INPUT, rtOutput.m_primaryVirtualMotionVector.view, nullptr); ctx->bindResourceView(RTXDI_COMPUTE_GRADIENTS_BINDING_POSITION_ERROR_INPUT, rtOutput.m_primaryPositionError.view, nullptr); diff --git a/src/dxvk/shaders/rtx/algorithm/geometry_resolver.slangh b/src/dxvk/shaders/rtx/algorithm/geometry_resolver.slangh index de0794884..96afbccc1 100644 --- a/src/dxvk/shaders/rtx/algorithm/geometry_resolver.slangh +++ b/src/dxvk/shaders/rtx/algorithm/geometry_resolver.slangh @@ -257,7 +257,7 @@ void geometryResolverOutputSurface( { minimalSurfaceInteractionWriteToGBuffer( surfaceInteraction, ivec2(pixelCoordinate), - PrimaryWorldPositionWorldTriangleNormal, + aliasedData0.PrimaryWorldPositionWorldTriangleNormal, PrimaryPositionError); PrimaryWorldInterpolatedNormal[pixelCoordinate] = float2x32ToSnorm2x16(sphereDirectionToSignedOctahedral(surfaceInteraction.interpolatedNormal)); } @@ -1009,13 +1009,26 @@ void geometryResolverVertex( uint numUnorderedInteractions = 0; uint8_t unorderedRayMask = convertPrimaryRayMaskToUnordered(geometryResolverState.rayMask, OBJECT_MASK_ALL_UNORDERED); + bool unorderedDecalEncountered = false; + uint4 decalMemory = 0; + f16vec3 decalEmissiveRadiance = f16vec3(0); resolveVertexUnordered( resolveMode, unorderedResolveRay, unorderedRayMask, geometryResolverState.portalSpace, /* useIntersectionBillboards = */ cb.enableBillboardOrientationCorrection && (geometryResolverState.directionAltered || cb.useIntersectionBillboardsOnPrimaryRays), geometryResolverState.accumulatedVectorTransform, geometryResolverState.accumulatedHitDistance, radianceAttenuation, emissiveRadiance, - numUnorderedInteractions); + numUnorderedInteractions, + unorderedDecalEncountered, decalMemory, decalEmissiveRadiance); + + if (cb.debugView == DEBUG_VIEW_PRIMARY_DECAL_ALBEDO) + { + MemoryDecalMaterialInteraction memory; + memory.packed = decalMemory; + memory.emissiveRadiance = decalEmissiveRadiance; + DecalMaterialInteraction decalMaterialInteraction = decalMaterialInteractionUnpack(memory); + storeInDebugView(geometryResolverState.pixelCoordinate, decalMaterialInteraction.albedo); + } // Note: Add to the number of unordered interactions in the debug view based on the number of unordered interactions in resolving. if (cb.debugView == DEBUG_VIEW_PRIMARY_UNORDERED_INTERACTIONS || cb.debugView == DEBUG_VIEW_PRIMARY_RAY_AND_UNORDERED_INTERACTIONS) @@ -1045,7 +1058,7 @@ void geometryResolverVertex( hackState.rayMask = geometryResolverState.rayMask; hackState.portalSpace = geometryResolverState.portalSpace; hackState.accumulatedVectorTransform = geometryResolverState.accumulatedVectorTransform; - hackState.decalEncountered = geometryResolverState.decalEncountered; + hackState.decalEncountered = geometryResolverState.decalEncountered || unorderedDecalEncountered; hackState.pixelCoordinate = geometryResolverState.pixelCoordinate; hackState.isStochasticAlphaBlend = false; @@ -1056,7 +1069,7 @@ void geometryResolverVertex( surface, surfaceInteraction, polymorphicSurfaceMaterialInteraction, radianceAttenuation, emissiveRadiance, - aliasedData0.DecalMaterial, aliasedData1.DecalEmissiveRadiance, false, true); + decalMemory, decalEmissiveRadiance, false, true); // Todo: Remove hack thing geometryResolverState.origin = hackState.origin; @@ -1467,13 +1480,17 @@ void geometryPSRResolverVertex( uint numUnorderedInteractions = 0; uint8_t unorderedRayMask = convertPrimaryRayMaskToUnordered(geometryPSRResolverState.rayMask, OBJECT_MASK_ALL_UNORDERED); + bool unorderedDecalEncountered = false; + uint4 decalMemory = 0; + f16vec3 decalEmissiveRadiance = f16vec3(0); resolveVertexUnordered( resolveMode, unorderedResolveRay, unorderedRayMask, geometryPSRResolverState.portalSpace, /* useIntersectionBillboards = */ cb.enableBillboardOrientationCorrection, geometryPSRResolverState.accumulatedVectorTransform, geometryPSRResolverState.accumulatedHitDistance, radianceAttenuation, emissiveRadiance, - numUnorderedInteractions); + numUnorderedInteractions, + unorderedDecalEncountered, decalMemory, decalEmissiveRadiance); // Note: Add to the number of unordered interactions in the debug view based on the number of unordered interactions in resolving. if (cb.debugView == DEBUG_VIEW_PRIMARY_UNORDERED_INTERACTIONS || cb.debugView == DEBUG_VIEW_PRIMARY_RAY_AND_UNORDERED_INTERACTIONS) @@ -1500,7 +1517,7 @@ void geometryPSRResolverVertex( hackState.rayMask = geometryPSRResolverState.rayMask; hackState.portalSpace = geometryPSRResolverState.portalSpace; hackState.accumulatedVectorTransform = geometryPSRResolverState.accumulatedVectorTransform; - hackState.decalEncountered = geometryPSRResolverState.decalEncountered; + hackState.decalEncountered = geometryPSRResolverState.decalEncountered || unorderedDecalEncountered; hackState.pixelCoordinate = geometryPSRResolverState.pixelCoordinate; resolveVertex( @@ -1510,7 +1527,7 @@ void geometryPSRResolverVertex( surface, surfaceInteraction, polymorphicSurfaceMaterialInteraction, radianceAttenuation, emissiveRadiance, - aliasedData0.DecalMaterial, aliasedData1.DecalEmissiveRadiance); + decalMemory, decalEmissiveRadiance); // Todo: Remove hack thing geometryPSRResolverState.origin = hackState.origin; diff --git a/src/dxvk/shaders/rtx/algorithm/geometry_resolver_state.slangh b/src/dxvk/shaders/rtx/algorithm/geometry_resolver_state.slangh index 2bbd4ef76..b657af912 100644 --- a/src/dxvk/shaders/rtx/algorithm/geometry_resolver_state.slangh +++ b/src/dxvk/shaders/rtx/algorithm/geometry_resolver_state.slangh @@ -381,23 +381,20 @@ void unpackPSRData(GbufferPSRData psrData, inout GeometryPSRResolverState geomet void storeReflectionPSRData(GbufferPSRData psrData, uint2 pixelCoordinate) { - // Note: since PSRData0 and PSRData1 are aliased with DecalMaterial and DecalEmissiveRadiance, - // it is very important that the reflection PSR pass happens right after the primary rays. - // Otherwise, the transmission PSR pass would overwrite the reflection data with its decals. - aliasedData0.ReflectionPSRData0[pixelCoordinate] = uint4(psrData.origin.xyz, psrData.encodedDirection); - aliasedData1.ReflectionPSRData1[pixelCoordinate] = uint2(psrData.encodedAccumulatedVectorTransform.xy); + aliasedData0.ReflectionPSRData0[pixelCoordinate] = asfloat(uint4(psrData.origin.xyz, psrData.encodedDirection)); + ReflectionPSRData1[pixelCoordinate] = uint2(psrData.encodedAccumulatedVectorTransform.xy); ReflectionPSRData2[pixelCoordinate] = uint2(psrData.attenuation, psrData.mediumMaterialIndexAndGeometryFlags); } GbufferPSRData loadReflectionPSRData(uint2 pixelCoordinate) { - uint4 data0 = aliasedData0.ReflectionPSRData0[pixelCoordinate]; - uint2 data1 = aliasedData1.ReflectionPSRData1[pixelCoordinate]; + uint4 data0 = asuint(aliasedData0.ReflectionPSRData0[pixelCoordinate]); + uint2 data1 = ReflectionPSRData1[pixelCoordinate]; uint2 data2 = ReflectionPSRData2[pixelCoordinate]; // Clear the PSR data to prevent storing NaNs in these aliased resources aliasedData0.ReflectionPSRData0[pixelCoordinate] = 0; - aliasedData1.ReflectionPSRData1[pixelCoordinate] = 0; + ReflectionPSRData1[pixelCoordinate] = 0; ReflectionPSRData2[pixelCoordinate] = 0; GbufferPSRData psrData; diff --git a/src/dxvk/shaders/rtx/algorithm/integrator_indirect.slangh b/src/dxvk/shaders/rtx/algorithm/integrator_indirect.slangh index 0e56e4bc7..506088418 100644 --- a/src/dxvk/shaders/rtx/algorithm/integrator_indirect.slangh +++ b/src/dxvk/shaders/rtx/algorithm/integrator_indirect.slangh @@ -204,6 +204,9 @@ void integratePathVertex( // between the origin and the hit point can be accumulated in advance. // Note: Only do unordered resolving when separate unordered approximations are desired for this bounce of the path. + bool unorderedDecalEncountered = false; + uint4 decalMemory = 0; + f16vec3 decalEmissiveRadiance = f16vec3(0); if (separateUnorderedApproximations) { Ray unorderedResolveRay; @@ -224,7 +227,8 @@ void integratePathVertex( /* useIntersectionBillboards = */ cb.enableBillboardOrientationCorrection, pathState.accumulatedHitDistance, radianceAttenuation, emissiveRadiance, - numUnorderedInteractions); + numUnorderedInteractions, + unorderedDecalEncountered, decalMemory, decalEmissiveRadiance); if (cb.debugView == DEBUG_VIEW_SECONDARY_UNORDERED_INTERACTIONS || cb.debugView == DEBUG_VIEW_SECONDARY_RAY_AND_UNORDERED_INTERACTIONS) { @@ -251,7 +255,7 @@ void integratePathVertex( hackState.portalSpace = pathState.portalSpace; hackState.rayMask = pathState.rayMask; hackState.firstRayPortal = invalidRayPortalIndex; - hackState.decalEncountered = pathState.decalEncountered; + hackState.decalEncountered = pathState.decalEncountered || unorderedDecalEncountered; hackState.pixelCoordinate = pathState.pixelCoordinate; resolveVertex( @@ -261,7 +265,7 @@ void integratePathVertex( surface, surfaceInteraction, polymorphicSurfaceMaterialInteraction, radianceAttenuation, emissiveRadiance, - DecalMaterial, aliasedData0.DecalEmissiveRadiance); + decalMemory, decalEmissiveRadiance); // Todo: Remove hack thing vec3 oldOrigin = pathState.origin; diff --git a/src/dxvk/shaders/rtx/algorithm/resolve.slangh b/src/dxvk/shaders/rtx/algorithm/resolve.slangh index 7e402b5e1..2a6fa240b 100644 --- a/src/dxvk/shaders/rtx/algorithm/resolve.slangh +++ b/src/dxvk/shaders/rtx/algorithm/resolve.slangh @@ -303,8 +303,8 @@ void resolveVertex( inout Surface surface, inout SurfaceInteraction surfaceInteraction, inout PolymorphicSurfaceMaterialInteraction polymorphicSurfaceMaterialInteraction, inout f16vec3 radianceAttenuation, inout vec3 emissiveRadiance, - RWTexture2D decalMaterialTexture, - RWTexture2D decalEmissiveRadianceTexture, + uint4 decalMemory, + f16vec3 decalEmissiveRadiance, // Forces enablement of ray portal resolve path regardless of global resolve mask // Needed for RayQuery paths for visibility rays from CHS as they don't run material specific hit groups // Visibility rays are expected not to start from RayPortal surfaces, and thus only RayPortal path is force enabled @@ -395,8 +395,8 @@ void resolveVertex( if (decalMaterialBlending && resolveVertexState.decalEncountered) { MemoryDecalMaterialInteraction memory; - memory.packed = decalMaterialTexture[resolveVertexState.pixelCoordinate]; - memory.emissiveRadiance = decalEmissiveRadianceTexture[resolveVertexState.pixelCoordinate].rgb; + memory.packed = decalMemory; + memory.emissiveRadiance = decalEmissiveRadiance; DecalMaterialInteraction decalMaterialInteraction = decalMaterialInteractionUnpack(memory); decalMaterialInteractionBlend(decalMaterialInteraction, opaqueSurfaceMaterialInteraction); @@ -404,28 +404,10 @@ void resolveVertex( resolveVertexState.decalEncountered = false; } + // must create this after decal has been composited to opaque surface material interaction polymorphicSurfaceMaterialInteraction = polymorphicSurfaceMaterialInteractionCreateInternal(opaqueSurfaceMaterialInteraction); - // If the current surface is a decal, store it and continue resolving - if (decalMaterialBlending && surfaceIsDecal(surface) && resolveVertexState.continueResolving) - { - if (opaqueSurfaceMaterialInteraction.opacity > 0.f) - { - const DecalMaterialInteraction decalMaterialInteraction = decalMaterialInteractionCreate(opaqueSurfaceMaterialInteraction); - - MemoryDecalMaterialInteraction memory = decalMaterialInteractionPack(decalMaterialInteraction); - decalMaterialTexture[resolveVertexState.pixelCoordinate] = memory.packed; - decalEmissiveRadianceTexture[resolveVertexState.pixelCoordinate] = f16vec4(memory.emissiveRadiance, 0); - - resolveVertexState.decalEncountered = true; - } - - resolveVertexFinalContinue(ray, surfaceInteraction, teleport, teleportMatrix, resolveVertexState); - - return; - } - // Note: Fully opaque surfaces have no chance at needing further resolving (since they are gauranteed to have no opacity-related blending or translucency), so stopping here is fine. // Todo: Incorporate decals into this check so this can be moved above the decal logic for early outing sooner on most hits? if (surface.isFullyOpaque) @@ -510,8 +492,8 @@ void resolveVertex( if (decalMaterialBlending && resolveVertexState.decalEncountered) { MemoryDecalMaterialInteraction memory; - memory.packed = decalMaterialTexture[resolveVertexState.pixelCoordinate]; - memory.emissiveRadiance = decalEmissiveRadianceTexture[resolveVertexState.pixelCoordinate].rgb; + memory.packed = decalMemory; + memory.emissiveRadiance = decalEmissiveRadiance; DecalMaterialInteraction decalMaterialInteraction = decalMaterialInteractionUnpack(memory); decalMaterialInteractionBlend(decalMaterialInteraction, translucentSurfaceMaterialInteraction); @@ -693,7 +675,10 @@ void resolveVertexUnordered( #endif float accumulatedHitDistance, inout f16vec3 radianceAttenuation, inout vec3 emissiveRadiance, - out uint numInteractions) + out uint numInteractions, + inout bool decalEncountered, + inout uint4 decalMemory, + inout f16vec3 decalEmissiveRadiance) { // Early out if approximations are not desired to be separated out @@ -737,6 +722,8 @@ void resolveVertexUnordered( ); f16vec4 binDistances = f16vec4(-1.0f, -1.0f, -1.0f, -1.0f); + uint8_t lastDecalSortKey = 0; + while (rayQuery.Proceed()) { RayHitInfo rayHitInfo; @@ -897,12 +884,63 @@ void resolveVertexUnordered( const OpaqueSurfaceMaterialInteraction opaqueSurfaceMaterialInteraction = opaqueSurfaceMaterialInteractionCreate(opaqueSurfaceMaterial, surface, surfaceInteraction, rayInteraction); - // Note: Return value ignored, should never return false in this path unless there is a bug. Additionally, incoming radiance attenuation - // set to 1.0 as attenuation will be manually added in later. - evaluateOpaqueApproximations( - resolveMode | resolveModeForceOpacityLightingApprox, - surface, surfaceInteraction, opaqueSurfaceMaterialInteraction, portalSpace, - f16vec3(1.0f), currentRadianceAttenuation, currentEmissiveRadiance); + if (isTriangle && surfaceIsDecal(surface)) + { + if (opaqueSurfaceMaterialInteraction.opacity > 0.f && rayInteraction.frontHit) + { + DecalMaterialInteraction decalMaterialInteraction = decalMaterialInteractionCreate(opaqueSurfaceMaterialInteraction); + + // If we have previously encountered a decal, must blend the new decal into our decal storage memory + if (decalEncountered) + { + MemoryDecalMaterialInteraction decalCompositedMemory; + decalCompositedMemory.packed = decalMemory; + decalCompositedMemory.emissiveRadiance = decalEmissiveRadiance; + + DecalMaterialInteraction decalMaterialInteractionComposited = decalMaterialInteractionUnpack(decalCompositedMemory); + + // Approximate decal sorting, accurate to 2 layers, semi-accurate thereafter. This works by maintaining a sort order (i.e. draw order) + // and switching between "over" or "under" blending based on the incoming sort key in relation to the previous. + if (lastDecalSortKey >= surface.decalSortOrder) + { + decalMaterialInteractionBlend(decalMaterialInteractionComposited, decalMaterialInteraction); + decalMaterialInteractionComposited = decalMaterialInteraction; + } + else + { + decalMaterialInteractionBlend(decalMaterialInteraction, decalMaterialInteractionComposited); + } + + MemoryDecalMaterialInteraction memory = decalMaterialInteractionPack(decalMaterialInteractionComposited); + decalMemory = memory.packed; + decalEmissiveRadiance = memory.emissiveRadiance; + } + else + { + MemoryDecalMaterialInteraction memory = decalMaterialInteractionPack(decalMaterialInteraction); + decalMemory = memory.packed; + decalEmissiveRadiance = memory.emissiveRadiance; + } + + lastDecalSortKey = surface.decalSortOrder; + decalEncountered = true; + } + + // account for these interactions for debug view + numInteractions += 1; + + // don't include decals in the opaque approximation. + continue; + } + else + { + // Note: Return value ignored, should never return false in this path unless there is a bug. Additionally, incoming radiance attenuation + // set to 1.0 as attenuation will be manually added in later. + evaluateOpaqueApproximations( + resolveMode | resolveModeForceOpacityLightingApprox, + surface, surfaceInteraction, opaqueSurfaceMaterialInteraction, portalSpace, + f16vec3(1.0f), currentRadianceAttenuation, currentEmissiveRadiance); + } } else if (polymorphicType == surfaceMaterialTypeTranslucent) { diff --git a/src/dxvk/shaders/rtx/concept/surface/surface.h b/src/dxvk/shaders/rtx/concept/surface/surface.h index 37af7ee4d..db16e5986 100644 --- a/src/dxvk/shaders/rtx/concept/surface/surface.h +++ b/src/dxvk/shaders/rtx/concept/surface/surface.h @@ -125,6 +125,8 @@ struct Surface uint8_t spriteSheetFPS; uint32_t objectPickingValue; + + uint8_t decalSortOrder; }; // Note: Minimal version of typical Surface Interaction for transmission across passes. diff --git a/src/dxvk/shaders/rtx/concept/surface/surface_create.slangh b/src/dxvk/shaders/rtx/concept/surface/surface_create.slangh index f1352e631..fae5626df 100644 --- a/src/dxvk/shaders/rtx/concept/surface/surface_create.slangh +++ b/src/dxvk/shaders/rtx/concept/surface/surface_create.slangh @@ -147,7 +147,7 @@ Surface surfaceCreate(MemorySurface memorySurface) surface.spriteSheetFPS = uint8_t((textureSpritesheetData >> 16) & 0xFF); // Note: 8 bits free here in the texture spritesheet data. - surface.objectPickingValue = memorySurface.data1.y; + surface.decalSortOrder = memorySurface.data15.x & 0xFF; return surface; } diff --git a/src/dxvk/shaders/rtx/concept/surface_material/decal_material_interaction.slangh b/src/dxvk/shaders/rtx/concept/surface_material/decal_material_interaction.slangh index 632070445..dd81fc3da 100644 --- a/src/dxvk/shaders/rtx/concept/surface_material/decal_material_interaction.slangh +++ b/src/dxvk/shaders/rtx/concept/surface_material/decal_material_interaction.slangh @@ -68,6 +68,37 @@ DecalMaterialInteraction decalMaterialInteractionCreate(OpaqueSurfaceMaterialInt return decalMaterialInteraction; } +void decalMaterialInteractionBlend( + DecalMaterialInteraction decalMaterialInteraction, + inout DecalMaterialInteraction decalMaterialInteractionOut) +{ + decalMaterialInteractionOut.shadingNormal = normalize(mix(decalMaterialInteractionOut.shadingNormal, + decalMaterialInteraction.shadingNormal, decalMaterialInteraction.opacity)); + + // Note: Treat albedo as if it is using premultiplied alpha as opacity is multiplied into it as part of the albedo derivation + // in the opaque material (see albedoToAdjustedAlbedo) which causes incorrect decal blending if not taken into account. + decalMaterialInteractionOut.albedo = + decalMaterialInteraction.albedo + decalMaterialInteractionOut.albedo * (1.0 - decalMaterialInteraction.opacity); + + // Note: Like albedo, treat base reflectivity as if it is using premultiplied alpha as opacity is also multiplied into it as part of + // the base reflectivity derivation in the opaque material (see calcBaseReflectivity) which causes incorrect decal blending if not taken into account. + decalMaterialInteractionOut.baseReflectivity = + decalMaterialInteraction.baseReflectivity + decalMaterialInteractionOut.baseReflectivity * (1.0 - decalMaterialInteraction.opacity); + + decalMaterialInteractionOut.roughness = mix(decalMaterialInteractionOut.roughness, + decalMaterialInteraction.roughness, decalMaterialInteraction.opacity); + + decalMaterialInteractionOut.anisotropy = mix(decalMaterialInteractionOut.anisotropy, + decalMaterialInteraction.anisotropy, decalMaterialInteraction.opacity); + + decalMaterialInteractionOut.emissiveRadiance = mix(decalMaterialInteractionOut.emissiveRadiance, + decalMaterialInteraction.emissiveRadiance, decalMaterialInteraction.opacity); + + // Note: Alpha compositing equation for alpha applied to opacity. + decalMaterialInteractionOut.opacity = + decalMaterialInteraction.opacity + decalMaterialInteractionOut.opacity * (1.0 - decalMaterialInteraction.opacity); +} + void decalMaterialInteractionBlend( DecalMaterialInteraction decalMaterialInteraction, inout OpaqueSurfaceMaterialInteraction opaqueSurfaceMaterialInteraction) diff --git a/src/dxvk/shaders/rtx/pass/gbuffer/gbuffer_binding_indices.h b/src/dxvk/shaders/rtx/pass/gbuffer/gbuffer_binding_indices.h index 17c8fbf2a..805ab124f 100644 --- a/src/dxvk/shaders/rtx/pass/gbuffer/gbuffer_binding_indices.h +++ b/src/dxvk/shaders/rtx/pass/gbuffer/gbuffer_binding_indices.h @@ -56,7 +56,6 @@ #define GBUFFER_BINDING_PRIMARY_HIT_DISTANCE_OUTPUT 58 #define GBUFFER_BINDING_PRIMARY_VIEW_DIRECTION_OUTPUT 59 #define GBUFFER_BINDING_PRIMARY_CONE_RADIUS_OUTPUT 60 -#define GBUFFER_BINDING_PRIMARY_WORLD_POSITION_OUTPUT 61 #define GBUFFER_BINDING_PRIMARY_POSITION_ERROR_OUTPUT 62 #define GBUFFER_BINDING_SECONDARY_ATTENUATION_OUTPUT 64 #define GBUFFER_BINDING_SECONDARY_WORLD_SHADING_NORMAL_OUTPUT 65 @@ -90,12 +89,10 @@ #define GBUFFER_BINDING_SHARED_SUBSURFACE_DATA_OUTPUT 91 #define GBUFFER_BINDING_ALIASED_DATA_0 92 -#define GBUFFER_BINDING_DECAL_MATERIAL_STORAGE (GBUFFER_BINDING_ALIASED_DATA_0 + 0) +#define GBUFFER_BINDING_PRIMARY_WORLD_POSITION_OUTPUT (GBUFFER_BINDING_ALIASED_DATA_0 + 0) #define GBUFFER_BINDING_REFLECTION_PSR_DATA_STORAGE_0 (GBUFFER_BINDING_ALIASED_DATA_0 + 1) -#define GBUFFER_BINDING_ALIASED_DATA_1 94 -#define GBUFFER_BINDING_DECAL_EMISSIVE_RADIANCE_STORAGE (GBUFFER_BINDING_ALIASED_DATA_1 + 0) -#define GBUFFER_BINDING_REFLECTION_PSR_DATA_STORAGE_1 (GBUFFER_BINDING_ALIASED_DATA_1 + 1) +#define GBUFFER_BINDING_REFLECTION_PSR_DATA_STORAGE_1 94 #define GBUFFER_BINDING_PRIMARY_OBJECT_PICKING_OUTPUT 96 diff --git a/src/dxvk/shaders/rtx/pass/gbuffer/gbuffer_bindings.slangh b/src/dxvk/shaders/rtx/pass/gbuffer/gbuffer_bindings.slangh index 1542f2f0a..737d11d65 100644 --- a/src/dxvk/shaders/rtx/pass/gbuffer/gbuffer_bindings.slangh +++ b/src/dxvk/shaders/rtx/pass/gbuffer/gbuffer_bindings.slangh @@ -107,9 +107,6 @@ RWTexture2D PrimaryViewDirection; layout(r16f, binding = GBUFFER_BINDING_PRIMARY_CONE_RADIUS_OUTPUT) RWTexture2D PrimaryConeRadius; -layout(rgba32f, binding = GBUFFER_BINDING_PRIMARY_WORLD_POSITION_OUTPUT) -RWTexture2D PrimaryWorldPositionWorldTriangleNormal; - layout(r32f, binding = GBUFFER_BINDING_PRIMARY_POSITION_ERROR_OUTPUT) RWTexture2D PrimaryPositionError; @@ -193,19 +190,15 @@ RWTexture2D SharedSubsurfaceData; layout(push_constant) ConstantBuffer push; -layout(rgba32ui, binding = GBUFFER_BINDING_ALIASED_DATA_0) +layout(rgba32f, binding = GBUFFER_BINDING_ALIASED_DATA_0) uniform struct AliasedData0 { - REORDER_COHERENT RWTexture2D DecalMaterial; // Internal storage - RWTexture2D ReflectionPSRData0; // Output/Input + RWTexture2D PrimaryWorldPositionWorldTriangleNormal; + RWTexture2D ReflectionPSRData0; // Output/Input } aliasedData0; -layout(rgba16f, binding = GBUFFER_BINDING_ALIASED_DATA_1) -uniform struct AliasedData1 -{ - REORDER_COHERENT RWTexture2D DecalEmissiveRadiance; // Internal storage - RWTexture2D ReflectionPSRData1; // Output/Input -} aliasedData1; +layout(rgba16f, binding = GBUFFER_BINDING_REFLECTION_PSR_DATA_STORAGE_1) +RWTexture2D ReflectionPSRData1; // Output/Input layout(rg32ui, binding = GBUFFER_BINDING_REFLECTION_PSR_DATA_STORAGE_2) RWTexture2D ReflectionPSRData2; diff --git a/src/dxvk/shaders/rtx/pass/integrate/integrate_indirect_binding_indices.h b/src/dxvk/shaders/rtx/pass/integrate/integrate_indirect_binding_indices.h index 6fc5c1257..9ad207fa1 100644 --- a/src/dxvk/shaders/rtx/pass/integrate/integrate_indirect_binding_indices.h +++ b/src/dxvk/shaders/rtx/pass/integrate/integrate_indirect_binding_indices.h @@ -58,10 +58,6 @@ #define INTEGRATE_INDIRECT_BINDING_GRADIENTS_INPUT 63 -// Storage - -#define INTEGRATE_INDIRECT_BINDING_DECAL_MATERIAL_STORAGE 64 - // Outputs #define INTEGRATE_INDIRECT_BINDING_RESTIR_GI_RESERVOIR_OUTPUT 70 @@ -73,8 +69,7 @@ #define INTEGRATE_INDIRECT_BINDING_ALIASED_DATA_0 90 #define INTEGRATE_INDIRECT_BINDING_THROUGHPUT_CONE_RADIUS_INPUT (INTEGRATE_INDIRECT_BINDING_ALIASED_DATA_0 + 0) -#define INTEGRATE_INDIRECT_BINDING_DECAL_EMISSIVE_RADIANCE_STORAGE (INTEGRATE_INDIRECT_BINDING_ALIASED_DATA_0 + 1) -#define INTEGRATE_INDIRECT_BINDING_INDIRECT_RADIANCE_HIT_DISTANCE_OUTPUT (INTEGRATE_INDIRECT_BINDING_ALIASED_DATA_0 + 2) +#define INTEGRATE_INDIRECT_BINDING_INDIRECT_RADIANCE_HIT_DISTANCE_OUTPUT (INTEGRATE_INDIRECT_BINDING_ALIASED_DATA_0 + 1) // Auxilary Inputs/Outputs diff --git a/src/dxvk/shaders/rtx/pass/integrate/integrate_indirect_bindings.slangh b/src/dxvk/shaders/rtx/pass/integrate/integrate_indirect_bindings.slangh index ff276d3b0..5e964707b 100644 --- a/src/dxvk/shaders/rtx/pass/integrate/integrate_indirect_bindings.slangh +++ b/src/dxvk/shaders/rtx/pass/integrate/integrate_indirect_bindings.slangh @@ -95,11 +95,6 @@ Texture2D FirstSampledLobeData; layout(rg16f, binding = INTEGRATE_INDIRECT_BINDING_GRADIENTS_INPUT) Texture2DArray RtxdiGradients; -// Storage - -layout(rgba32ui, binding = INTEGRATE_INDIRECT_BINDING_DECAL_MATERIAL_STORAGE) -REORDER_COHERENT RWTexture2D DecalMaterial; - // Outputs layout(binding = INTEGRATE_INDIRECT_BINDING_RESTIR_GI_RESERVOIR_OUTPUT) @@ -132,7 +127,6 @@ layout(rgba16f, binding = INTEGRATE_INDIRECT_BINDING_ALIASED_DATA_0) uniform struct AliasedData0 { Texture2D ThroughputConeRadius; // Input - REORDER_COHERENT RWTexture2D DecalEmissiveRadiance; // Intermediate storage // Indirect radiance and hit distance output for an active target driven by GeometryFlags for a given pixel. // It contains data for either {Primary / Secondary Surface, Diffuse / Specular Lobe} diff --git a/src/dxvk/shaders/rtx/utility/debug_view_indices.h b/src/dxvk/shaders/rtx/utility/debug_view_indices.h index 60262ee46..de71f8e3a 100644 --- a/src/dxvk/shaders/rtx/utility/debug_view_indices.h +++ b/src/dxvk/shaders/rtx/utility/debug_view_indices.h @@ -88,6 +88,8 @@ #define DEBUG_VIEW_PSR_PRIMARY_SECONDARY_SURFACE_MASK 80 #define DEBUG_VIEW_PSR_SELECTED_INTEGRATION_SURFACE_PDF 81 +#define DEBUG_VIEW_PRIMARY_DECAL_ALBEDO 88 + #define DEBUG_VIEW_PRIMARY_SPECULAR_ALBEDO 90 #define DEBUG_VIEW_SECONDARY_SPECULAR_ALBEDO 91