mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-25 07:09:48 -06:00
Merge pull request #10890 from tellowkrinkle/VertexLineExpand
VideoCommon: Add vertex shader point/line expansion
This commit is contained in:
@ -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(¶ms[param_count], 1, D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
param_count++;
|
||||
SetRootParamCBV(¶ms[param_count], 0, D3D12_SHADER_VISIBILITY_GEOMETRY);
|
||||
if (g_ActiveConfig.UseVSForLinePointExpand())
|
||||
SetRootParamCBV(¶ms[param_count], 2, D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
else
|
||||
SetRootParamCBV(¶ms[param_count], 0, D3D12_SHADER_VISIBILITY_GEOMETRY);
|
||||
param_count++;
|
||||
SetRootParamTable(¶ms[param_count], &ranges[param_count], D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 3,
|
||||
1, D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
param_count++;
|
||||
SetRootParamConstant(¶ms[param_count], 2, 1, D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
SetRootParamConstant(¶ms[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)
|
||||
|
Reference in New Issue
Block a user