mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-27 17:58:59 +02:00
[vk, rasterizer] Update sample location handling for MSAA configurations
This commit is contained in:
parent
3496e5ef0d
commit
2bd503f8cc
3 changed files with 50 additions and 14 deletions
|
|
@ -798,13 +798,17 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||||
key.state.alpha_to_one_enabled != 0 ? VK_TRUE : VK_FALSE,
|
key.state.alpha_to_one_enabled != 0 ? VK_TRUE : VK_FALSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<VkSampleLocationEXT, 16> default_sample_locations{};
|
const auto [sample_grid_width, sample_grid_height] =
|
||||||
|
VideoCommon::SampleLocationGridSize(msaa_mode);
|
||||||
|
const u32 sample_count = static_cast<u32>(VideoCommon::NumSamples(msaa_mode));
|
||||||
|
const u32 total_sample_locations = sample_count * sample_grid_width * sample_grid_height;
|
||||||
|
std::array<VkSampleLocationEXT, VideoCommon::MaxSampleLocationSlots> default_sample_locations{};
|
||||||
VkSampleLocationsInfoEXT sample_locations_info{
|
VkSampleLocationsInfoEXT sample_locations_info{
|
||||||
.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
|
.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.sampleLocationsPerPixel = vk_samples,
|
.sampleLocationsPerPixel = vk_samples,
|
||||||
.sampleLocationGridSize = {1u, 1u},
|
.sampleLocationGridSize = {sample_grid_width, sample_grid_height},
|
||||||
.sampleLocationsCount = static_cast<u32>(VideoCommon::NumSamples(msaa_mode)),
|
.sampleLocationsCount = total_sample_locations,
|
||||||
.pSampleLocations = default_sample_locations.data(),
|
.pSampleLocations = default_sample_locations.data(),
|
||||||
};
|
};
|
||||||
VkPipelineSampleLocationsStateCreateInfoEXT sample_locations_ci{
|
VkPipelineSampleLocationsStateCreateInfoEXT sample_locations_ci{
|
||||||
|
|
@ -813,7 +817,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||||
.sampleLocationsEnable = VK_FALSE,
|
.sampleLocationsEnable = VK_FALSE,
|
||||||
.sampleLocationsInfo = sample_locations_info,
|
.sampleLocationsInfo = sample_locations_info,
|
||||||
};
|
};
|
||||||
if (device.IsExtSampleLocationsSupported() && sample_locations_info.sampleLocationsCount > 1 &&
|
if (device.IsExtSampleLocationsSupported() && total_sample_locations > 0 &&
|
||||||
device.SupportsSampleLocationsFor(vk_samples)) {
|
device.SupportsSampleLocationsFor(vk_samples)) {
|
||||||
sample_locations_ci.sampleLocationsEnable = VK_TRUE;
|
sample_locations_ci.sampleLocationsEnable = VK_TRUE;
|
||||||
sample_locations_ci.pNext = std::exchange(multisample_ci.pNext, &sample_locations_ci);
|
sample_locations_ci.pNext = std::exchange(multisample_ci.pNext, &sample_locations_ci);
|
||||||
|
|
|
||||||
|
|
@ -1411,39 +1411,44 @@ void RasterizerVulkan::UpdateSampleLocations(Tegra::Engines::Maxwell3D::Regs& re
|
||||||
|
|
||||||
const auto msaa_mode = regs.anti_alias_samples_mode;
|
const auto msaa_mode = regs.anti_alias_samples_mode;
|
||||||
const u32 sample_count = static_cast<u32>(VideoCommon::NumSamples(msaa_mode));
|
const u32 sample_count = static_cast<u32>(VideoCommon::NumSamples(msaa_mode));
|
||||||
if (sample_count <= 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const VkSampleCountFlagBits vk_samples = MaxwellToVK::MsaaMode(msaa_mode);
|
const VkSampleCountFlagBits vk_samples = MaxwellToVK::MsaaMode(msaa_mode);
|
||||||
if (!device.SupportsSampleLocationsFor(vk_samples)) {
|
if (!device.SupportsSampleLocationsFor(vk_samples)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto [grid_width, grid_height] = VideoCommon::SampleLocationGridSize(msaa_mode);
|
||||||
|
const u32 total_locations = sample_count * grid_width * grid_height;
|
||||||
|
if (total_locations == 0 || total_locations > VideoCommon::MaxSampleLocationSlots) {
|
||||||
|
LOG_WARNING(Render_Vulkan, "Unsupported sample-location grid configuration: samples={}, grid={}x{}",
|
||||||
|
sample_count, grid_width, grid_height);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto& props = device.SampleLocationProperties();
|
const auto& props = device.SampleLocationProperties();
|
||||||
std::array<VkSampleLocationEXT, 16> locations{};
|
std::array<VkSampleLocationEXT, VideoCommon::MaxSampleLocationSlots> locations{};
|
||||||
constexpr float unit = 1.0f / 16.0f;
|
constexpr float unit = 1.0f / 16.0f;
|
||||||
const auto clamp_coord = [&](float coord) {
|
const auto clamp_coord = [&](float coord) {
|
||||||
return std::clamp(coord, props.sampleLocationCoordinateRange[0],
|
return std::clamp(coord, props.sampleLocationCoordinateRange[0],
|
||||||
props.sampleLocationCoordinateRange[1]);
|
props.sampleLocationCoordinateRange[1]);
|
||||||
};
|
};
|
||||||
|
|
||||||
for (u32 sample_index = 0; sample_index < sample_count; ++sample_index) {
|
for (u32 index = 0; index < total_locations; ++index) {
|
||||||
const auto& packed = regs.multisample_sample_locations[sample_index / 4];
|
const auto& packed = regs.multisample_sample_locations[index / 4];
|
||||||
const auto [raw_x, raw_y] = packed.Location(sample_index % 4);
|
const auto [raw_x, raw_y] = packed.Location(index % 4);
|
||||||
const float offset_x = static_cast<float>(static_cast<int>(raw_x) - 8);
|
const float offset_x = static_cast<float>(static_cast<int>(raw_x) - 8);
|
||||||
const float offset_y = static_cast<float>(static_cast<int>(raw_y) - 8);
|
const float offset_y = static_cast<float>(static_cast<int>(raw_y) - 8);
|
||||||
const float x = clamp_coord(offset_x * unit);
|
const float x = clamp_coord(offset_x * unit);
|
||||||
const float y = clamp_coord(offset_y * unit);
|
const float y = clamp_coord(offset_y * unit);
|
||||||
locations[sample_index] = VkSampleLocationEXT{.x = x, .y = y};
|
locations[index] = VkSampleLocationEXT{.x = x, .y = y};
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSampleLocationsInfoEXT info{
|
VkSampleLocationsInfoEXT info{
|
||||||
.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
|
.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.sampleLocationsPerPixel = vk_samples,
|
.sampleLocationsPerPixel = vk_samples,
|
||||||
.sampleLocationGridSize = {1u, 1u},
|
.sampleLocationGridSize = {grid_width, grid_height},
|
||||||
.sampleLocationsCount = sample_count,
|
.sampleLocationsCount = total_locations,
|
||||||
.pSampleLocations = nullptr,
|
.pSampleLocations = nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,22 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
#include "video_core/textures/texture.h"
|
#include "video_core/textures/texture.h"
|
||||||
|
|
||||||
namespace VideoCommon {
|
namespace VideoCommon {
|
||||||
|
|
||||||
|
constexpr inline std::size_t MaxSampleLocationSlots = 16;
|
||||||
|
|
||||||
[[nodiscard]] inline std::pair<int, int> SamplesLog2(int num_samples) {
|
[[nodiscard]] inline std::pair<int, int> SamplesLog2(int num_samples) {
|
||||||
switch (num_samples) {
|
switch (num_samples) {
|
||||||
case 1:
|
case 1:
|
||||||
|
|
@ -95,4 +102,24 @@ namespace VideoCommon {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NVN guarantees up to sixteen programmable sample slots shared across a repeating pixel grid
|
||||||
|
// (per the 0.7.0 addon release notes), so the grid dimensions shrink as MSAA increases.
|
||||||
|
[[nodiscard]] inline std::pair<u32, u32> SampleLocationGridSize(Tegra::Texture::MsaaMode msaa_mode) {
|
||||||
|
const int samples = NumSamples(msaa_mode);
|
||||||
|
switch (samples) {
|
||||||
|
case 1:
|
||||||
|
return {4u, 4u};
|
||||||
|
case 2:
|
||||||
|
return {4u, 2u};
|
||||||
|
case 4:
|
||||||
|
return {2u, 2u};
|
||||||
|
case 8:
|
||||||
|
return {2u, 1u};
|
||||||
|
case 16:
|
||||||
|
return {1u, 1u};
|
||||||
|
}
|
||||||
|
ASSERT_MSG(false, "Unsupported sample count for grid size={}", samples);
|
||||||
|
return {1u, 1u};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace VideoCommon
|
} // namespace VideoCommon
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue