diff --git a/packman-external.xml b/packman-external.xml
index 4e5106a12..bc9e7caea 100644
--- a/packman-external.xml
+++ b/packman-external.xml
@@ -20,7 +20,7 @@
-
+
diff --git a/src/d3d9/d3d9_rtx.cpp b/src/d3d9/d3d9_rtx.cpp
index 1e22dd45b..6b3a29239 100644
--- a/src/d3d9/d3d9_rtx.cpp
+++ b/src/d3d9/d3d9_rtx.cpp
@@ -515,14 +515,10 @@ namespace dxvk {
}
if (triggerRtxInjection) {
- const auto currentReflexFrameId = GetReflexFrameId();
-
+ // Bind all resources required for this drawcall to context first (i.e. render targets)
m_parent->PrepareDraw(drawContext.PrimitiveType);
- m_parent->EmitCs([currentReflexFrameId](DxvkContext* ctx) {
- static_cast(ctx)->injectRTX(currentReflexFrameId);
- });
- m_parent->FlushCsChunk();
+ triggerInjectRTX();
m_rtxInjectTriggered = true;
return { true, false };
@@ -643,6 +639,16 @@ namespace dxvk {
return { preserveOriginalDraw, true };
}
+ void D3D9Rtx::triggerInjectRTX() {
+ // Flush any pending game and RTX work
+ m_parent->Flush();
+
+ // Send command to inject RTX
+ m_parent->EmitCs([cReflexFrameId = GetReflexFrameId()](DxvkContext* ctx) {
+ static_cast(ctx)->injectRTX(cReflexFrameId);
+ });
+ }
+
void D3D9Rtx::CommitGeometryToRT(const DrawContext& drawContext) {
ScopedCpuProfileZone();
auto drawInfo = m_parent->GenerateDrawInfo(drawContext.PrimitiveType, drawContext.PrimitiveCount, m_parent->GetInstanceCount());
diff --git a/src/d3d9/d3d9_rtx.h b/src/d3d9/d3d9_rtx.h
index c44106c7e..fc23a121b 100644
--- a/src/d3d9/d3d9_rtx.h
+++ b/src/d3d9/d3d9_rtx.h
@@ -244,7 +244,10 @@ namespace dxvk {
bool processTextures();
PrepareDrawType internalPrepareDraw(const IndexContext& indexContext, const VertexContext vertexContext[caps::MaxStreams], const DrawContext& drawContext);
-
+
+ void triggerInjectRTX();
+
+
struct DrawCallType {
RtxGeometryStatus status;
bool triggerRtxInjection;
diff --git a/src/dxvk/rtx_render/rtx_asset_data_manager.cpp b/src/dxvk/rtx_render/rtx_asset_data_manager.cpp
index 6fb51fc43..ad4902ba3 100644
--- a/src/dxvk/rtx_render/rtx_asset_data_manager.cpp
+++ b/src/dxvk/rtx_render/rtx_asset_data_manager.cpp
@@ -531,10 +531,11 @@ namespace dxvk {
const bool isSupported = isDDS;
if (!isSupported) {
+ const char* message = "Unsupported image file format, use the RTX-Remix toolkit and ingest the following asset: ";
if (RtxOptions::Automation::suppressAssetLoadingErrors()) {
- Logger::warn(str::format("Unsupported image file format, please convert to DDS using Remix Export: ", filename));
+ Logger::warn(str::format(message, filename));
} else {
- Logger::err(str::format("Unsupported image file format, please convert to DDS using Remix Export: ", filename));
+ Logger::err(str::format(message, filename));
}
return nullptr;
}
diff --git a/src/dxvk/rtx_render/rtx_bindless_resource_manager.cpp b/src/dxvk/rtx_render/rtx_bindless_resource_manager.cpp
index ea2f6475f..67aa8077a 100644
--- a/src/dxvk/rtx_render/rtx_bindless_resource_manager.cpp
+++ b/src/dxvk/rtx_render/rtx_bindless_resource_manager.cpp
@@ -54,121 +54,86 @@ namespace dxvk {
return m_tables[type][currentIdx()]->bindlessDescSet;
}
- void BindlessResourceManager::prepareSceneData(const Rc ctx, const std::vector& rtTextures, const std::vector& rtBuffers, const std::vector>& samplers) {
- ScopedCpuProfileZone();
- if (m_frameLastUpdated == m_device->getCurrentFrameId()) {
- Logger::debug("Updating bindless tables multiple times per frame...");
- return;
- }
-
- // Increment
- m_globalBindlessDescSetIdx = nextIdx();
+ template
+ void BindlessResourceManager::createDescriptorSet(const Rc& ctx, const std::vector& engineObjects, const T& dummyDescriptor) {
+ const size_t numDescriptors = std::max((size_t) 1, engineObjects.size()); // Must always leave 1 to have a valid binding set
+ assert(numDescriptors <= kMaxBindlessResources);
- // Textures
- {
- std::vector imageInfo(rtTextures.size());
+ std::vector descriptorInfos(numDescriptors);
+ descriptorInfos[0] = dummyDescriptor; // we set the first descriptor to be a dummy (size is always at least 1) and overwrite it if there are valid engine objects
- uint32_t idx = 0;
- for (auto&& texRef : rtTextures) {
- DxvkImageView* imageView = texRef.getImageView();
+ uint32_t idx = 0;
+ for (auto&& engineObject : engineObjects) {
+ descriptorInfos[idx] = dummyDescriptor;
+ if constexpr (Type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) {
+ DxvkImageView* imageView = engineObject.getImageView();
if (imageView != nullptr) {
- imageInfo[idx].sampler = nullptr;
- imageInfo[idx].imageView = imageView->handle();
- imageInfo[idx].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ descriptorInfos[idx].sampler = nullptr;
+ descriptorInfos[idx].imageView = imageView->handle();
+ descriptorInfos[idx].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
ctx->getCommandList()->trackResource(imageView);
- } else {
- imageInfo[idx] = m_device->getCommon()->dummyResources().imageViewDescriptor(VK_IMAGE_VIEW_TYPE_2D, true);
}
-
- ++idx;
+ } else if constexpr (Type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) {
+ if (engineObject.defined()) {
+ descriptorInfos[idx] = engineObject.getDescriptor().buffer;
+ ctx->getCommandList()->trackResource(engineObject.buffer());
+ }
+ } else if constexpr (Type == VK_DESCRIPTOR_TYPE_SAMPLER) {
+ if (engineObject != nullptr) {
+ descriptorInfos[idx].sampler = engineObject->handle();
+ descriptorInfos[idx].imageView = nullptr;
+ }
+ } else {
+ static_assert(Type != VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || Type != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER || Type != VK_DESCRIPTOR_TYPE_SAMPLER, "Support for this descriptor type has not been implemented yet.");
+ return;
}
- assert(idx <= kMaxBindlessResources);
-
- if (idx > 0) {
- VkWriteDescriptorSet descWrites;
- descWrites.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- descWrites.pNext = nullptr;
- descWrites.dstSet = 0;// This will be filled in by the BindlessTable
- descWrites.dstBinding = 0;
- descWrites.dstArrayElement = 0;
- descWrites.descriptorCount = idx;
- descWrites.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
- descWrites.pImageInfo = &imageInfo[0];
- descWrites.pBufferInfo = nullptr;
- descWrites.pTexelBufferView = nullptr;
- m_tables[Table::Textures][currentIdx()]->updateDescriptors(descWrites);
- }
+ ++idx;
}
- // Buffers
- {
- uint32_t idx = 0;
- std::vector bufferInfo(rtBuffers.size());
- for (auto&& bufRef : rtBuffers) {
- if (bufRef.defined()) {
- bufferInfo[idx] = bufRef.getDescriptor().buffer;
- ctx->getCommandList()->trackResource(bufRef.buffer());
- } else {
- bufferInfo[idx] = m_device->getCommon()->dummyResources().bufferDescriptor();
- }
+ VkWriteDescriptorSet descWrites;
+ memset(&descWrites, 0, sizeof(descWrites));
+ descWrites.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrites.descriptorCount = numDescriptors;
+ descWrites.descriptorType = Type;
- ++idx;
- }
+ if constexpr (std::is_same_v) {
+ descWrites.pImageInfo = &descriptorInfos[0];
+ } else if constexpr (std::is_same_v) {
+ descWrites.pBufferInfo = &descriptorInfos[0];
+ }
- assert(idx <= kMaxBindlessResources);
-
- if (idx > 0) {
- VkWriteDescriptorSet descWrites;
- descWrites.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- descWrites.pNext = nullptr;
- descWrites.dstSet = 0;// This will be filled in by the BindlessTable
- descWrites.dstBinding = 0;
- descWrites.dstArrayElement = 0;
- descWrites.descriptorCount = idx;
- descWrites.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- descWrites.pImageInfo = nullptr;
- descWrites.pBufferInfo = &bufferInfo[0];
- descWrites.pTexelBufferView = nullptr;
- m_tables[Table::Buffers][currentIdx()]->updateDescriptors(descWrites);
- }
+ switch (Type) {
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ m_tables[Table::Textures][currentIdx()]->updateDescriptors(descWrites);
+ break;
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ m_tables[Table::Buffers][currentIdx()]->updateDescriptors(descWrites);
+ break;
+ case VK_DESCRIPTOR_TYPE_SAMPLER:
+ m_tables[Table::Samplers][currentIdx()]->updateDescriptors(descWrites);
+ break;
}
+ }
- // Samplers
- {
- std::vector imageInfo(samplers.size());
-
- uint32_t idx = 0;
- for (auto&& sampler : samplers) {
- if (sampler != nullptr) {
- imageInfo[idx].sampler = sampler->handle();
- imageInfo[idx].imageView = nullptr;
- ctx->getCommandList()->trackResource(sampler);
- } else {
- imageInfo[idx] = m_device->getCommon()->dummyResources().samplerDescriptor();
- }
+ void BindlessResourceManager::prepareSceneData(const Rc ctx, const std::vector& rtTextures, const std::vector& rtBuffers, const std::vector>& samplers) {
+ ScopedCpuProfileZone();
+ if (m_frameLastUpdated == m_device->getCurrentFrameId()) {
+ Logger::debug("Updating bindless tables multiple times per frame...");
+ return;
+ }
- ++idx;
- }
+ // Increment
+ m_globalBindlessDescSetIdx = nextIdx();
- assert(idx <= kMaxBindlessSamplers);
-
- if (idx > 0) {
- VkWriteDescriptorSet descWrites;
- descWrites.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- descWrites.pNext = nullptr;
- descWrites.dstSet = 0;// This will be filled in by the BindlessTable
- descWrites.dstBinding = 0;
- descWrites.dstArrayElement = 0;
- descWrites.descriptorCount = idx;
- descWrites.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
- descWrites.pImageInfo = &imageInfo[0];
- descWrites.pBufferInfo = nullptr;
- descWrites.pTexelBufferView = nullptr;
- m_tables[Table::Samplers][currentIdx()]->updateDescriptors(descWrites);
- }
- }
+ const VkDescriptorImageInfo dummyImage = m_device->getCommon()->dummyResources().imageViewDescriptor(VK_IMAGE_VIEW_TYPE_2D, true);
+ const VkDescriptorBufferInfo dummyBuffer = m_device->getCommon()->dummyResources().bufferDescriptor();
+ const VkDescriptorImageInfo dummySampler = m_device->getCommon()->dummyResources().samplerDescriptor();
+
+ createDescriptorSet(ctx, rtTextures, dummyImage);
+ createDescriptorSet(ctx, rtBuffers, dummyBuffer);
+ createDescriptorSet(ctx, samplers, dummySampler);
m_frameLastUpdated = m_device->getCurrentFrameId();
}
@@ -212,7 +177,7 @@ namespace dxvk {
throw DxvkError("BindlessTable: Failed to create descriptor set layout");
}
- void BindlessResourceManager::BindlessTable::updateDescriptors(VkWriteDescriptorSet& set) {
+ void BindlessResourceManager::BindlessTable::updateDescriptors(VkWriteDescriptorSet set) {
if (bindlessDescSet == nullptr) {
// Allocate the descriptor set
bindlessDescSet = m_pManager->m_globalBindlessPool[m_pManager->currentIdx()]->alloc(layout, "bindless descriptor set");
diff --git a/src/dxvk/rtx_render/rtx_bindless_resource_manager.h b/src/dxvk/rtx_render/rtx_bindless_resource_manager.h
index d7d59bf4d..4f1e40588 100644
--- a/src/dxvk/rtx_render/rtx_bindless_resource_manager.h
+++ b/src/dxvk/rtx_render/rtx_bindless_resource_manager.h
@@ -66,7 +66,7 @@ namespace dxvk {
VkDescriptorSet bindlessDescSet = VK_NULL_HANDLE;
void createLayout(const VkDescriptorType type);
- void updateDescriptors(VkWriteDescriptorSet& set);
+ void updateDescriptors(VkWriteDescriptorSet set);
private:
const Rc vkd() const;
@@ -92,5 +92,8 @@ namespace dxvk {
}
void createGlobalBindlessDescPool();
+
+ template
+ void createDescriptorSet(const Rc& ctx, const std::vector& engineObjects, const T& dummyDescriptor);
};
} // namespace dxvk
\ No newline at end of file
diff --git a/src/dxvk/rtx_render/rtx_context.cpp b/src/dxvk/rtx_render/rtx_context.cpp
index 02e34a973..25c7a23dd 100644
--- a/src/dxvk/rtx_render/rtx_context.cpp
+++ b/src/dxvk/rtx_render/rtx_context.cpp
@@ -347,8 +347,6 @@ namespace dxvk {
m_execBarriers.recordCommands(m_cmd);
- flushCommandList();
-
ScopedGpuProfileZone(this, "InjectRTX");
// Signal Reflex rendering start
diff --git a/src/dxvk/rtx_render/rtx_geometry_utils.cpp b/src/dxvk/rtx_render/rtx_geometry_utils.cpp
index a00c3b1ce..5bdf726be 100644
--- a/src/dxvk/rtx_render/rtx_geometry_utils.cpp
+++ b/src/dxvk/rtx_render/rtx_geometry_utils.cpp
@@ -157,8 +157,8 @@ namespace dxvk {
}
void RtxGeometryUtils::dispatchSkinning(const DrawCallState& drawCallState,
- const RaytraceGeometry& geo) const {
- const Rc ctx = m_skinningContext;
+ const RaytraceGeometry& geo) {
+ const Rc& ctx = m_skinningContext;
// Create command list for the initial skinning dispatch (e.g. The first frame we get skinning mesh draw calls)
if (ctx->getCommandList() == nullptr) {
ctx->beginRecording(ctx->getDevice()->createCommandList());
@@ -210,7 +210,7 @@ namespace dxvk {
DxvkBufferSlice cb = m_pCbData->alloc(alignment, sizeof(SkinningArgs));
memcpy(cb.mapPtr(0), ¶ms, sizeof(SkinningArgs));
- m_skinningContext->getCommandList()->trackResource(cb.buffer());
+ ctx->getCommandList()->trackResource(cb.buffer());
ctx->bindResourceBuffer(BINDING_SKINNING_CONSTANTS, cb);
ctx->bindResourceBuffer(BINDING_POSITION_OUTPUT, geo.positionBuffer);
@@ -226,7 +226,7 @@ namespace dxvk {
const VkExtent3D workgroups = util::computeBlockCount(VkExtent3D { params.numVertices, 1, 1 }, VkExtent3D { 128, 1, 1 });
ctx->dispatch(workgroups.width, workgroups.height, workgroups.depth);
- m_skinningContext->getCommandList()->trackResource(cb.buffer());
+ ctx->getCommandList()->trackResource(cb.buffer());
} else {
const float* srcPosition = reinterpret_cast(drawCallState.getGeometryData().positionBuffer.mapPtr(0));
const float* srcNormal = reinterpret_cast(drawCallState.getGeometryData().normalBuffer.mapPtr(0));
@@ -249,6 +249,7 @@ namespace dxvk {
ctx->writeToBuffer(geo.normalBuffer.buffer(), geo.normalBuffer.offsetFromSlice() + idx * geo.normalBuffer.stride(), sizeof(dstNormal), &dstNormal[0], true);
}
}
+ ++m_skinningCommands;
}
void RtxGeometryUtils::dispatchViewModelCorrection(
diff --git a/src/dxvk/rtx_render/rtx_geometry_utils.h b/src/dxvk/rtx_render/rtx_geometry_utils.h
index 711dd180e..36f5f5aa7 100644
--- a/src/dxvk/rtx_render/rtx_geometry_utils.h
+++ b/src/dxvk/rtx_render/rtx_geometry_utils.h
@@ -48,6 +48,7 @@ namespace dxvk {
class RtxGeometryUtils : public CommonDeviceObject {
std::unique_ptr m_pCbData;
Rc m_skinningContext;
+ uint32_t m_skinningCommands = 0;
public:
explicit RtxGeometryUtils(DxvkDevice* pDevice);
@@ -68,7 +69,7 @@ namespace dxvk {
/**
* \brief Execute a compute shader to perform skinning
*/
- void dispatchSkinning(const DrawCallState& drawCallState, const RaytraceGeometry& geo) const;
+ void dispatchSkinning(const DrawCallState& drawCallState, const RaytraceGeometry& geo);
/**
* \brief Execute a compute shader to perform view model perspective correction
@@ -170,7 +171,7 @@ namespace dxvk {
InterleavedGeometryDescriptor& output) const;
inline void flushCommandList() {
- if (m_skinningContext->getCommandList() != nullptr) {
+ if (m_skinningContext->getCommandList() != nullptr && m_skinningCommands > 0) {
m_skinningContext->flushCommandList();
}
}
diff --git a/src/dxvk/rtx_render/rtx_material_data.h b/src/dxvk/rtx_render/rtx_material_data.h
index 18b575a3b..9de0db78d 100644
--- a/src/dxvk/rtx_render/rtx_material_data.h
+++ b/src/dxvk/rtx_render/rtx_material_data.h
@@ -79,7 +79,7 @@
X(SubsurfaceSingleScatteringAlbedo, subsurface_single_scattering_albedo, Vector3, Vector3(0.f), Vector3(1.f), Vector3(0.5f, 0.5f, 0.5f)) \
X(SubsurfaceVolumetricAnisotropy, subsurface_volumetric_anisotropy, float, -1.f, 1.f, 0.f) \
/* Sampler State */ \
- X(FilterMode, filter_mode, uint8_t, lss::Mdl::Filter::Nearest, lss::Mdl::Filter::Linear, lss::Mdl::Filter::Nearest) \
+ X(FilterMode, filter_mode, uint8_t, lss::Mdl::Filter::Nearest, lss::Mdl::Filter::Linear, lss::Mdl::Filter::Linear) \
X(WrapModeU, wrap_mode_u, uint8_t, lss::Mdl::WrapMode::Clamp, lss::Mdl::WrapMode::Clip, lss::Mdl::WrapMode::Repeat) \
X(WrapModeV, wrap_mode_v, uint8_t, lss::Mdl::WrapMode::Clamp, lss::Mdl::WrapMode::Clip, lss::Mdl::WrapMode::Repeat)
@@ -116,7 +116,7 @@
X(ThinWallThickness, thin_wall_thickness, float, .001f, 65504.0f, .001f) \
X(EnableDiffuseLayer, use_diffuse_layer, bool, false, true, false) \
/* Sampler State */ \
- X(FilterMode, filter_mode, uint8_t, lss::Mdl::Filter::Nearest, lss::Mdl::Filter::Linear, lss::Mdl::Filter::Nearest) \
+ X(FilterMode, filter_mode, uint8_t, lss::Mdl::Filter::Nearest, lss::Mdl::Filter::Linear, lss::Mdl::Filter::Linear) \
X(WrapModeU, wrap_mode_u, uint8_t, lss::Mdl::WrapMode::Clamp, lss::Mdl::WrapMode::Clip, lss::Mdl::WrapMode::Repeat) \
X(WrapModeV, wrap_mode_v, uint8_t, lss::Mdl::WrapMode::Clamp, lss::Mdl::WrapMode::Clip, lss::Mdl::WrapMode::Repeat)
@@ -140,7 +140,7 @@
X(EnableEmission, enable_emission, bool, false, true, false) \
X(EmissiveIntensity, emissive_intensity, float, 0.f, 65504.0f, 40.f) \
/* Sampler State */ \
- X(FilterMode, filter_mode, uint8_t, lss::Mdl::Filter::Nearest, lss::Mdl::Filter::Linear, lss::Mdl::Filter::Nearest) \
+ X(FilterMode, filter_mode, uint8_t, lss::Mdl::Filter::Nearest, lss::Mdl::Filter::Linear, lss::Mdl::Filter::Linear) \
X(WrapModeU, wrap_mode_u, uint8_t, lss::Mdl::WrapMode::Clamp, lss::Mdl::WrapMode::Clip, lss::Mdl::WrapMode::Repeat) \
X(WrapModeV, wrap_mode_v, uint8_t, lss::Mdl::WrapMode::Clamp, lss::Mdl::WrapMode::Clip, lss::Mdl::WrapMode::Repeat)
diff --git a/src/dxvk/rtx_render/rtx_materials.h b/src/dxvk/rtx_render/rtx_materials.h
index 912f4021b..9197c1a8c 100644
--- a/src/dxvk/rtx_render/rtx_materials.h
+++ b/src/dxvk/rtx_render/rtx_materials.h
@@ -1677,14 +1677,6 @@ struct MaterialData {
}
#undef P_SAMPLER_INFO
- void setReplacement() {
- m_isReplacement = true;
- }
-
- bool isReplacement() const {
- return m_isReplacement;
- }
-
private:
// Type-specific Material Data Information
bool m_ignored = false;
@@ -1696,8 +1688,6 @@ struct MaterialData {
TranslucentMaterialData m_translucentMaterialData;
RayPortalMaterialData m_rayPortalMaterialData;
};
-
- bool m_isReplacement = false;
};
enum class HighlightColor {
diff --git a/src/dxvk/rtx_render/rtx_scene_manager.cpp b/src/dxvk/rtx_render/rtx_scene_manager.cpp
index 799a3de85..8daf6a7cc 100644
--- a/src/dxvk/rtx_render/rtx_scene_manager.cpp
+++ b/src/dxvk/rtx_render/rtx_scene_manager.cpp
@@ -476,8 +476,6 @@ namespace dxvk {
replacementMaterial.emplace(MaterialData(*pReplacementMaterial));
// merge in the input material from game
replacementMaterial->mergeLegacyMaterial(input.getMaterialData());
- // mark material as replacement so we know how to handle sampler state
- replacementMaterial->setReplacement();
// bind as a material override for this draw
overrideMaterialData = &replacementMaterial.value();
}
@@ -525,7 +523,7 @@ namespace dxvk {
if (overrideMaterialData == nullptr) {
// Note: Color texture used as mask texture for the Ray Portal
- rayPortalMaterialData.emplace(RayPortalMaterialData { input.getMaterialData().getColorTexture(), texture2, static_cast(rayPortalTextureIndex), 1, 1, 0, 0.f,true, 1.f, 0, 0, 0 });
+ rayPortalMaterialData.emplace(RayPortalMaterialData { input.getMaterialData().getColorTexture(), texture2, static_cast(rayPortalTextureIndex), 1, 1, 0, 0.f,true, 1.f, lss::Mdl::Filter::Linear, lss::Mdl::WrapMode::Repeat, lss::Mdl::WrapMode::Repeat });
// Note: A bit dirty but since we use a pointer to the material data in processDrawCallState, we need a pointer to this locally created one on the
// stack in a place that doesn't go out of scope without actually allocating any heap memory.
@@ -847,17 +845,15 @@ namespace dxvk {
// Legacy and replacement materials should follow same filtering but due to lack of override capability per texture
// legacy textures use original sampler to stay true to the original intent while replacements use more advanced filtering
// for better quality by default.
- Rc originalSampler = drawCallState.getMaterialData().getSampler(); // convenience variable for debug
+ const Rc& originalSampler = drawCallState.getMaterialData().getSampler(); // convenience variable for debug
Rc sampler = originalSampler;
const bool isLegacyMaterial = (renderMaterialDataType == MaterialDataType::Legacy);
// If the original sampler if valid and the new rendering material is not legacy type
// go ahead with patching and maybe merging the sampler states
if(originalSampler != nullptr && !isLegacyMaterial) {
DxvkSamplerCreateInfo samplerInfo = originalSampler->info(); // Use sampler create info struct as convenience
- // Only merge prior to patching if this is a replacement material
- if(renderMaterialData.isReplacement()) {
- renderMaterialData.populateSamplerInfo(samplerInfo);
- }
+ renderMaterialData.populateSamplerInfo(samplerInfo);
+
sampler = patchSampler(samplerInfo.magFilter,
samplerInfo.addressModeU, samplerInfo.addressModeV, samplerInfo.addressModeW,
samplerInfo.borderColor);
diff --git a/src/dxvk/rtx_render/rtx_terrain_baker.cpp b/src/dxvk/rtx_render/rtx_terrain_baker.cpp
index 2e1c9f37b..9ed7ccb6e 100644
--- a/src/dxvk/rtx_render/rtx_terrain_baker.cpp
+++ b/src/dxvk/rtx_render/rtx_terrain_baker.cpp
@@ -577,9 +577,10 @@ namespace dxvk {
0.0f, // opaqueMaterialDefaults.subsurfaceMeasurementDistance
Vector3(), // opaqueMaterialDefaults.subsurfaceSingleScatteringAlbedo
0.0f, // opaqueMaterialDefaults.subsurfaceVolumetricAnisotropy
- lss::Mdl::Filter::Nearest,
- lss::Mdl::WrapMode::Repeat, // U
- lss::Mdl::WrapMode::Repeat // V
+ // NOTE: The terrain defines it's own sampler, and these are the modes it uses.
+ lss::Mdl::Filter::Linear,
+ lss::Mdl::WrapMode::Clamp, // U
+ lss::Mdl::WrapMode::Clamp // V
));
m_hasInitializedMaterialDataThisFrame = true;
diff --git a/src/dxvk/shaders/rtx/concept/surface/surface_create.slangh b/src/dxvk/shaders/rtx/concept/surface/surface_create.slangh
index fae5626df..badd33e4a 100644
--- a/src/dxvk/shaders/rtx/concept/surface/surface_create.slangh
+++ b/src/dxvk/shaders/rtx/concept/surface/surface_create.slangh
@@ -148,6 +148,8 @@ Surface surfaceCreate(MemorySurface memorySurface)
// Note: 8 bits free here in the texture spritesheet data.
surface.decalSortOrder = memorySurface.data15.x & 0xFF;
+
+ surface.objectPickingValue = memorySurface.data1.y;
return surface;
}