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; }