forked from suyu/suyu
vk_shader_decompiler: Use registry for specialization
This commit is contained in:
parent
8e9f23f393
commit
7acebd7eb6
4 changed files with 37 additions and 31 deletions
|
@ -273,9 +273,9 @@ VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCach
|
||||||
specialization.workgroup_size = key.workgroup_size;
|
specialization.workgroup_size = key.workgroup_size;
|
||||||
specialization.shared_memory_size = key.shared_memory_size;
|
specialization.shared_memory_size = key.shared_memory_size;
|
||||||
|
|
||||||
const SPIRVShader spirv_shader{
|
const SPIRVShader spirv_shader{Decompile(device, shader->GetIR(), ShaderType::Compute,
|
||||||
Decompile(device, shader->GetIR(), ShaderType::Compute, specialization),
|
shader->GetRegistry(), specialization),
|
||||||
shader->GetEntries()};
|
shader->GetEntries()};
|
||||||
entry = std::make_unique<VKComputePipeline>(device, scheduler, descriptor_pool,
|
entry = std::make_unique<VKComputePipeline>(device, scheduler, descriptor_pool,
|
||||||
update_descriptor_queue, spirv_shader);
|
update_descriptor_queue, spirv_shader);
|
||||||
return *entry;
|
return *entry;
|
||||||
|
@ -324,8 +324,7 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) {
|
||||||
const auto& gpu = system.GPU().Maxwell3D();
|
const auto& gpu = system.GPU().Maxwell3D();
|
||||||
|
|
||||||
Specialization specialization;
|
Specialization specialization;
|
||||||
specialization.primitive_topology = fixed_state.input_assembly.topology;
|
if (fixed_state.input_assembly.topology == Maxwell::PrimitiveTopology::Points) {
|
||||||
if (specialization.primitive_topology == Maxwell::PrimitiveTopology::Points) {
|
|
||||||
ASSERT(fixed_state.input_assembly.point_size != 0.0f);
|
ASSERT(fixed_state.input_assembly.point_size != 0.0f);
|
||||||
specialization.point_size = fixed_state.input_assembly.point_size;
|
specialization.point_size = fixed_state.input_assembly.point_size;
|
||||||
}
|
}
|
||||||
|
@ -333,9 +332,6 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) {
|
||||||
specialization.attribute_types[i] = fixed_state.vertex_input.attributes[i].type;
|
specialization.attribute_types[i] = fixed_state.vertex_input.attributes[i].type;
|
||||||
}
|
}
|
||||||
specialization.ndc_minus_one_to_one = fixed_state.rasterizer.ndc_minus_one_to_one;
|
specialization.ndc_minus_one_to_one = fixed_state.rasterizer.ndc_minus_one_to_one;
|
||||||
specialization.tessellation.primitive = fixed_state.tessellation.primitive;
|
|
||||||
specialization.tessellation.spacing = fixed_state.tessellation.spacing;
|
|
||||||
specialization.tessellation.clockwise = fixed_state.tessellation.clockwise;
|
|
||||||
|
|
||||||
SPIRVProgram program;
|
SPIRVProgram program;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> bindings;
|
std::vector<vk::DescriptorSetLayoutBinding> bindings;
|
||||||
|
@ -356,8 +352,9 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) {
|
||||||
const std::size_t stage = index == 0 ? 0 : index - 1; // Stage indices are 0 - 5
|
const std::size_t stage = index == 0 ? 0 : index - 1; // Stage indices are 0 - 5
|
||||||
const auto program_type = GetShaderType(program_enum);
|
const auto program_type = GetShaderType(program_enum);
|
||||||
const auto& entries = shader->GetEntries();
|
const auto& entries = shader->GetEntries();
|
||||||
program[stage] = {Decompile(device, shader->GetIR(), program_type, specialization),
|
program[stage] = {
|
||||||
entries};
|
Decompile(device, shader->GetIR(), program_type, shader->GetRegistry(), specialization),
|
||||||
|
entries};
|
||||||
|
|
||||||
if (program_enum == Maxwell::ShaderProgram::VertexA) {
|
if (program_enum == Maxwell::ShaderProgram::VertexA) {
|
||||||
// VertexB was combined with VertexA, so we skip the VertexB iteration
|
// VertexB was combined with VertexA, so we skip the VertexB iteration
|
||||||
|
|
|
@ -132,6 +132,10 @@ public:
|
||||||
return shader_ir;
|
return shader_ir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const VideoCommon::Shader::Registry& GetRegistry() const {
|
||||||
|
return registry;
|
||||||
|
}
|
||||||
|
|
||||||
const VideoCommon::Shader::ShaderIR& GetIR() const {
|
const VideoCommon::Shader::ShaderIR& GetIR() const {
|
||||||
return shader_ir;
|
return shader_ir;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "video_core/renderer_vulkan/vk_shader_decompiler.h"
|
#include "video_core/renderer_vulkan/vk_shader_decompiler.h"
|
||||||
#include "video_core/shader/node.h"
|
#include "video_core/shader/node.h"
|
||||||
#include "video_core/shader/shader_ir.h"
|
#include "video_core/shader/shader_ir.h"
|
||||||
|
#include "video_core/shader/transform_feedback.h"
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
|
@ -266,9 +267,10 @@ bool IsPrecise(Operation operand) {
|
||||||
class SPIRVDecompiler final : public Sirit::Module {
|
class SPIRVDecompiler final : public Sirit::Module {
|
||||||
public:
|
public:
|
||||||
explicit SPIRVDecompiler(const VKDevice& device, const ShaderIR& ir, ShaderType stage,
|
explicit SPIRVDecompiler(const VKDevice& device, const ShaderIR& ir, ShaderType stage,
|
||||||
const Specialization& specialization)
|
const Registry& registry, const Specialization& specialization)
|
||||||
: Module(0x00010300), device{device}, ir{ir}, stage{stage}, header{ir.GetHeader()},
|
: Module(0x00010300), device{device}, ir{ir}, stage{stage}, header{ir.GetHeader()},
|
||||||
specialization{specialization} {
|
registry{registry}, specialization{specialization},
|
||||||
|
transform_feedback{BuildTransformFeedback(registry.GetGraphicsInfo())} {
|
||||||
AddCapability(spv::Capability::Shader);
|
AddCapability(spv::Capability::Shader);
|
||||||
AddCapability(spv::Capability::UniformAndStorageBuffer16BitAccess);
|
AddCapability(spv::Capability::UniformAndStorageBuffer16BitAccess);
|
||||||
AddCapability(spv::Capability::ImageQuery);
|
AddCapability(spv::Capability::ImageQuery);
|
||||||
|
@ -318,25 +320,29 @@ public:
|
||||||
AddExecutionMode(main, spv::ExecutionMode::OutputVertices,
|
AddExecutionMode(main, spv::ExecutionMode::OutputVertices,
|
||||||
header.common2.threads_per_input_primitive);
|
header.common2.threads_per_input_primitive);
|
||||||
break;
|
break;
|
||||||
case ShaderType::TesselationEval:
|
case ShaderType::TesselationEval: {
|
||||||
|
const auto& info = registry.GetGraphicsInfo();
|
||||||
AddCapability(spv::Capability::Tessellation);
|
AddCapability(spv::Capability::Tessellation);
|
||||||
AddEntryPoint(spv::ExecutionModel::TessellationEvaluation, main, "main", interfaces);
|
AddEntryPoint(spv::ExecutionModel::TessellationEvaluation, main, "main", interfaces);
|
||||||
AddExecutionMode(main, GetExecutionMode(specialization.tessellation.primitive));
|
AddExecutionMode(main, GetExecutionMode(info.tessellation_primitive));
|
||||||
AddExecutionMode(main, GetExecutionMode(specialization.tessellation.spacing));
|
AddExecutionMode(main, GetExecutionMode(info.tessellation_spacing));
|
||||||
AddExecutionMode(main, specialization.tessellation.clockwise
|
AddExecutionMode(main, info.tessellation_clockwise
|
||||||
? spv::ExecutionMode::VertexOrderCw
|
? spv::ExecutionMode::VertexOrderCw
|
||||||
: spv::ExecutionMode::VertexOrderCcw);
|
: spv::ExecutionMode::VertexOrderCcw);
|
||||||
break;
|
break;
|
||||||
case ShaderType::Geometry:
|
}
|
||||||
|
case ShaderType::Geometry: {
|
||||||
|
const auto& info = registry.GetGraphicsInfo();
|
||||||
AddCapability(spv::Capability::Geometry);
|
AddCapability(spv::Capability::Geometry);
|
||||||
AddEntryPoint(spv::ExecutionModel::Geometry, main, "main", interfaces);
|
AddEntryPoint(spv::ExecutionModel::Geometry, main, "main", interfaces);
|
||||||
AddExecutionMode(main, GetExecutionMode(specialization.primitive_topology));
|
AddExecutionMode(main, GetExecutionMode(info.primitive_topology));
|
||||||
AddExecutionMode(main, GetExecutionMode(header.common3.output_topology));
|
AddExecutionMode(main, GetExecutionMode(header.common3.output_topology));
|
||||||
AddExecutionMode(main, spv::ExecutionMode::OutputVertices,
|
AddExecutionMode(main, spv::ExecutionMode::OutputVertices,
|
||||||
header.common4.max_output_vertices);
|
header.common4.max_output_vertices);
|
||||||
// TODO(Rodrigo): Where can we get this info from?
|
// TODO(Rodrigo): Where can we get this info from?
|
||||||
AddExecutionMode(main, spv::ExecutionMode::Invocations, 1U);
|
AddExecutionMode(main, spv::ExecutionMode::Invocations, 1U);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case ShaderType::Fragment:
|
case ShaderType::Fragment:
|
||||||
AddEntryPoint(spv::ExecutionModel::Fragment, main, "main", interfaces);
|
AddEntryPoint(spv::ExecutionModel::Fragment, main, "main", interfaces);
|
||||||
AddExecutionMode(main, spv::ExecutionMode::OriginUpperLeft);
|
AddExecutionMode(main, spv::ExecutionMode::OriginUpperLeft);
|
||||||
|
@ -545,7 +551,8 @@ private:
|
||||||
if (stage != ShaderType::Geometry) {
|
if (stage != ShaderType::Geometry) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const u32 num_input = GetNumPrimitiveTopologyVertices(specialization.primitive_topology);
|
const auto& info = registry.GetGraphicsInfo();
|
||||||
|
const u32 num_input = GetNumPrimitiveTopologyVertices(info.primitive_topology);
|
||||||
DeclareInputVertexArray(num_input);
|
DeclareInputVertexArray(num_input);
|
||||||
DeclareOutputVertex();
|
DeclareOutputVertex();
|
||||||
}
|
}
|
||||||
|
@ -898,7 +905,7 @@ private:
|
||||||
u32 GetNumInputVertices() const {
|
u32 GetNumInputVertices() const {
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case ShaderType::Geometry:
|
case ShaderType::Geometry:
|
||||||
return GetNumPrimitiveTopologyVertices(specialization.primitive_topology);
|
return GetNumPrimitiveTopologyVertices(registry.GetGraphicsInfo().primitive_topology);
|
||||||
case ShaderType::TesselationControl:
|
case ShaderType::TesselationControl:
|
||||||
case ShaderType::TesselationEval:
|
case ShaderType::TesselationEval:
|
||||||
return NumInputPatches;
|
return NumInputPatches;
|
||||||
|
@ -2495,7 +2502,9 @@ private:
|
||||||
const ShaderIR& ir;
|
const ShaderIR& ir;
|
||||||
const ShaderType stage;
|
const ShaderType stage;
|
||||||
const Tegra::Shader::Header header;
|
const Tegra::Shader::Header header;
|
||||||
|
const Registry& registry;
|
||||||
const Specialization& specialization;
|
const Specialization& specialization;
|
||||||
|
const std::unordered_map<u8, VaryingTFB> transform_feedback;
|
||||||
|
|
||||||
const Id t_void = Name(TypeVoid(), "void");
|
const Id t_void = Name(TypeVoid(), "void");
|
||||||
|
|
||||||
|
@ -2870,8 +2879,9 @@ ShaderEntries GenerateShaderEntries(const VideoCommon::Shader::ShaderIR& ir) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u32> Decompile(const VKDevice& device, const VideoCommon::Shader::ShaderIR& ir,
|
std::vector<u32> Decompile(const VKDevice& device, const VideoCommon::Shader::ShaderIR& ir,
|
||||||
ShaderType stage, const Specialization& specialization) {
|
ShaderType stage, const VideoCommon::Shader::Registry& registry,
|
||||||
return SPIRVDecompiler(device, ir, stage, specialization).Assemble();
|
const Specialization& specialization) {
|
||||||
|
return SPIRVDecompiler(device, ir, stage, registry, specialization).Assemble();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/engines/shader_type.h"
|
#include "video_core/engines/shader_type.h"
|
||||||
|
#include "video_core/shader/registry.h"
|
||||||
#include "video_core/shader/shader_ir.h"
|
#include "video_core/shader/shader_ir.h"
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
@ -91,17 +92,9 @@ struct Specialization final {
|
||||||
u32 shared_memory_size{};
|
u32 shared_memory_size{};
|
||||||
|
|
||||||
// Graphics specific
|
// Graphics specific
|
||||||
Maxwell::PrimitiveTopology primitive_topology{};
|
|
||||||
std::optional<float> point_size{};
|
std::optional<float> point_size{};
|
||||||
std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{};
|
std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{};
|
||||||
bool ndc_minus_one_to_one{};
|
bool ndc_minus_one_to_one{};
|
||||||
|
|
||||||
// Tessellation specific
|
|
||||||
struct {
|
|
||||||
Maxwell::TessellationPrimitive primitive{};
|
|
||||||
Maxwell::TessellationSpacing spacing{};
|
|
||||||
bool clockwise{};
|
|
||||||
} tessellation;
|
|
||||||
};
|
};
|
||||||
// Old gcc versions don't consider this trivially copyable.
|
// Old gcc versions don't consider this trivially copyable.
|
||||||
// static_assert(std::is_trivially_copyable_v<Specialization>);
|
// static_assert(std::is_trivially_copyable_v<Specialization>);
|
||||||
|
@ -114,6 +107,8 @@ struct SPIRVShader {
|
||||||
ShaderEntries GenerateShaderEntries(const VideoCommon::Shader::ShaderIR& ir);
|
ShaderEntries GenerateShaderEntries(const VideoCommon::Shader::ShaderIR& ir);
|
||||||
|
|
||||||
std::vector<u32> Decompile(const VKDevice& device, const VideoCommon::Shader::ShaderIR& ir,
|
std::vector<u32> Decompile(const VKDevice& device, const VideoCommon::Shader::ShaderIR& ir,
|
||||||
Tegra::Engines::ShaderType stage, const Specialization& specialization);
|
Tegra::Engines::ShaderType stage,
|
||||||
|
const VideoCommon::Shader::Registry& registry,
|
||||||
|
const Specialization& specialization);
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
Loading…
Reference in a new issue