Compare commits

...

2 Commits

Author SHA1 Message Date
gdkchan
61b1ce252f Allow partially mapped textures with unmapped start (#4394) 2023-02-10 11:47:59 -03:00
gdkchan
5f38086f94 Fix SPIR-V when all inputs/outputs are indexed (#4389) 2023-02-09 04:48:25 +01:00
3 changed files with 104 additions and 63 deletions

View File

@@ -474,6 +474,13 @@ namespace Ryujinx.Graphics.Gpu.Image
{ {
address = memoryManager.Translate(info.GpuAddress); address = memoryManager.Translate(info.GpuAddress);
// If the start address is unmapped, let's try to find a page of memory that is mapped.
if (address == MemoryManager.PteUnmapped)
{
address = memoryManager.TranslateFirstMapped(info.GpuAddress, (ulong)info.CalculateSizeInfo(layerSize).TotalSize);
}
// If address is still invalid, the texture is fully unmapped, so it has no data, just return null.
if (address == MemoryManager.PteUnmapped) if (address == MemoryManager.PteUnmapped)
{ {
return null; return null;

View File

@@ -583,6 +583,38 @@ namespace Ryujinx.Graphics.Gpu.Memory
return UnpackPaFromPte(pte) + (va & PageMask); return UnpackPaFromPte(pte) + (va & PageMask);
} }
/// <summary>
/// Translates a GPU virtual address to a CPU virtual address on the first mapped page of memory
/// on the specified region.
/// If no page is mapped on the specified region, <see cref="PteUnmapped"/> is returned.
/// </summary>
/// <param name="va">GPU virtual address to be translated</param>
/// <param name="size">Size of the range to be translated</param>
/// <returns>CPU virtual address, or <see cref="PteUnmapped"/> if unmapped</returns>
public ulong TranslateFirstMapped(ulong va, ulong size)
{
if (!ValidateAddress(va))
{
return PteUnmapped;
}
ulong endVa = va + size;
ulong pte = GetPte(va);
for (; va < endVa && pte == PteUnmapped; va += PageSize - (va & PageMask))
{
pte = GetPte(va);
}
if (pte == PteUnmapped)
{
return PteUnmapped;
}
return UnpackPaFromPte(pte) + (va & PageMask);
}
/// <summary> /// <summary>
/// Gets the kind of a given memory page. /// Gets the kind of a given memory page.
/// This might indicate the type of resource that can be allocated on the page, and also texture tiling. /// This might indicate the type of resource that can be allocated on the page, and also texture tiling.

View File

@@ -397,20 +397,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static void DeclareInputAttributes(CodeGenContext context, StructuredProgramInfo info, bool perPatch) private static void DeclareInputAttributes(CodeGenContext context, StructuredProgramInfo info, bool perPatch)
{ {
bool iaIndexing = context.Config.UsedFeatures.HasFlag(FeatureFlags.IaIndexing); bool iaIndexing = context.Config.UsedFeatures.HasFlag(FeatureFlags.IaIndexing);
var inputs = perPatch ? info.InputsPerPatch : info.Inputs;
foreach (int attr in inputs) if (iaIndexing && !perPatch)
{
if (!AttributeInfo.Validate(context.Config, attr, isOutAttr: false, perPatch))
{
continue;
}
bool isUserAttr = attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd;
if (iaIndexing && isUserAttr && !perPatch)
{
if (context.InputsArray == null)
{ {
var attrType = context.TypeVector(context.TypeFP32(), (LiteralInteger)4); var attrType = context.TypeVector(context.TypeFP32(), (LiteralInteger)4);
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)MaxAttributes)); attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)MaxAttributes));
@@ -433,9 +421,23 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
context.AddGlobalVariable(spvVar); context.AddGlobalVariable(spvVar);
context.InputsArray = spvVar; context.InputsArray = spvVar;
} }
}
else var inputs = perPatch ? info.InputsPerPatch : info.Inputs;
foreach (int attr in inputs)
{ {
if (!AttributeInfo.Validate(context.Config, attr, isOutAttr: false, perPatch))
{
continue;
}
bool isUserAttr = attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd;
if (iaIndexing && isUserAttr && !perPatch)
{
continue;
}
PixelImap iq = PixelImap.Unused; PixelImap iq = PixelImap.Unused;
if (context.Config.Stage == ShaderStage.Fragment) if (context.Config.Stage == ShaderStage.Fragment)
@@ -459,25 +461,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
DeclareInputOrOutput(context, attr, perPatch, isOutAttr: false, iq); DeclareInputOrOutput(context, attr, perPatch, isOutAttr: false, iq);
} }
} }
}
private static void DeclareOutputAttributes(CodeGenContext context, StructuredProgramInfo info, bool perPatch) private static void DeclareOutputAttributes(CodeGenContext context, StructuredProgramInfo info, bool perPatch)
{ {
bool oaIndexing = context.Config.UsedFeatures.HasFlag(FeatureFlags.OaIndexing); bool oaIndexing = context.Config.UsedFeatures.HasFlag(FeatureFlags.OaIndexing);
var outputs = perPatch ? info.OutputsPerPatch : info.Outputs;
foreach (int attr in outputs) if (oaIndexing && !perPatch)
{
if (!AttributeInfo.Validate(context.Config, attr, isOutAttr: true, perPatch))
{
continue;
}
bool isUserAttr = attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd;
if (oaIndexing && isUserAttr && !perPatch)
{
if (context.OutputsArray == null)
{ {
var attrType = context.TypeVector(context.TypeFP32(), (LiteralInteger)4); var attrType = context.TypeVector(context.TypeFP32(), (LiteralInteger)4);
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)MaxAttributes)); attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)MaxAttributes));
@@ -495,11 +484,24 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
context.AddGlobalVariable(spvVar); context.AddGlobalVariable(spvVar);
context.OutputsArray = spvVar; context.OutputsArray = spvVar;
} }
}
else var outputs = perPatch ? info.OutputsPerPatch : info.Outputs;
foreach (int attr in outputs)
{ {
DeclareOutputAttribute(context, attr, perPatch); if (!AttributeInfo.Validate(context.Config, attr, isOutAttr: true, perPatch))
{
continue;
} }
bool isUserAttr = attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd;
if (oaIndexing && isUserAttr && !perPatch)
{
continue;
}
DeclareOutputAttribute(context, attr, perPatch);
} }
if (context.Config.Stage == ShaderStage.Vertex) if (context.Config.Stage == ShaderStage.Vertex)