[maxwell, vk] VK_EXT_Sample_Locations
This commit is contained in:
committed by
Caio Oliveira
parent
1bd8012450
commit
e66bc40b8b
@@ -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() ? VK_TRUE : VK_FALSE,
|
||||
.minSampleShading = static_cast<float>(Settings::values.sample_shading_fraction.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);
|
||||
}
|
||||
|
||||
@@ -1108,6 +1108,11 @@ bool Device::GetSuitability(bool requires_swapchain) {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT;
|
||||
SetNext(next, properties.transform_feedback);
|
||||
}
|
||||
if (extensions.sample_locations) {
|
||||
properties.sample_locations.sType =
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT;
|
||||
SetNext(next, properties.sample_locations);
|
||||
}
|
||||
if (extensions.maintenance5) {
|
||||
properties.maintenance5.sType =
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR;
|
||||
@@ -1385,6 +1390,11 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
properties.transform_feedback.transformFeedbackQueries);
|
||||
}
|
||||
|
||||
// VK_EXT_sample_locations
|
||||
extensions.sample_locations = features.sample_locations.sampleLocations;
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.sample_locations, features.sample_locations,
|
||||
VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_vertex_input_dynamic_state
|
||||
extensions.vertex_input_dynamic_state =
|
||||
features.vertex_input_dynamic_state.vertexInputDynamicState;
|
||||
|
||||
@@ -63,6 +63,7 @@ VK_DEFINE_HANDLE(VmaAllocator)
|
||||
FEATURE(EXT, ProvokingVertex, PROVOKING_VERTEX, provoking_vertex) \
|
||||
FEATURE(EXT, Robustness2, ROBUSTNESS_2, robustness2) \
|
||||
FEATURE(EXT, TransformFeedback, TRANSFORM_FEEDBACK, transform_feedback) \
|
||||
FEATURE(EXT, SampleLocations, SAMPLE_LOCATIONS, sample_locations) \
|
||||
FEATURE(EXT, VertexInputDynamicState, VERTEX_INPUT_DYNAMIC_STATE, vertex_input_dynamic_state) \
|
||||
FEATURE(EXT, SwapchainMaintenance1, SWAPCHAIN_MAINTENANCE_1, swapchain_maintenance1) \
|
||||
FEATURE(KHR, Maintenance5, MAINTENANCE_5, maintenance5) \
|
||||
@@ -342,6 +343,11 @@ public:
|
||||
return properties.float_controls;
|
||||
}
|
||||
|
||||
/// Returns sample location properties (VK_EXT_sample_locations).
|
||||
const VkPhysicalDeviceSampleLocationsPropertiesEXT& SampleLocationProperties() const {
|
||||
return properties.sample_locations;
|
||||
}
|
||||
|
||||
/// Returns true if ASTC is natively supported.
|
||||
bool IsOptimalAstcSupported() const {
|
||||
return features.features.textureCompressionASTC_LDR;
|
||||
@@ -550,6 +556,17 @@ public:
|
||||
return extensions.transform_feedback;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports VK_EXT_sample_locations.
|
||||
bool IsExtSampleLocationsSupported() const {
|
||||
return extensions.sample_locations;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports custom sample locations for the given sample count.
|
||||
bool SupportsSampleLocationsFor(VkSampleCountFlagBits samples) const {
|
||||
return extensions.sample_locations &&
|
||||
(properties.sample_locations.sampleLocationSampleCounts & samples) != 0;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports VK_EXT_transform_feedback properly.
|
||||
bool AreTransformFeedbackGeometryStreamsSupported() const {
|
||||
return features.transform_feedback.geometryStreams;
|
||||
@@ -1017,6 +1034,7 @@ private:
|
||||
VkPhysicalDevicePushDescriptorPropertiesKHR push_descriptor{};
|
||||
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control{};
|
||||
VkPhysicalDeviceTransformFeedbackPropertiesEXT transform_feedback{};
|
||||
VkPhysicalDeviceSampleLocationsPropertiesEXT sample_locations{};
|
||||
VkPhysicalDeviceMaintenance5PropertiesKHR maintenance5{};
|
||||
VkPhysicalDeviceMultiDrawPropertiesEXT multi_draw{};
|
||||
|
||||
|
||||
@@ -166,6 +166,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
|
||||
X(vkCmdSetColorWriteMaskEXT);
|
||||
X(vkCmdSetColorBlendEnableEXT);
|
||||
X(vkCmdSetColorBlendEquationEXT);
|
||||
X(vkCmdSetSampleLocationsEXT);
|
||||
X(vkCmdResolveImage);
|
||||
X(vkCreateBuffer);
|
||||
X(vkCreateBufferView);
|
||||
|
||||
@@ -266,6 +266,7 @@ struct DeviceDispatch : InstanceDispatch {
|
||||
PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT{};
|
||||
PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT{};
|
||||
PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT{};
|
||||
PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT{};
|
||||
PFN_vkCmdWaitEvents vkCmdWaitEvents{};
|
||||
PFN_vkCreateBuffer vkCreateBuffer{};
|
||||
PFN_vkCreateBufferView vkCreateBufferView{};
|
||||
@@ -1525,6 +1526,10 @@ public:
|
||||
dld->vkCmdSetColorBlendEquationEXT(handle, first, equations.size(), equations.data());
|
||||
}
|
||||
|
||||
void SetSampleLocationsEXT(const VkSampleLocationsInfoEXT& info) const noexcept {
|
||||
dld->vkCmdSetSampleLocationsEXT(handle, &info);
|
||||
}
|
||||
|
||||
void SetLineWidth(float line_width) const noexcept {
|
||||
dld->vkCmdSetLineWidth(handle, line_width);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user