@@ -482,6 +482,7 @@ namespace dxvk {
482
482
}
483
483
484
484
m_activePOMCount = 0 ;
485
+ m_startInMediumMaterialIndex = BINDING_INDEX_INVALID;
485
486
486
487
if (m_uniqueObjectSearchDistance != RtxOptions::uniqueObjectDistance ()) {
487
488
m_uniqueObjectSearchDistance = RtxOptions::uniqueObjectDistance ();
@@ -503,8 +504,29 @@ namespace dxvk {
503
504
return ;
504
505
}
505
506
506
- if (m_fog.mode == D3DFOG_NONE && input.getFogState ().mode != D3DFOG_NONE) {
507
- m_fog = input.getFogState ();
507
+ if (input.getFogState ().mode != D3DFOG_NONE) {
508
+ XXH64_hash_t fogHash = input.getFogState ().getHash ();
509
+ if (m_fogStates.find (fogHash) == m_fogStates.end ()) {
510
+ // Only do anything if we haven't seen this fog before.
511
+ m_fogStates[fogHash] = input.getFogState ();
512
+
513
+ MaterialData* pFogReplacement = m_pReplacer->getReplacementMaterial (fogHash);
514
+ if (pFogReplacement) {
515
+ // Fog has been replaced by a translucent material to start the camera in,
516
+ // meaning that it was being used to indicate 'underwater' or something similar.
517
+ if (pFogReplacement->getType () != MaterialDataType::Translucent) {
518
+ Logger::warn (str::format (" Fog replacement materials must be translucent. Ignoring material for " , std::hex, m_fog.getHash ()));
519
+ } else {
520
+ std::optional<RtSurfaceMaterial> surfaceMaterial {};
521
+
522
+ createSurfaceMaterial (ctx, surfaceMaterial, *pFogReplacement, input);
523
+ m_startInMediumMaterialIndex = m_surfaceMaterialCache.track (*surfaceMaterial);
524
+ }
525
+ } else if (m_fog.mode == D3DFOG_NONE) {
526
+ // render the first unreplaced fog.
527
+ m_fog = input.getFogState ();
528
+ }
529
+ }
508
530
}
509
531
510
532
// Get Material and Mesh replacements
@@ -718,7 +740,9 @@ namespace dxvk {
718
740
}
719
741
720
742
void SceneManager::clearFogState () {
743
+ ImGUI::SetFogStates (m_fogStates, m_fog.getHash ());
721
744
m_fog = FogState ();
745
+ m_fogStates.clear ();
722
746
}
723
747
724
748
void SceneManager::updateBufferCache (RaytraceGeometry& newGeoData) {
@@ -879,18 +903,67 @@ namespace dxvk {
879
903
const auto renderMaterialDataType = renderMaterialData.getType ();
880
904
std::optional<RtSurfaceMaterial> surfaceMaterial{};
881
905
906
+ createSurfaceMaterial (ctx, surfaceMaterial, renderMaterialData, drawCallState);
907
+
908
+ assert (surfaceMaterial.has_value ());
909
+ assert (surfaceMaterial->validate ());
910
+
911
+ // Cache this
912
+ m_surfaceMaterialCache.track (*surfaceMaterial);
913
+
914
+ RtInstance* instance = m_instanceManager.processSceneObject (m_cameraManager, m_rayPortalManager, *pBlas, drawCallState, renderMaterialData, *surfaceMaterial);
915
+
916
+ // Check if a light should be created for this Material
917
+ if (instance && RtxOptions::Get ()->shouldConvertToLight (drawCallState.getMaterialData ().getHash ())) {
918
+ createEffectLight (ctx, drawCallState, instance);
919
+ }
920
+
921
+ const bool objectPickingActive = m_device->getCommon ()->getResources ().getRaytracingOutput ()
922
+ .m_primaryObjectPicking .isValid ();
923
+
924
+ if (objectPickingActive && instance && g_allowMappingLegacyHashToObjectPickingValue) {
925
+ auto meta = DrawCallMetaInfo {};
926
+ {
927
+ XXH64_hash_t h;
928
+ h = drawCallState.getMaterialData ().getColorTexture ().getImageHash ();
929
+ if (h != kEmptyHash ) {
930
+ meta.legacyTextureHash = h;
931
+ }
932
+ h = drawCallState.getMaterialData ().getColorTexture2 ().getImageHash ();
933
+ if (h != kEmptyHash ) {
934
+ meta.legacyTextureHash2 = h;
935
+ }
936
+ }
937
+
938
+ {
939
+ std::lock_guard lock { m_drawCallMeta.mutex };
940
+ auto [iter, isNew] = m_drawCallMeta.infos [m_drawCallMeta.ticker ].emplace (instance->surface .objectPickingValue , meta);
941
+ ONCE_IF_FALSE (isNew, Logger::warn (
942
+ " Found multiple draw calls with the same \' objectPickingValue\' . "
943
+ " Ignoring further MetaInfo-s, some objects might be not be available through object picking" ));
944
+ }
945
+ }
946
+
947
+ return instance ? instance->getId () : UINT64_MAX;
948
+ }
949
+
950
+ void SceneManager::createSurfaceMaterial ( Rc<DxvkContext> ctx,
951
+ std::optional<RtSurfaceMaterial>& surfaceMaterial,
952
+ const MaterialData& renderMaterialData,
953
+ const DrawCallState& drawCallState) {
954
+ ScopedCpuProfileZone ();
882
955
const bool hasTexcoords = drawCallState.hasTextureCoordinates ();
956
+ const auto renderMaterialDataType = renderMaterialData.getType ();
883
957
884
958
// We're going to use this to create a modified sampler for replacement textures.
885
959
// Legacy and replacement materials should follow same filtering but due to lack of override capability per texture
886
960
// legacy textures use original sampler to stay true to the original intent while replacements use more advanced filtering
887
961
// for better quality by default.
888
962
const Rc<DxvkSampler>& originalSampler = drawCallState.getMaterialData ().getSampler (); // convenience variable for debug
889
963
Rc<DxvkSampler> sampler = originalSampler;
890
- const bool isLegacyMaterial = (renderMaterialDataType == MaterialDataType::Legacy);
891
964
// If the original sampler if valid and the new rendering material is not legacy type
892
965
// go ahead with patching and maybe merging the sampler states
893
- if (originalSampler != nullptr && !isLegacyMaterial ) {
966
+ if (originalSampler != nullptr && renderMaterialDataType != MaterialDataType::Legacy ) {
894
967
DxvkSamplerCreateInfo samplerInfo = originalSampler->info (); // Use sampler create info struct as convenience
895
968
renderMaterialData.populateSamplerInfo (samplerInfo);
896
969
@@ -900,7 +973,7 @@ namespace dxvk {
900
973
}
901
974
uint32_t samplerIndex = trackSampler (sampler);
902
975
903
- if (isLegacyMaterial || renderMaterialDataType == MaterialDataType::Opaque || drawCallState.isUsingRaytracedRenderTarget ) {
976
+ if (renderMaterialDataType == MaterialDataType::Legacy || renderMaterialDataType == MaterialDataType::Opaque || drawCallState.isUsingRaytracedRenderTarget ) {
904
977
uint32_t albedoOpacityTextureIndex = kSurfaceMaterialInvalidTextureIndex ;
905
978
uint32_t normalTextureIndex = kSurfaceMaterialInvalidTextureIndex ;
906
979
uint32_t tangentTextureIndex = kSurfaceMaterialInvalidTextureIndex ;
@@ -1109,46 +1182,6 @@ namespace dxvk {
1109
1182
1110
1183
surfaceMaterial.emplace (rayPortalSurfaceMaterial);
1111
1184
}
1112
- assert (surfaceMaterial.has_value ());
1113
- assert (surfaceMaterial->validate ());
1114
-
1115
- // Cache this
1116
- m_surfaceMaterialCache.track (*surfaceMaterial);
1117
-
1118
- RtInstance* instance = m_instanceManager.processSceneObject (m_cameraManager, m_rayPortalManager, *pBlas, drawCallState, renderMaterialData, *surfaceMaterial);
1119
-
1120
- // Check if a light should be created for this Material
1121
- if (instance && RtxOptions::Get ()->shouldConvertToLight (drawCallState.getMaterialData ().getHash ())) {
1122
- createEffectLight (ctx, drawCallState, instance);
1123
- }
1124
-
1125
- const bool objectPickingActive = m_device->getCommon ()->getResources ().getRaytracingOutput ()
1126
- .m_primaryObjectPicking .isValid ();
1127
-
1128
- if (objectPickingActive && instance && g_allowMappingLegacyHashToObjectPickingValue) {
1129
- auto meta = DrawCallMetaInfo {};
1130
- {
1131
- XXH64_hash_t h;
1132
- h = drawCallState.getMaterialData ().getColorTexture ().getImageHash ();
1133
- if (h != kEmptyHash ) {
1134
- meta.legacyTextureHash = h;
1135
- }
1136
- h = drawCallState.getMaterialData ().getColorTexture2 ().getImageHash ();
1137
- if (h != kEmptyHash ) {
1138
- meta.legacyTextureHash2 = h;
1139
- }
1140
- }
1141
-
1142
- {
1143
- std::lock_guard lock { m_drawCallMeta.mutex };
1144
- auto [iter, isNew] = m_drawCallMeta.infos [m_drawCallMeta.ticker ].emplace (instance->surface .objectPickingValue , meta);
1145
- ONCE_IF_FALSE (isNew, Logger::warn (
1146
- " Found multiple draw calls with the same \' objectPickingValue\' . "
1147
- " Ignoring further MetaInfo-s, some objects might be not be available through object picking" ));
1148
- }
1149
- }
1150
-
1151
- return instance ? instance->getId () : UINT64_MAX;
1152
1185
}
1153
1186
1154
1187
std::optional<XXH64_hash_t> SceneManager::findLegacyTextureHashByObjectPickingValue (uint32_t objectPickingValue) {
@@ -1377,7 +1410,10 @@ namespace dxvk {
1377
1410
if (m_surfaceMaterialCache.getTotalCount () > 0 ) {
1378
1411
ScopedGpuProfileZone (ctx, " updateSurfaceMaterials" );
1379
1412
// Note: We duplicate the materials in the buffer so we don't have to do pointer chasing on the GPU (i.e. rather than BLAS->Surface->Material, do, BLAS->Surface, BLAS->Material)
1380
- const auto surfaceMaterialsGPUSize = m_accelManager.getSurfaceCount () * kSurfaceMaterialGPUSize ;
1413
+ size_t surfaceMaterialsGPUSize = m_accelManager.getSurfaceCount () * kSurfaceMaterialGPUSize ;
1414
+ if (m_startInMediumMaterialIndex != BINDING_INDEX_INVALID) {
1415
+ surfaceMaterialsGPUSize += kSurfaceMaterialGPUSize ;
1416
+ }
1381
1417
1382
1418
info.size = align (surfaceMaterialsGPUSize, kBufferAlignment );
1383
1419
info.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
@@ -1394,6 +1430,13 @@ namespace dxvk {
1394
1430
surfaceIndex++;
1395
1431
}
1396
1432
1433
+ if (m_startInMediumMaterialIndex != BINDING_INDEX_INVALID) {
1434
+ auto && surfaceMaterial = m_surfaceMaterialCache.getObjectTable ()[m_startInMediumMaterialIndex];
1435
+ surfaceMaterial.writeGPUData (surfaceMaterialsGPUData.data (), dataOffset, surfaceIndex);
1436
+ m_startInMediumMaterialIndex = surfaceIndex;
1437
+ surfaceIndex++;
1438
+ }
1439
+
1397
1440
assert (dataOffset == surfaceMaterialsGPUSize);
1398
1441
assert (surfaceMaterialsGPUData.size () == surfaceMaterialsGPUSize);
1399
1442
0 commit comments