Merge pull request #10890 from tellowkrinkle/VertexLineExpand

VideoCommon: Add vertex shader point/line expansion
This commit is contained in:
JMC47
2022-10-23 01:49:26 -04:00
committed by GitHub
36 changed files with 696 additions and 121 deletions
@@ -84,6 +84,8 @@ const Info<int> GFX_SHADER_PRECOMPILER_THREADS{
{System::GFX, "Settings", "ShaderPrecompilerThreads"}, -1};
const Info<bool> GFX_SAVE_TEXTURE_CACHE_TO_STATE{
{System::GFX, "Settings", "SaveTextureCacheToState"}, true};
const Info<bool> GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION{
{System::GFX, "Settings", "PreferVSForLinePointExpansion"}, false};
const Info<bool> GFX_SW_DUMP_OBJECTS{{System::GFX, "Settings", "SWDumpObjects"}, false};
const Info<bool> GFX_SW_DUMP_TEV_STAGES{{System::GFX, "Settings", "SWDumpTevStages"}, false};
@@ -73,6 +73,7 @@ extern const Info<ShaderCompilationMode> GFX_SHADER_COMPILATION_MODE;
extern const Info<int> GFX_SHADER_COMPILER_THREADS;
extern const Info<int> GFX_SHADER_PRECOMPILER_THREADS;
extern const Info<bool> GFX_SAVE_TEXTURE_CACHE_TO_STATE;
extern const Info<bool> GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION;
extern const Info<bool> GFX_SW_DUMP_OBJECTS;
extern const Info<bool> GFX_SW_DUMP_TEV_STAGES;
+1 -1
View File
@@ -94,7 +94,7 @@ static size_t s_state_writes_in_queue;
static std::condition_variable s_state_write_queue_is_empty;
// Don't forget to increase this after doing changes on the savestate system
constexpr u32 STATE_VERSION = 154; // Last changed in PR 11177
constexpr u32 STATE_VERSION = 155; // Last changed in PR 10890
// Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list,
@@ -128,15 +128,18 @@ void AdvancedWidget::CreateWidgets()
m_enable_prog_scan = new ToolTipCheckBox(tr("Enable Progressive Scan"));
m_backend_multithreading =
new GraphicsBool(tr("Backend Multithreading"), Config::GFX_BACKEND_MULTITHREADING);
m_prefer_vs_for_point_line_expansion = new GraphicsBool(
tr("Prefer VS for Point/Line Expansion"), Config::GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION);
misc_layout->addWidget(m_enable_cropping, 0, 0);
misc_layout->addWidget(m_enable_prog_scan, 0, 1);
misc_layout->addWidget(m_backend_multithreading, 1, 0);
misc_layout->addWidget(m_prefer_vs_for_point_line_expansion, 1, 1);
#ifdef _WIN32
m_borderless_fullscreen =
new GraphicsBool(tr("Borderless Fullscreen"), Config::GFX_BORDERLESS_FULLSCREEN);
misc_layout->addWidget(m_borderless_fullscreen, 1, 1);
misc_layout->addWidget(m_borderless_fullscreen, 2, 0);
#endif
// Experimental.
@@ -198,6 +201,10 @@ void AdvancedWidget::SaveSettings()
void AdvancedWidget::OnBackendChanged()
{
m_backend_multithreading->setEnabled(g_Config.backend_info.bSupportsMultithreading);
m_prefer_vs_for_point_line_expansion->setEnabled(
g_Config.backend_info.bSupportsGeometryShaders &&
g_Config.backend_info.bSupportsVSLinePointExpand);
AddDescriptions();
}
void AdvancedWidget::OnEmulationStateChanged(bool running)
@@ -289,6 +296,11 @@ void AdvancedWidget::AddDescriptions()
"this option may result in a performance improvement on systems with more than "
"two CPU cores. Currently, this is limited to the Vulkan backend.<br><br>"
"<dolphin_emphasis>If unsure, leave this checked.</dolphin_emphasis>");
static const char TR_PREFER_VS_FOR_POINT_LINE_EXPANSION_DESCRIPTION[] =
QT_TR_NOOP("On backends that support both using the geometry shader and the vertex shader "
"for expanding points and lines, selects the vertex shader for the job. May "
"affect performance."
"<br><br>%1");
static const char TR_DEFER_EFB_ACCESS_INVALIDATION_DESCRIPTION[] = QT_TR_NOOP(
"Defers invalidation of the EFB access cache until a GPU synchronization command "
"is executed. If disabled, the cache will be invalidated with every draw call. "
@@ -316,6 +328,9 @@ void AdvancedWidget::AddDescriptions()
"unchecked.</dolphin_emphasis>");
#endif
static const char IF_UNSURE_UNCHECKED[] =
QT_TR_NOOP("<dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>");
m_enable_wireframe->SetDescription(tr(TR_WIREFRAME_DESCRIPTION));
m_show_statistics->SetDescription(tr(TR_SHOW_STATS_DESCRIPTION));
m_enable_format_overlay->SetDescription(tr(TR_TEXTURE_FORMAT_DESCRIPTION));
@@ -337,6 +352,17 @@ void AdvancedWidget::AddDescriptions()
m_enable_cropping->SetDescription(tr(TR_CROPPING_DESCRIPTION));
m_enable_prog_scan->SetDescription(tr(TR_PROGRESSIVE_SCAN_DESCRIPTION));
m_backend_multithreading->SetDescription(tr(TR_BACKEND_MULTITHREADING_DESCRIPTION));
QString vsexpand_extra;
if (!g_Config.backend_info.bSupportsGeometryShaders)
vsexpand_extra = tr("Forced on because %1 doesn't support geometry shaders.")
.arg(tr(g_Config.backend_info.DisplayName.c_str()));
else if (!g_Config.backend_info.bSupportsVSLinePointExpand)
vsexpand_extra = tr("Forced off because %1 doesn't support VS expansion.")
.arg(tr(g_Config.backend_info.DisplayName.c_str()));
else
vsexpand_extra = tr(IF_UNSURE_UNCHECKED);
m_prefer_vs_for_point_line_expansion->SetDescription(
tr(TR_PREFER_VS_FOR_POINT_LINE_EXPANSION_DESCRIPTION).arg(vsexpand_extra));
#ifdef _WIN32
m_borderless_fullscreen->SetDescription(tr(TR_BORDERLESS_FULLSCREEN_DESCRIPTION));
#endif
@@ -59,6 +59,7 @@ private:
GraphicsBool* m_enable_cropping;
ToolTipCheckBox* m_enable_prog_scan;
GraphicsBool* m_backend_multithreading;
GraphicsBool* m_prefer_vs_for_point_line_expansion;
GraphicsBool* m_borderless_fullscreen;
// Experimental
@@ -19,6 +19,14 @@
namespace DX12
{
static bool UsesDynamicVertexLoader(const AbstractPipeline* pipeline)
{
const AbstractPipelineUsage usage = static_cast<const DXPipeline*>(pipeline)->GetUsage();
return (g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader &&
usage == AbstractPipelineUsage::GXUber) ||
(g_ActiveConfig.UseVSForLinePointExpand() && usage != AbstractPipelineUsage::Utility);
}
Renderer::Renderer(std::unique_ptr<SwapChain> swap_chain, float backbuffer_scale)
: ::Renderer(swap_chain ? swap_chain->GetWidth() : 0, swap_chain ? swap_chain->GetHeight() : 0,
backbuffer_scale,
@@ -364,8 +372,7 @@ void Renderer::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex)
return;
// DX12 is great and doesn't include the base vertex in SV_VertexID
if (static_cast<const DXPipeline*>(m_current_pipeline)->GetUsage() ==
AbstractPipelineUsage::GXUber)
if (UsesDynamicVertexLoader(m_current_pipeline))
g_dx_context->GetCommandList()->SetGraphicsRoot32BitConstant(
ROOT_PARAMETER_BASE_VERTEX_CONSTANT, base_vertex, 0);
g_dx_context->GetCommandList()->DrawIndexedInstanced(num_indices, 1, base_index, base_vertex, 0);
@@ -601,8 +608,7 @@ bool Renderer::ApplyState()
}
}
if (dirty_bits & DirtyState_VS_SRV_Descriptor &&
pipeline->GetUsage() == AbstractPipelineUsage::GXUber)
if (dirty_bits & DirtyState_VS_SRV_Descriptor && UsesDynamicVertexLoader(pipeline))
{
cmdlist->SetGraphicsRootDescriptorTable(ROOT_PARAMETER_VS_SRV,
m_state.vertex_srv_descriptor_base);
@@ -724,9 +730,7 @@ bool Renderer::UpdateUAVDescriptorTable()
bool Renderer::UpdateVSSRVDescriptorTable()
{
if (!g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader ||
static_cast<const DXPipeline*>(m_current_pipeline)->GetUsage() !=
AbstractPipelineUsage::GXUber)
if (!UsesDynamicVertexLoader(m_current_pipeline))
{
return true;
}
@@ -353,12 +353,15 @@ bool DXContext::CreateGXRootSignature()
param_count++;
SetRootParamCBV(&params[param_count], 1, D3D12_SHADER_VISIBILITY_VERTEX);
param_count++;
SetRootParamCBV(&params[param_count], 0, D3D12_SHADER_VISIBILITY_GEOMETRY);
if (g_ActiveConfig.UseVSForLinePointExpand())
SetRootParamCBV(&params[param_count], 2, D3D12_SHADER_VISIBILITY_VERTEX);
else
SetRootParamCBV(&params[param_count], 0, D3D12_SHADER_VISIBILITY_GEOMETRY);
param_count++;
SetRootParamTable(&params[param_count], &ranges[param_count], D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 3,
1, D3D12_SHADER_VISIBILITY_VERTEX);
param_count++;
SetRootParamConstant(&params[param_count], 2, 1, D3D12_SHADER_VISIBILITY_VERTEX);
SetRootParamConstant(&params[param_count], 3, 1, D3D12_SHADER_VISIBILITY_VERTEX);
param_count++;
// Since these must be contiguous, pixel lighting goes to bbox if not enabled.
@@ -88,6 +88,7 @@ void VideoBackend::FillBackendInfo()
g_Config.backend_info.bSupportsSettingObjectNames = true;
g_Config.backend_info.bSupportsPartialMultisampleResolve = true;
g_Config.backend_info.bSupportsDynamicVertexLoader = true;
g_Config.backend_info.bSupportsVSLinePointExpand = true;
// We can only check texture support once we have a device.
if (g_dx_context)
@@ -83,7 +83,7 @@ public:
void SetTexture(u32 idx, id<MTLTexture> texture);
void SetSampler(u32 idx, const SamplerState& sampler);
void SetComputeTexture(const Texture* texture);
void InvalidateUniforms(bool vertex, bool fragment);
void InvalidateUniforms(bool vertex, bool geometry, bool fragment);
void SetUtilityUniform(const void* buffer, size_t size);
void SetTexelBuffer(id<MTLBuffer> buffer, u32 offset0, u32 offset1);
void SetVerticesAndIndices(id<MTLBuffer> vertices, id<MTLBuffer> indices);
@@ -180,6 +180,7 @@ private:
{
// clang-format off
bool has_gx_vs_uniform : 1;
bool has_gx_gs_uniform : 1;
bool has_gx_ps_uniform : 1;
bool has_utility_vs_uniform : 1;
bool has_utility_ps_uniform : 1;
@@ -15,6 +15,7 @@
#include "VideoBackends/Metal/MTLTexture.h"
#include "VideoBackends/Metal/MTLUtil.h"
#include "VideoCommon/GeometryShaderManager.h"
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/VertexShaderManager.h"
@@ -462,9 +463,10 @@ void Metal::StateTracker::UnbindTexture(id<MTLTexture> texture)
}
}
void Metal::StateTracker::InvalidateUniforms(bool vertex, bool fragment)
void Metal::StateTracker::InvalidateUniforms(bool vertex, bool geometry, bool fragment)
{
m_flags.has_gx_vs_uniform &= !vertex;
m_flags.has_gx_gs_uniform &= !geometry;
m_flags.has_gx_ps_uniform &= !fragment;
}
@@ -722,6 +724,14 @@ void Metal::StateTracker::PrepareRender()
ADDSTAT(g_stats.this_frame.bytes_uniform_streamed,
Align(sizeof(VertexShaderConstants), AlignMask::Uniform));
}
if (!m_flags.has_gx_gs_uniform && pipe->UsesVertexBuffer(2))
{
m_flags.has_gx_gs_uniform = true;
[m_current_render_encoder setVertexBytes:&GeometryShaderManager::constants
length:sizeof(GeometryShaderConstants)
atIndex:2];
ADDSTAT(g_stats.this_frame.bytes_uniform_streamed, sizeof(GeometryShaderConstants));
}
if (!m_flags.has_gx_ps_uniform)
{
m_flags.has_gx_ps_uniform = true;
@@ -75,6 +75,7 @@ void Metal::Util::PopulateBackendInfo(VideoConfig* config)
// Metal requires multisample resolve to be done on a render pass
config->backend_info.bSupportsPartialMultisampleResolve = false;
config->backend_info.bSupportsDynamicVertexLoader = true;
config->backend_info.bSupportsVSLinePointExpand = true;
}
void Metal::Util::PopulateBackendInfoAdapters(VideoConfig* config,
@@ -427,6 +428,7 @@ std::optional<std::string> Metal::Util::TranslateShaderToMSL(ShaderStage stage,
static const spirv_cross::MSLResourceBinding resource_bindings[] = {
MakeResourceBinding(spv::ExecutionModelVertex, 0, 0, 1, 0, 0), // vs/ubo
MakeResourceBinding(spv::ExecutionModelVertex, 0, 1, 1, 0, 0), // vs/ubo
MakeResourceBinding(spv::ExecutionModelVertex, 0, 2, 2, 0, 0), // vs/ubo
MakeResourceBinding(spv::ExecutionModelVertex, 2, 1, 0, 0, 0), // vs/ssbo
MakeResourceBinding(spv::ExecutionModelFragment, 0, 0, 0, 0, 0), // vs/ubo
MakeResourceBinding(spv::ExecutionModelFragment, 0, 1, 1, 0, 0), // vs/ubo
@@ -5,6 +5,7 @@
#include "VideoBackends/Metal/MTLStateTracker.h"
#include "VideoCommon/GeometryShaderManager.h"
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/VertexShaderManager.h"
@@ -88,7 +89,9 @@ void Metal::VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32
void Metal::VertexManager::UploadUniforms()
{
g_state_tracker->InvalidateUniforms(VertexShaderManager::dirty, PixelShaderManager::dirty);
g_state_tracker->InvalidateUniforms(VertexShaderManager::dirty, GeometryShaderManager::dirty,
PixelShaderManager::dirty);
VertexShaderManager::dirty = false;
GeometryShaderManager::dirty = false;
PixelShaderManager::dirty = false;
}
@@ -423,6 +423,8 @@ Renderer::Renderer(std::unique_ptr<GLContext> main_gl_context, float backbuffer_
((GLExtensions::Version() >= 310) || GLExtensions::Supports("GL_NV_primitive_restart"));
g_Config.backend_info.bSupportsFragmentStoresAndAtomics =
GLExtensions::Supports("GL_ARB_shader_storage_buffer_object");
g_Config.backend_info.bSupportsVSLinePointExpand =
GLExtensions::Supports("GL_ARB_shader_storage_buffer_object");
g_Config.backend_info.bSupportsGSInstancing = GLExtensions::Supports("GL_ARB_gpu_shader5");
g_Config.backend_info.bSupportsSSAA = GLExtensions::Supports("GL_ARB_gpu_shader5") &&
GLExtensions::Supports("GL_ARB_sample_shading");
@@ -58,6 +58,11 @@ bool VertexManager::Initialize()
m_vertex_buffer = StreamBuffer::Create(GL_ARRAY_BUFFER, VERTEX_STREAM_BUFFER_SIZE);
m_index_buffer = StreamBuffer::Create(GL_ELEMENT_ARRAY_BUFFER, INDEX_STREAM_BUFFER_SIZE);
if (g_ActiveConfig.UseVSForLinePointExpand() ||
g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader)
{
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_vertex_buffer->GetGLBufferId());
}
if (g_ActiveConfig.backend_info.bSupportsPaletteConversion)
{
@@ -156,9 +156,11 @@ bool ObjectCache::CreateDescriptorSetLayouts()
{5, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT},
}};
std::array<VkDescriptorSetLayoutBinding, 3> ubo_bindings = standard_ubo_bindings;
std::array<VkDescriptorSetLayoutCreateInfo, NUM_DESCRIPTOR_SET_LAYOUTS> create_infos{{
{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, nullptr, 0,
static_cast<u32>(standard_ubo_bindings.size()), standard_ubo_bindings.data()},
static_cast<u32>(ubo_bindings.size()), ubo_bindings.data()},
{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, nullptr, 0,
static_cast<u32>(standard_sampler_bindings.size()), standard_sampler_bindings.data()},
{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, nullptr, 0,
@@ -172,8 +174,17 @@ bool ObjectCache::CreateDescriptorSetLayouts()
}};
// Don't set the GS bit if geometry shaders aren't available.
if (!g_ActiveConfig.backend_info.bSupportsGeometryShaders)
if (g_ActiveConfig.UseVSForLinePointExpand())
{
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders)
ubo_bindings[UBO_DESCRIPTOR_SET_BINDING_GS].stageFlags |= VK_SHADER_STAGE_VERTEX_BIT;
else
ubo_bindings[UBO_DESCRIPTOR_SET_BINDING_GS].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
}
else if (!g_ActiveConfig.backend_info.bSupportsGeometryShaders)
{
create_infos[DESCRIPTOR_SET_LAYOUT_STANDARD_UNIFORM_BUFFERS].bindingCount--;
}
// Remove the dynamic vertex loader's buffer if it'll never be needed
if (!g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader)
@@ -244,12 +255,14 @@ bool ObjectCache::CreatePipelineLayouts()
static_cast<u32>(compute_sets.size()), compute_sets.data(), 0, nullptr},
}};
const bool ssbos_in_standard =
g_ActiveConfig.backend_info.bSupportsBBox || g_ActiveConfig.UseVSForLinePointExpand();
// If bounding box is unsupported, don't bother with the SSBO descriptor set.
if (!g_ActiveConfig.backend_info.bSupportsBBox)
if (!ssbos_in_standard)
pipeline_layout_info[PIPELINE_LAYOUT_STANDARD].setLayoutCount--;
// If neither SSBO-using feature is supported, skip in ubershaders too
if (!g_ActiveConfig.backend_info.bSupportsBBox &&
!g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader)
if (!ssbos_in_standard && !g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader)
pipeline_layout_info[PIPELINE_LAYOUT_UBER].setLayoutCount--;
for (size_t i = 0; i < pipeline_layout_info.size(); i++)
@@ -458,6 +458,9 @@ void StateTracker::UpdateGXDescriptorSet()
std::array<VkWriteDescriptorSet, MAX_DESCRIPTOR_WRITES> writes;
u32 num_writes = 0;
const bool needs_gs_ubo = g_ActiveConfig.backend_info.bSupportsGeometryShaders ||
g_ActiveConfig.UseVSForLinePointExpand();
if (m_dirty_flags & DIRTY_FLAG_GX_UBOS || m_gx_descriptor_sets[0] == VK_NULL_HANDLE)
{
m_gx_descriptor_sets[0] = g_command_buffer_mgr->AllocateDescriptorSet(
@@ -465,8 +468,7 @@ void StateTracker::UpdateGXDescriptorSet()
for (size_t i = 0; i < NUM_UBO_DESCRIPTOR_SET_BINDINGS; i++)
{
if (i == UBO_DESCRIPTOR_SET_BINDING_GS &&
!g_ActiveConfig.backend_info.bSupportsGeometryShaders)
if (i == UBO_DESCRIPTOR_SET_BINDING_GS && !needs_gs_ubo)
{
continue;
}
@@ -505,8 +507,9 @@ void StateTracker::UpdateGXDescriptorSet()
}
const bool needs_bbox_ssbo = g_ActiveConfig.backend_info.bSupportsBBox;
const bool needs_vertex_ssbo = g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader &&
m_pipeline->GetUsage() == AbstractPipelineUsage::GXUber;
const bool needs_vertex_ssbo = (g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader &&
m_pipeline->GetUsage() == AbstractPipelineUsage::GXUber) ||
g_ActiveConfig.UseVSForLinePointExpand();
const bool needs_ssbo = needs_bbox_ssbo || needs_vertex_ssbo;
if (needs_ssbo &&
@@ -520,7 +523,8 @@ void StateTracker::UpdateGXDescriptorSet()
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr, m_gx_descriptor_sets[2], 0, 0, 1,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nullptr, &m_bindings.ssbo, nullptr};
if (g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader)
if (g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader ||
g_ActiveConfig.UseVSForLinePointExpand())
{
writes[num_writes++] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
nullptr,
@@ -546,21 +550,18 @@ void StateTracker::UpdateGXDescriptorSet()
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline->GetVkPipelineLayout(), 0,
needs_ssbo ? NUM_GX_DESCRIPTOR_SETS : (NUM_GX_DESCRIPTOR_SETS - 1),
m_gx_descriptor_sets.data(),
g_ActiveConfig.backend_info.bSupportsGeometryShaders ?
NUM_UBO_DESCRIPTOR_SET_BINDINGS :
(NUM_UBO_DESCRIPTOR_SET_BINDINGS - 1),
needs_gs_ubo ? NUM_UBO_DESCRIPTOR_SET_BINDINGS :
(NUM_UBO_DESCRIPTOR_SET_BINDINGS - 1),
m_bindings.gx_ubo_offsets.data());
m_dirty_flags &= ~(DIRTY_FLAG_DESCRIPTOR_SETS | DIRTY_FLAG_GX_UBO_OFFSETS);
}
else if (m_dirty_flags & DIRTY_FLAG_GX_UBO_OFFSETS)
{
vkCmdBindDescriptorSets(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline->GetVkPipelineLayout(), 0,
1, m_gx_descriptor_sets.data(),
g_ActiveConfig.backend_info.bSupportsGeometryShaders ?
NUM_UBO_DESCRIPTOR_SET_BINDINGS :
(NUM_UBO_DESCRIPTOR_SET_BINDINGS - 1),
m_bindings.gx_ubo_offsets.data());
vkCmdBindDescriptorSets(
g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipeline->GetVkPipelineLayout(), 0, 1, m_gx_descriptor_sets.data(),
needs_gs_ubo ? NUM_UBO_DESCRIPTOR_SET_BINDINGS : (NUM_UBO_DESCRIPTOR_SET_BINDINGS - 1),
m_bindings.gx_ubo_offsets.data());
m_dirty_flags &= ~DIRTY_FLAG_GX_UBO_OFFSETS;
}
}
@@ -304,6 +304,7 @@ void VulkanContext::PopulateBackendInfo(VideoConfig* config)
config->backend_info.bSupportsSettingObjectNames = false; // Dependent on features.
config->backend_info.bSupportsPartialMultisampleResolve = true; // Assumed support.
config->backend_info.bSupportsDynamicVertexLoader = true; // Assumed support.
config->backend_info.bSupportsVSLinePointExpand = true; // Assumed support.
}
void VulkanContext::PopulateBackendInfoAdapters(VideoConfig* config, const GPUList& gpu_list)
@@ -102,9 +102,18 @@ struct VertexShaderConstants
std::array<u32, 8> vertex_offset_texcoords;
};
enum class VSExpand : u32
{
None = 0,
Point,
Line,
};
struct GeometryShaderConstants
{
float4 stereoparams;
float4 lineptparams;
int4 texoffset;
VSExpand vs_expand; // Used by VS point/line expansion in ubershaders
u32 pad[3];
};
+1 -1
View File
@@ -19,7 +19,7 @@ namespace VideoCommon
// As pipelines encompass both shader UIDs and render states, changes to either of these should
// also increment the pipeline UID version. Incrementing the UID version will cause all UID
// caches to be invalidated.
constexpr u32 GX_PIPELINE_UID_VERSION = 5; // Last changed in PR 10747
constexpr u32 GX_PIPELINE_UID_VERSION = 6; // Last changed in PR 10890
struct GXPipelineUid
{
+3 -20
View File
@@ -97,10 +97,8 @@ ShaderCode GenerateGeometryShaderCode(APIType api_type, const ShaderHostConfig&
else
out.Write("cbuffer GSBlock {{\n");
out.Write("\tfloat4 " I_STEREOPARAMS ";\n"
"\tfloat4 " I_LINEPTPARAMS ";\n"
"\tint4 " I_TEXOFFSET ";\n"
"}};\n");
out.Write("{}", s_geometry_shader_uniforms);
out.Write("}};\n");
out.Write("struct VS_OUTPUT {{\n");
GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, host_config, "",
@@ -171,22 +169,7 @@ ShaderCode GenerateGeometryShaderCode(APIType api_type, const ShaderHostConfig&
"\tVS_OUTPUT end = o[1];\n");
}
// GameCube/Wii's line drawing algorithm is a little quirky. It does not
// use the correct line caps. Instead, the line caps are vertical or
// horizontal depending the slope of the line.
out.Write("\tfloat2 offset;\n"
"\tfloat2 to = abs(end.pos.xy / end.pos.w - start.pos.xy / start.pos.w);\n"
// FIXME: What does real hardware do when line is at a 45-degree angle?
// FIXME: Lines aren't drawn at the correct width. See Twilight Princess map.
"\tif (" I_LINEPTPARAMS ".y * to.y > " I_LINEPTPARAMS ".x * to.x) {{\n"
// Line is more tall. Extend geometry left and right.
// Lerp LineWidth/2 from [0..VpWidth] to [-1..1]
"\t\toffset = float2(" I_LINEPTPARAMS ".z / " I_LINEPTPARAMS ".x, 0);\n"
"\t}} else {{\n"
// Line is more wide. Extend geometry up and down.
// Lerp LineWidth/2 from [0..VpHeight] to [1..-1]
"\t\toffset = float2(0, -" I_LINEPTPARAMS ".z / " I_LINEPTPARAMS ".y);\n"
"\t}}\n");
GenerateLineOffset(out, "\t", "\t\t", "end.pos", "start.pos", "");
}
else if (primitive_type == PrimitiveType::Points)
{

Some files were not shown because too many files have changed in this diff Show More