renderer_vulkan: Fix LMDM crashes
* Cache vertex format lookups to avoid crashing the driver when the game does too many lookups * Increase watcher count. For some reason the game uses way too many watchers * Fix other misc SPIRV bugs and don't crash when shadow is requested
This commit is contained in:
@@ -21,7 +21,7 @@ class MemorySystem;
|
|||||||
namespace GPU {
|
namespace GPU {
|
||||||
|
|
||||||
// Measured on hardware to be 2240568 timer cycles or 4481136 ARM11 cycles
|
// Measured on hardware to be 2240568 timer cycles or 4481136 ARM11 cycles
|
||||||
constexpr u64 frame_ticks = 4481136ull;
|
constexpr u64 frame_ticks = /*4481136ull*/2240568ull;
|
||||||
|
|
||||||
// Refresh rate defined by ratio of ARM11 frequency to ARM11 ticks per frame
|
// Refresh rate defined by ratio of ARM11 frequency to ARM11 ticks per frame
|
||||||
// (268,111,856) / (4,481,136) = 59.83122493939037Hz
|
// (268,111,856) / (4,481,136) = 59.83122493939037Hz
|
||||||
|
@@ -91,8 +91,7 @@ public:
|
|||||||
u32 fill_size = 0;
|
u32 fill_size = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
u32 watcher_count = 0;
|
std::vector<std::weak_ptr<Watcher>> watchers;
|
||||||
std::array<std::weak_ptr<Watcher>, 8> watchers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class S>
|
template <class S>
|
||||||
@@ -190,7 +189,7 @@ template <class S>
|
|||||||
auto SurfaceBase<S>::CreateWatcher() -> std::shared_ptr<Watcher> {
|
auto SurfaceBase<S>::CreateWatcher() -> std::shared_ptr<Watcher> {
|
||||||
auto weak_ptr = reinterpret_cast<S*>(this)->weak_from_this();
|
auto weak_ptr = reinterpret_cast<S*>(this)->weak_from_this();
|
||||||
auto watcher = std::make_shared<Watcher>(std::move(weak_ptr));
|
auto watcher = std::make_shared<Watcher>(std::move(weak_ptr));
|
||||||
watchers[watcher_count++] = watcher;
|
watchers.push_back(watcher);
|
||||||
return watcher;
|
return watcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,8 +211,7 @@ void SurfaceBase<S>::UnlinkAllWatcher() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watchers = {};
|
watchers.clear();
|
||||||
watcher_count = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
@@ -63,10 +63,18 @@ vk::ShaderStageFlagBits ToVkShaderStage(std::size_t index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool IsAttribFormatSupported(const VertexAttribute& attrib, const Instance& instance) {
|
[[nodiscard]] bool IsAttribFormatSupported(const VertexAttribute& attrib, const Instance& instance) {
|
||||||
|
static std::unordered_map<vk::Format, bool> format_support_cache;
|
||||||
|
|
||||||
vk::PhysicalDevice physical_device = instance.GetPhysicalDevice();
|
vk::PhysicalDevice physical_device = instance.GetPhysicalDevice();
|
||||||
const vk::Format format = ToVkAttributeFormat(attrib.type, attrib.size);
|
const vk::Format format = ToVkAttributeFormat(attrib.type, attrib.size);
|
||||||
const vk::FormatFeatureFlags features = physical_device.getFormatProperties(format).bufferFeatures;
|
auto [it, new_format] = format_support_cache.try_emplace(format, false);
|
||||||
return (features & vk::FormatFeatureFlagBits::eVertexBuffer) == vk::FormatFeatureFlagBits::eVertexBuffer;
|
if (new_format) {
|
||||||
|
LOG_INFO(Render_Vulkan, "Quering support for format {}", vk::to_string(format));
|
||||||
|
const vk::FormatFeatureFlags features = physical_device.getFormatProperties(format).bufferFeatures;
|
||||||
|
it->second = (features & vk::FormatFeatureFlagBits::eVertexBuffer) == vk::FormatFeatureFlagBits::eVertexBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second;
|
||||||
};
|
};
|
||||||
|
|
||||||
PipelineCache::PipelineCache(const Instance& instance, Scheduler& scheduler,
|
PipelineCache::PipelineCache(const Instance& instance, Scheduler& scheduler,
|
||||||
|
@@ -1541,7 +1541,6 @@ do {
|
|||||||
|
|
||||||
} while ((old = imageAtomicCompSwap(shadow_buffer, image_coord, old, new)) != old2);
|
} while ((old = imageAtomicCompSwap(shadow_buffer, image_coord, old, new)) != old2);
|
||||||
)";
|
)";
|
||||||
LOG_INFO(Render_Vulkan, "{}", out);
|
|
||||||
} else {
|
} else {
|
||||||
out += "gl_FragDepth = depth;\n";
|
out += "gl_FragDepth = depth;\n";
|
||||||
// Round the final fragment color to maintain the PICA's 8 bits of precision
|
// Round the final fragment color to maintain the PICA's 8 bits of precision
|
||||||
|
@@ -423,7 +423,7 @@ void FragmentModule::WriteLighting() {
|
|||||||
|
|
||||||
// Apply shadow attenuation to alpha components if enabled
|
// Apply shadow attenuation to alpha components if enabled
|
||||||
if (lighting.shadow_alpha) {
|
if (lighting.shadow_alpha) {
|
||||||
const Id shadow_a{OpCompositeExtract(vec_ids.Get(4), shadow, 3)};
|
const Id shadow_a{OpCompositeExtract(f32_id, shadow, 3)};
|
||||||
const Id shadow_a_vec{OpCompositeConstruct(vec_ids.Get(4), ConstF32(1.f, 1.f, 1.f), shadow_a)};
|
const Id shadow_a_vec{OpCompositeConstruct(vec_ids.Get(4), ConstF32(1.f, 1.f, 1.f), shadow_a)};
|
||||||
if (lighting.enable_primary_alpha) {
|
if (lighting.enable_primary_alpha) {
|
||||||
diffuse_sum = OpFMul(vec_ids.Get(4), diffuse_sum, shadow_a_vec);
|
diffuse_sum = OpFMul(vec_ids.Get(4), diffuse_sum, shadow_a_vec);
|
||||||
|
Reference in New Issue
Block a user