shader: Rework varyings and implement passthrough geometry shaders

Put all varyings into a single std::bitset with helpers to access it.

Implement passthrough geometry shaders using host's.
This commit is contained in:
ReinUsesLisp 2021-06-24 02:41:09 -03:00 committed by ameerj
parent 4f052a1f39
commit 7dafa96ab5
29 changed files with 351 additions and 337 deletions

View file

@ -961,7 +961,11 @@ public:
SamplerIndex sampler_index;
INSERT_PADDING_WORDS_NOINIT(0x25);
INSERT_PADDING_WORDS_NOINIT(0x2);
std::array<u32, 8> gp_passthrough_mask;
INSERT_PADDING_WORDS_NOINIT(0x1B);
u32 depth_test_enable;
@ -1628,6 +1632,7 @@ ASSERT_REG_POSITION(zeta_width, 0x48a);
ASSERT_REG_POSITION(zeta_height, 0x48b);
ASSERT_REG_POSITION(zeta_depth, 0x48c);
ASSERT_REG_POSITION(sampler_index, 0x48D);
ASSERT_REG_POSITION(gp_passthrough_mask, 0x490);
ASSERT_REG_POSITION(depth_test_enable, 0x4B3);
ASSERT_REG_POSITION(independent_blend_enable, 0x4B9);
ASSERT_REG_POSITION(depth_write_enabled, 0x4BA);

View file

@ -61,10 +61,10 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
bool glasm_use_storage_buffers, bool use_assembly_shaders) {
Shader::RuntimeInfo info;
if (previous_program) {
info.previous_stage_stores_generic = previous_program->info.stores_generics;
info.previous_stage_stores = previous_program->info.stores;
} else {
// Mark all stores as available
info.previous_stage_stores_generic.flip();
// Mark all stores as available for vertex shaders
info.previous_stage_stores.mask.set();
}
switch (program.stage) {
case Shader::Stage::VertexB:
@ -187,6 +187,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
.support_demote_to_helper_invocation = false,
.support_int64_atomics = false,
.support_derivative_control = device.HasDerivativeControl(),
.support_geometry_shader_passthrough = false, // TODO
.support_gl_nv_gpu_shader_5 = device.HasNvGpuShader5(),
.support_gl_amd_gpu_shader_half_float = device.HasAmdShaderHalfFloat(),
.support_gl_texture_shadow_lod = device.HasTextureShadowLod(),

View file

@ -487,10 +487,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
static_vector<VkVertexInputBindingDivisorDescriptionEXT, 32> vertex_binding_divisors;
static_vector<VkVertexInputAttributeDescription, 32> vertex_attributes;
if (key.state.dynamic_vertex_input) {
const auto& input_attributes = stage_infos[0].input_generics;
for (size_t index = 0; index < key.state.attributes.size(); ++index) {
const u32 type = key.state.DynamicAttributeType(index);
if (!input_attributes[index].used || type == 0) {
if (!stage_infos[0].loads.Generic(index) || type == 0) {
continue;
}
vertex_attributes.push_back({
@ -526,10 +525,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
});
}
}
const auto& input_attributes = stage_infos[0].input_generics;
for (size_t index = 0; index < key.state.attributes.size(); ++index) {
const auto& attribute = key.state.attributes[index];
if (!attribute.enabled || !input_attributes[index].used) {
if (!attribute.enabled || !stage_infos[0].loads.Generic(index)) {
continue;
}
vertex_attributes.push_back({

View file

@ -123,18 +123,21 @@ Shader::AttributeType AttributeType(const FixedPipelineState& state, size_t inde
return Shader::AttributeType::Disabled;
}
Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineCacheKey& key,
Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> programs,
const GraphicsPipelineCacheKey& key,
const Shader::IR::Program& program,
const Shader::IR::Program* previous_program) {
Shader::RuntimeInfo info;
if (previous_program) {
info.previous_stage_stores_generic = previous_program->info.stores_generics;
info.previous_stage_stores = previous_program->info.stores;
if (previous_program->is_geometry_passthrough) {
info.previous_stage_stores.mask |= previous_program->info.passthrough.mask;
}
} else {
// Mark all stores as available
info.previous_stage_stores_generic.flip();
info.previous_stage_stores.mask.set();
}
const Shader::Stage stage{program.stage};
const bool has_geometry{key.unique_hashes[4] != 0};
const bool has_geometry{key.unique_hashes[4] != 0 && !programs[4].is_geometry_passthrough};
const bool gl_ndc{key.state.ndc_minus_one_to_one != 0};
const float point_size{Common::BitCast<float>(key.state.point_size)};
switch (stage) {
@ -302,6 +305,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::Engines::Maxw
.support_demote_to_helper_invocation = true,
.support_int64_atomics = device.IsExtShaderAtomicInt64Supported(),
.support_derivative_control = true,
.support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(),
.warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(),
@ -518,7 +522,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
const size_t stage_index{index - 1};
infos[stage_index] = &program.info;
const Shader::RuntimeInfo runtime_info{MakeRuntimeInfo(key, program, previous_stage)};
const auto runtime_info{MakeRuntimeInfo(programs, key, program, previous_stage)};
const std::vector<u32> code{EmitSPIRV(profile, runtime_info, program, binding)};
device.SaveShader(code);
modules[stage_index] = BuildShader(device, code);

View file

@ -22,7 +22,7 @@
namespace VideoCommon {
constexpr std::array<char, 8> MAGIC_NUMBER{'y', 'u', 'z', 'u', 'c', 'a', 'c', 'h'};
constexpr u32 CACHE_VERSION = 4;
constexpr u32 CACHE_VERSION = 5;
constexpr size_t INST_SIZE = sizeof(u64);
@ -155,6 +155,10 @@ void GenericEnvironment::Serialize(std::ofstream& file) const {
.write(reinterpret_cast<const char*>(&shared_memory_size), sizeof(shared_memory_size));
} else {
file.write(reinterpret_cast<const char*>(&sph), sizeof(sph));
if (stage == Shader::Stage::Geometry) {
file.write(reinterpret_cast<const char*>(&gp_passthrough_mask),
sizeof(gp_passthrough_mask));
}
}
}
@ -202,6 +206,7 @@ GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_,
u32 start_address_)
: GenericEnvironment{gpu_memory_, program_base_, start_address_}, maxwell3d{&maxwell3d_} {
gpu_memory->ReadBlock(program_base + start_address, &sph, sizeof(sph));
gp_passthrough_mask = maxwell3d->regs.gp_passthrough_mask;
switch (program) {
case Maxwell::ShaderProgram::VertexA:
stage = Shader::Stage::VertexA;
@ -319,6 +324,9 @@ void FileEnvironment::Deserialize(std::ifstream& file) {
.read(reinterpret_cast<char*>(&shared_memory_size), sizeof(shared_memory_size));
} else {
file.read(reinterpret_cast<char*>(&sph), sizeof(sph));
if (stage == Shader::Stage::Geometry) {
file.read(reinterpret_cast<char*>(&gp_passthrough_mask), sizeof(gp_passthrough_mask));
}
}
}

View file

@ -350,6 +350,10 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
LOG_INFO(Render_Vulkan, "Device doesn't support viewport masks");
}
if (!nv_geometry_shader_passthrough) {
LOG_INFO(Render_Vulkan, "Device doesn't support passthrough geometry shaders");
}
VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR std430_layout;
if (khr_uniform_buffer_standard_layout) {
std430_layout = {
@ -768,6 +772,8 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
};
test(nv_viewport_swizzle, VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME, true);
test(nv_viewport_array2, VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME, true);
test(nv_geometry_shader_passthrough, VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME,
true);
test(khr_uniform_buffer_standard_layout,
VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME, true);
test(khr_spirv_1_4, VK_KHR_SPIRV_1_4_EXTENSION_NAME, true);

View file

@ -194,6 +194,11 @@ public:
return nv_viewport_array2;
}
/// Returns true if the device supports VK_NV_geometry_shader_passthrough.
bool IsNvGeometryShaderPassthroughSupported() const {
return nv_geometry_shader_passthrough;
}
/// Returns true if the device supports VK_KHR_uniform_buffer_standard_layout.
bool IsKhrUniformBufferStandardLayoutSupported() const {
return khr_uniform_buffer_standard_layout;
@ -363,6 +368,7 @@ private:
bool is_blit_depth_stencil_supported{}; ///< Support for blitting from and to depth stencil.
bool nv_viewport_swizzle{}; ///< Support for VK_NV_viewport_swizzle.
bool nv_viewport_array2{}; ///< Support for VK_NV_viewport_array2.
bool nv_geometry_shader_passthrough{}; ///< Support for VK_NV_geometry_shader_passthrough.
bool khr_uniform_buffer_standard_layout{}; ///< Support for scalar uniform buffer layouts.
bool khr_spirv_1_4{}; ///< Support for VK_KHR_spirv_1_4.
bool khr_workgroup_memory_explicit_layout{}; ///< Support for explicit workgroup layouts.