mirror of
https://github.com/par274/sharpemu.git
synced 2026-08-01 07:29:43 +08:00
52e17b5056
* [shader-decoder-part1] Implemented a shader decoder for Gen5 shaders, including IR generation, metadata reading, scalar evaluation, and SPIR-V translation. Updated related exports and video output components to support the new shader decoding functionality. * [shader decoder] correct RDNA2 operands, fixing synchronization problems * [shader-decoder] RDNA2 decoder improvements * [shader-decoder] fix RDNA2 shift masking and sprite draws * [shader-decoder] improve RDNA2 shader decoder to support more instructions and fix some issues with the previous implementation.
168 lines
6.8 KiB
C#
168 lines
6.8 KiB
C#
// Copyright (C) 2026 SharpEmu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
namespace SharpEmu.Libs.Agc;
|
|
|
|
internal static class SpirvFixedShaders
|
|
{
|
|
public static byte[] CreateFullscreenVertex(uint attributeCount)
|
|
{
|
|
var module = new SpirvModuleBuilder();
|
|
module.AddCapability(SpirvCapability.Shader);
|
|
|
|
var voidType = module.TypeVoid();
|
|
var boolType = module.TypeBool();
|
|
var uintType = module.TypeInt(32, signed: false);
|
|
var floatType = module.TypeFloat(32);
|
|
var vec4Type = module.TypeVector(floatType, 4);
|
|
var inputUintPointer = module.TypePointer(SpirvStorageClass.Input, uintType);
|
|
var outputVec4Pointer = module.TypePointer(SpirvStorageClass.Output, vec4Type);
|
|
|
|
var vertexIndex = module.AddGlobalVariable(inputUintPointer, SpirvStorageClass.Input);
|
|
module.AddName(vertexIndex, "vertexIndex");
|
|
module.AddDecoration(
|
|
vertexIndex,
|
|
SpirvDecoration.BuiltIn,
|
|
(uint)SpirvBuiltIn.VertexIndex);
|
|
|
|
var position = module.AddGlobalVariable(outputVec4Pointer, SpirvStorageClass.Output);
|
|
module.AddName(position, "position");
|
|
module.AddDecoration(position, SpirvDecoration.BuiltIn, (uint)SpirvBuiltIn.Position);
|
|
|
|
var attributes = new uint[attributeCount];
|
|
for (uint index = 0; index < attributeCount; index++)
|
|
{
|
|
attributes[index] =
|
|
module.AddGlobalVariable(outputVec4Pointer, SpirvStorageClass.Output);
|
|
module.AddName(attributes[index], $"attr{index}");
|
|
module.AddDecoration(attributes[index], SpirvDecoration.Location, index);
|
|
module.AddDecoration(attributes[index], SpirvDecoration.NoPerspective);
|
|
}
|
|
|
|
var functionType = module.TypeFunction(voidType);
|
|
var main = module.BeginFunction(voidType, functionType);
|
|
module.AddName(main, "main");
|
|
module.AddLabel();
|
|
|
|
var indexValue = module.AddInstruction(SpirvOp.Load, uintType, vertexIndex);
|
|
var one = module.Constant(uintType, 1);
|
|
var two = module.Constant(uintType, 2);
|
|
var shifted = module.AddInstruction(SpirvOp.ShiftLeftLogical, uintType, indexValue, one);
|
|
var xBits = module.AddInstruction(SpirvOp.BitwiseAnd, uintType, shifted, two);
|
|
var yBits = module.AddInstruction(SpirvOp.BitwiseAnd, uintType, indexValue, two);
|
|
var x = module.AddInstruction(SpirvOp.ConvertUToF, floatType, xBits);
|
|
var y = module.AddInstruction(SpirvOp.ConvertUToF, floatType, yBits);
|
|
var zero = module.ConstantFloat(floatType, 0f);
|
|
var oneFloat = module.ConstantFloat(floatType, 1f);
|
|
var twoFloat = module.ConstantFloat(floatType, 2f);
|
|
var xPosition = module.AddInstruction(SpirvOp.FMul, floatType, x, twoFloat);
|
|
xPosition = module.AddInstruction(SpirvOp.FSub, floatType, xPosition, oneFloat);
|
|
var yPosition = module.AddInstruction(SpirvOp.FMul, floatType, y, twoFloat);
|
|
yPosition = module.AddInstruction(SpirvOp.FSub, floatType, yPosition, oneFloat);
|
|
var positionValue = module.AddInstruction(
|
|
SpirvOp.CompositeConstruct,
|
|
vec4Type,
|
|
xPosition,
|
|
yPosition,
|
|
zero,
|
|
oneFloat);
|
|
module.AddStatement(SpirvOp.Store, position, positionValue);
|
|
|
|
var attributeValue = module.AddInstruction(
|
|
SpirvOp.CompositeConstruct,
|
|
vec4Type,
|
|
x,
|
|
y,
|
|
zero,
|
|
oneFloat);
|
|
foreach (var attribute in attributes)
|
|
{
|
|
module.AddStatement(SpirvOp.Store, attribute, attributeValue);
|
|
}
|
|
|
|
module.AddStatement(SpirvOp.Return);
|
|
module.EndFunction();
|
|
|
|
var interfaces = new uint[2 + attributes.Length];
|
|
interfaces[0] = vertexIndex;
|
|
interfaces[1] = position;
|
|
attributes.CopyTo(interfaces, 2);
|
|
module.AddEntryPoint(SpirvExecutionModel.Vertex, main, "main", interfaces);
|
|
_ = boolType;
|
|
return module.Build();
|
|
}
|
|
|
|
public static byte[] CreateCopyFragment()
|
|
{
|
|
var module = new SpirvModuleBuilder();
|
|
module.AddCapability(SpirvCapability.Shader);
|
|
|
|
var voidType = module.TypeVoid();
|
|
var floatType = module.TypeFloat(32);
|
|
var vec2Type = module.TypeVector(floatType, 2);
|
|
var vec4Type = module.TypeVector(floatType, 4);
|
|
var inputVec4Pointer = module.TypePointer(SpirvStorageClass.Input, vec4Type);
|
|
var outputVec4Pointer = module.TypePointer(SpirvStorageClass.Output, vec4Type);
|
|
var imageType = module.TypeImage(
|
|
floatType,
|
|
SpirvImageDim.Dim2D,
|
|
depth: false,
|
|
arrayed: false,
|
|
multisampled: false,
|
|
sampled: 1,
|
|
SpirvImageFormat.Unknown);
|
|
var sampledImageType = module.TypeSampledImage(imageType);
|
|
var sampledImagePointer =
|
|
module.TypePointer(SpirvStorageClass.UniformConstant, sampledImageType);
|
|
|
|
var attribute = module.AddGlobalVariable(inputVec4Pointer, SpirvStorageClass.Input);
|
|
module.AddName(attribute, "attr0");
|
|
module.AddDecoration(attribute, SpirvDecoration.Location, 0);
|
|
|
|
var texture = module.AddGlobalVariable(
|
|
sampledImagePointer,
|
|
SpirvStorageClass.UniformConstant);
|
|
module.AddName(texture, "tex0");
|
|
module.AddDecoration(texture, SpirvDecoration.DescriptorSet, 0);
|
|
module.AddDecoration(texture, SpirvDecoration.Binding, 1);
|
|
|
|
var output = module.AddGlobalVariable(outputVec4Pointer, SpirvStorageClass.Output);
|
|
module.AddName(output, "outColor");
|
|
module.AddDecoration(output, SpirvDecoration.Location, 0);
|
|
|
|
var functionType = module.TypeFunction(voidType);
|
|
var main = module.BeginFunction(voidType, functionType);
|
|
module.AddName(main, "main");
|
|
module.AddLabel();
|
|
|
|
var attributeValue = module.AddInstruction(SpirvOp.Load, vec4Type, attribute);
|
|
var coordinates = module.AddInstruction(
|
|
SpirvOp.VectorShuffle,
|
|
vec2Type,
|
|
attributeValue,
|
|
attributeValue,
|
|
0,
|
|
1);
|
|
var sampledImage = module.AddInstruction(SpirvOp.Load, sampledImageType, texture);
|
|
var lod = module.ConstantFloat(floatType, 0f);
|
|
var color = module.AddInstruction(
|
|
SpirvOp.ImageSampleExplicitLod,
|
|
vec4Type,
|
|
sampledImage,
|
|
coordinates,
|
|
2,
|
|
lod);
|
|
module.AddStatement(SpirvOp.Store, output, color);
|
|
module.AddStatement(SpirvOp.Return);
|
|
module.EndFunction();
|
|
|
|
module.AddEntryPoint(
|
|
SpirvExecutionModel.Fragment,
|
|
main,
|
|
"main",
|
|
[attribute, texture, output]);
|
|
module.AddExecutionMode(main, SpirvExecutionMode.OriginUpperLeft);
|
|
return module.Build();
|
|
}
|
|
}
|