Browse Source

[maxwell, vk] VK_EXT_Sample_Locations

pull/3115/head
CamilleLaVey 4 weeks ago
parent
commit
68345db817
  1. 33
      src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
  2. 54
      src/video_core/renderer_vulkan/vk_rasterizer.cpp
  3. 1
      src/video_core/renderer_vulkan/vk_rasterizer.h
  4. 8
      src/video_core/renderer_vulkan/vk_state_tracker.cpp
  5. 5
      src/video_core/renderer_vulkan/vk_state_tracker.h
  6. 10
      src/video_core/vulkan_common/vulkan_device.cpp
  7. 18
      src/video_core/vulkan_common/vulkan_device.h
  8. 1
      src/video_core/vulkan_common/vulkan_wrapper.cpp
  9. 5
      src/video_core/vulkan_common/vulkan_wrapper.h

33
src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp

@ -5,6 +5,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <array>
#include <iostream>
#include <span>
#include <string_view>
@ -25,6 +26,7 @@
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
#include "video_core/polygon_mode_utils.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"
@ -779,11 +781,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,
@ -792,6 +796,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,
@ -941,6 +966,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,

54
src/video_core/renderer_vulkan/vk_rasterizer.cpp

@ -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/polygon_mode_utils.h"
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
@ -1020,6 +1021,7 @@ void RasterizerVulkan::UpdateDynamicStates() {
UpdateDepthBounds(regs);
UpdateStencilFaces(regs);
UpdateLineWidth(regs);
UpdateSampleLocations(regs);
// EDS1: CullMode, DepthCompare, FrontFace, StencilOp, DepthBoundsTest, DepthTest, DepthWrite, StencilTest
if (device.IsExtExtendedDynamicStateSupported()) {
@ -1375,6 +1377,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;

1
src/video_core/renderer_vulkan/vk_rasterizer.h

@ -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);

8
src/video_core/renderer_vulkan/vk_state_tracker.cpp

@ -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);

5
src/video_core/renderer_vulkan/vk_state_tracker.h

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

10
src/video_core/vulkan_common/vulkan_device.cpp

@ -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;
@ -1379,6 +1384,11 @@ void Device::RemoveUnsuitableExtensions() {
RemoveExtensionFeatureIfUnsuitable(extensions.transform_feedback, features.transform_feedback,
VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
// 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;

18
src/video_core/vulkan_common/vulkan_device.h

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

1
src/video_core/vulkan_common/vulkan_wrapper.cpp

@ -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);

5
src/video_core/vulkan_common/vulkan_wrapper.h

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

Loading…
Cancel
Save