mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-20 12:38:59 +02:00
[maxwell, vk] VK_EXT_Sample_Locations
This commit is contained in:
parent
b3d65d7671
commit
531d44a90b
9 changed files with 133 additions and 2 deletions
|
|
@ -5,6 +5,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#include <span>
|
||||
|
||||
|
|
@ -23,6 +24,7 @@
|
|||
#include "video_core/renderer_vulkan/vk_texture_cache.h"
|
||||
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
||||
#include "video_core/shader_notify.h"
|
||||
#include "video_core/texture_cache/samples_helper.h"
|
||||
#include "video_core/texture_cache/texture_cache.h"
|
||||
#include "video_core/vulkan_common/vulkan_device.h"
|
||||
|
||||
|
|
@ -747,11 +749,13 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
|||
|
||||
const bool supports_alpha_output = fragment_has_color0_output;
|
||||
const bool alpha_to_one_supported = device.SupportsAlphaToOne();
|
||||
const VkPipelineMultisampleStateCreateInfo multisample_ci{
|
||||
const auto msaa_mode = key.state.msaa_mode.Value();
|
||||
const VkSampleCountFlagBits vk_samples = MaxwellToVK::MsaaMode(msaa_mode);
|
||||
VkPipelineMultisampleStateCreateInfo multisample_ci{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.rasterizationSamples = MaxwellToVK::MsaaMode(key.state.msaa_mode),
|
||||
.rasterizationSamples = vk_samples,
|
||||
.sampleShadingEnable = Settings::values.sample_shading.GetValue() > 0 ? VK_TRUE : VK_FALSE,
|
||||
.minSampleShading = f32(Settings::values.sample_shading.GetValue()) / 100.0f,
|
||||
.pSampleMask = nullptr,
|
||||
|
|
@ -760,6 +764,27 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
|||
.alphaToOneEnable = supports_alpha_output && alpha_to_one_supported &&
|
||||
key.state.alpha_to_one_enabled != 0 ? VK_TRUE : VK_FALSE,
|
||||
};
|
||||
|
||||
std::array<VkSampleLocationEXT, 16> default_sample_locations{};
|
||||
VkSampleLocationsInfoEXT sample_locations_info{
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
|
||||
.pNext = nullptr,
|
||||
.sampleLocationsPerPixel = vk_samples,
|
||||
.sampleLocationGridSize = {1u, 1u},
|
||||
.sampleLocationsCount = static_cast<u32>(VideoCommon::NumSamples(msaa_mode)),
|
||||
.pSampleLocations = default_sample_locations.data(),
|
||||
};
|
||||
VkPipelineSampleLocationsStateCreateInfoEXT sample_locations_ci{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT,
|
||||
.pNext = nullptr,
|
||||
.sampleLocationsEnable = VK_FALSE,
|
||||
.sampleLocationsInfo = sample_locations_info,
|
||||
};
|
||||
if (device.IsExtSampleLocationsSupported() && sample_locations_info.sampleLocationsCount > 1 &&
|
||||
device.SupportsSampleLocationsFor(vk_samples)) {
|
||||
sample_locations_ci.sampleLocationsEnable = VK_TRUE;
|
||||
sample_locations_ci.pNext = std::exchange(multisample_ci.pNext, &sample_locations_ci);
|
||||
}
|
||||
const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
|
|
@ -909,6 +934,10 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
|||
}
|
||||
}
|
||||
|
||||
if (sample_locations_ci.sampleLocationsEnable) {
|
||||
dynamic_states.push_back(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
|
||||
}
|
||||
|
||||
const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
||||
#include "video_core/shader_cache.h"
|
||||
#include "video_core/texture_cache/texture_cache_base.h"
|
||||
#include "video_core/texture_cache/samples_helper.h"
|
||||
#include "video_core/vulkan_common/vulkan_device.h"
|
||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||
|
||||
|
|
@ -996,6 +997,7 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
|||
UpdateDepthBounds(regs);
|
||||
UpdateStencilFaces(regs);
|
||||
UpdateLineWidth(regs);
|
||||
UpdateSampleLocations(regs);
|
||||
|
||||
// EDS1: CullMode, DepthCompare, FrontFace, StencilOp, DepthBoundsTest, DepthTest, DepthWrite, StencilTest
|
||||
if (device.IsExtExtendedDynamicStateSupported()) {
|
||||
|
|
@ -1358,6 +1360,58 @@ void RasterizerVulkan::UpdateLineWidth(Tegra::Engines::Maxwell3D::Regs& regs) {
|
|||
scheduler.Record([width](vk::CommandBuffer cmdbuf) { cmdbuf.SetLineWidth(width); });
|
||||
}
|
||||
|
||||
void RasterizerVulkan::UpdateSampleLocations(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||
if (!device.IsExtSampleLocationsSupported()) {
|
||||
state_tracker.TouchSampleLocations();
|
||||
return;
|
||||
}
|
||||
if (!state_tracker.TouchSampleLocations()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto msaa_mode = regs.anti_alias_samples_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);
|
||||
if (!device.SupportsSampleLocationsFor(vk_samples)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& props = device.SampleLocationProperties();
|
||||
std::array<VkSampleLocationEXT, 16> locations{};
|
||||
constexpr float unit = 1.0f / 16.0f;
|
||||
const auto clamp_coord = [&](float coord) {
|
||||
return std::clamp(coord, props.sampleLocationCoordinateRange[0],
|
||||
props.sampleLocationCoordinateRange[1]);
|
||||
};
|
||||
|
||||
for (u32 sample_index = 0; sample_index < sample_count; ++sample_index) {
|
||||
const auto& packed = regs.multisample_sample_locations[sample_index / 4];
|
||||
const auto [raw_x, raw_y] = packed.Location(sample_index % 4);
|
||||
const float x = clamp_coord((static_cast<int>(raw_x) - 8) * unit);
|
||||
const float y = clamp_coord((static_cast<int>(raw_y) - 8) * unit);
|
||||
locations[sample_index] = VkSampleLocationEXT{.x = x, .y = y};
|
||||
}
|
||||
|
||||
VkSampleLocationsInfoEXT info{
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
|
||||
.pNext = nullptr,
|
||||
.sampleLocationsPerPixel = vk_samples,
|
||||
.sampleLocationGridSize = {1u, 1u},
|
||||
.sampleLocationsCount = sample_count,
|
||||
.pSampleLocations = locations.data(),
|
||||
};
|
||||
|
||||
scheduler.Record([info, locations](vk::CommandBuffer cmdbuf) mutable {
|
||||
auto info_copy = info;
|
||||
info_copy.pSampleLocations = locations.data();
|
||||
cmdbuf.SetSampleLocationsEXT(info_copy);
|
||||
});
|
||||
}
|
||||
|
||||
void RasterizerVulkan::UpdateCullMode(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||
if (!state_tracker.TouchCullMode()) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ private:
|
|||
void UpdateDepthBounds(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateLineWidth(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateSampleLocations(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
|
||||
void UpdateCullMode(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateDepthBoundsTestEnable(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ Flags MakeInvalidationFlags() {
|
|||
StencilWriteMask,
|
||||
StencilCompare,
|
||||
LineWidth,
|
||||
SampleLocations,
|
||||
CullMode,
|
||||
DepthBoundsEnable,
|
||||
DepthTestEnable,
|
||||
|
|
@ -129,6 +130,12 @@ void SetupDirtyLineWidth(Tables& tables) {
|
|||
tables[0][OFF(line_width_aliased)] = LineWidth;
|
||||
}
|
||||
|
||||
void SetupDirtySampleLocations(Tables& tables) {
|
||||
tables[0][OFF(anti_alias_samples_mode)] = SampleLocations;
|
||||
FillBlock(tables[0], OFF(multisample_sample_locations),
|
||||
NUM(multisample_sample_locations), SampleLocations);
|
||||
}
|
||||
|
||||
void SetupDirtyCullMode(Tables& tables) {
|
||||
auto& table = tables[0];
|
||||
table[OFF(gl_cull_face)] = CullMode;
|
||||
|
|
@ -246,6 +253,7 @@ void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) {
|
|||
SetupDirtyDepthBounds(tables);
|
||||
SetupDirtyStencilProperties(tables);
|
||||
SetupDirtyLineWidth(tables);
|
||||
SetupDirtySampleLocations(tables);
|
||||
SetupDirtyCullMode(tables);
|
||||
SetupDirtyStateEnable(tables);
|
||||
SetupDirtyDepthCompareOp(tables);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ enum : u8 {
|
|||
StencilWriteMask,
|
||||
StencilCompare,
|
||||
LineWidth,
|
||||
SampleLocations,
|
||||
|
||||
CullMode,
|
||||
DepthBoundsEnable,
|
||||
|
|
@ -185,6 +186,10 @@ public:
|
|||
return Exchange(Dirty::LineWidth, false);
|
||||
}
|
||||
|
||||
bool TouchSampleLocations() {
|
||||
return Exchange(Dirty::SampleLocations, false);
|
||||
}
|
||||
|
||||
bool TouchCullMode() {
|
||||
return Exchange(Dirty::CullMode, false);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue