private void UploadConstBuffers(NvGpuVmm vmm, GalPipelineState state, long[] keys) { Profile.Begin(Profiles.GPU.Engine3d.UploadConstBuffers); for (int stage = 0; stage < keys.Length; stage++) { foreach (CBufferDescriptor desc in _gpu.Renderer.Shader.GetConstBufferUsage(keys[stage])) { ConstBuffer cb = _constBuffers[stage][desc.Slot]; if (!cb.Enabled) { continue; } long key = vmm.GetPhysicalAddress(cb.Position); if (_gpu.ResourceManager.MemoryRegionModified(vmm, key, cb.Size, NvGpuBufferType.ConstBuffer)) { if (vmm.TryGetHostAddress(cb.Position, cb.Size, out IntPtr cbPtr)) { _gpu.Renderer.Buffer.SetData(key, cb.Size, cbPtr); } else { _gpu.Renderer.Buffer.SetData(key, vmm.ReadBytes(cb.Position, cb.Size)); } } state.ConstBufferKeys[stage][desc.Slot] = key; } } Profile.End(Profiles.GPU.Engine3d.UploadConstBuffers); }
private static int SubmitGpfifo(ServiceCtx Context) { long InputPosition = Context.Request.GetBufferType0x21Position(); long OutputPosition = Context.Request.GetBufferType0x22Position(); NvHostChannelSubmitGpfifo Args = AMemoryHelper.Read <NvHostChannelSubmitGpfifo>(Context.Memory, InputPosition); NvGpuVmm Vmm = NvGpuASIoctl.GetVmm(Context); for (int Index = 0; Index < Args.NumEntries; Index++) { long Gpfifo = Context.Memory.ReadInt64(InputPosition + 0x18 + Index * 8); long VA = Gpfifo & 0xff_ffff_ffff; int Size = (int)(Gpfifo >> 40) & 0x7ffffc; byte[] Data = Vmm.ReadBytes(VA, Size); NvGpuPBEntry[] PushBuffer = NvGpuPushBuffer.Decode(Data); Context.Ns.Gpu.Fifo.PushBuffer(Vmm, PushBuffer); } Args.SyncptId = 0; Args.SyncptValue = 0; AMemoryHelper.Write(Context.Memory, OutputPosition, Args); return(NvResult.Success); }
private void UploadConstBuffers(NvGpuVmm Vmm, GalPipelineState State, long[] Keys) { for (int Stage = 0; Stage < Keys.Length; Stage++) { foreach (ShaderDeclInfo DeclInfo in Gpu.Renderer.Shader.GetConstBufferUsage(Keys[Stage])) { ConstBuffer Cb = ConstBuffers[Stage][DeclInfo.Cbuf]; if (!Cb.Enabled) { continue; } long Key = Vmm.GetPhysicalAddress(Cb.Position); if (Gpu.ResourceManager.MemoryRegionModified(Vmm, Key, Cb.Size, NvGpuBufferType.ConstBuffer)) { if (Vmm.TryGetHostAddress(Cb.Position, Cb.Size, out IntPtr CbPtr)) { Gpu.Renderer.Buffer.SetData(Key, Cb.Size, CbPtr); } else { Gpu.Renderer.Buffer.SetData(Key, Vmm.ReadBytes(Cb.Position, Cb.Size)); } } State.ConstBufferKeys[Stage][DeclInfo.Cbuf] = Key; } } }
private void UploadUniforms(NvGpuVmm Vmm) { long BasePosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress); for (int Index = 0; Index < 5; Index++) { int Control = ReadRegister(NvGpuEngine3dReg.ShaderNControl + (Index + 1) * 0x10); int Offset = ReadRegister(NvGpuEngine3dReg.ShaderNOffset + (Index + 1) * 0x10); //Note: Vertex Program (B) is always enabled. bool Enable = (Control & 1) != 0 || Index == 0; if (!Enable) { continue; } for (int Cbuf = 0; Cbuf < ConstBuffers[Index].Length; Cbuf++) { ConstBuffer Cb = ConstBuffers[Index][Cbuf]; if (Cb.Enabled) { byte[] Data = Vmm.ReadBytes(Cb.Position, (uint)Cb.Size); Gpu.Renderer.Shader.SetConstBuffer(BasePosition + (uint)Offset, Cbuf, Data); } } } }
private byte[] ReadShaderBinary(NvGpuVmm Vmm, long Key) { long Size = GetShaderSize(Vmm, Key); long Address = Vmm.GetPhysicalAddress(Key); return(Vmm.ReadBytes(Key, Size)); }
private static void PushGpfifo(ServiceCtx Context, NvGpuVmm Vmm, long Gpfifo) { long VA = Gpfifo & 0xff_ffff_ffff; int Size = (int)(Gpfifo >> 40) & 0x7ffffc; byte[] Data = Vmm.ReadBytes(VA, Size); NvGpuPBEntry[] PushBuffer = NvGpuPushBuffer.Decode(Data); Context.Device.Gpu.Fifo.PushBuffer(Vmm, PushBuffer); }
public static bool CopyTexture( NvGpuVmm Vmm, GalImage SrcImage, GalImage DstImage, long SrcAddress, long DstAddress, int SrcX, int SrcY, int DstX, int DstY, int Width, int Height) { ISwizzle SrcSwizzle = TextureHelper.GetSwizzle(SrcImage); ISwizzle DstSwizzle = TextureHelper.GetSwizzle(DstImage); ImageDescriptor Desc = GetImageDescriptor(SrcImage.Format); if (GetImageDescriptor(DstImage.Format).BytesPerPixel != Desc.BytesPerPixel) { return(false); } int BytesPerPixel = Desc.BytesPerPixel; for (int Y = 0; Y < Height; Y++) { for (int X = 0; X < Width; X++) { long SrcOffset = (uint)SrcSwizzle.GetSwizzleOffset(SrcX + X, SrcY + Y); long DstOffset = (uint)DstSwizzle.GetSwizzleOffset(DstX + X, DstY + Y); byte[] Texel = Vmm.ReadBytes(SrcAddress + SrcOffset, BytesPerPixel); Vmm.WriteBytes(DstAddress + DstOffset, Texel); } } return(true); }
// TODO: Support non 2D public static bool CopyTexture( NvGpuVmm vmm, GalImage srcImage, GalImage dstImage, long srcAddress, long dstAddress, int srcX, int srcY, int dstX, int dstY, int width, int height) { ISwizzle srcSwizzle = TextureHelper.GetSwizzle(srcImage); ISwizzle dstSwizzle = TextureHelper.GetSwizzle(dstImage); ImageDescriptor desc = GetImageDescriptor(srcImage.Format); if (GetImageDescriptor(dstImage.Format).BytesPerPixel != desc.BytesPerPixel) { return(false); } int bytesPerPixel = desc.BytesPerPixel; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { long srcOffset = (uint)srcSwizzle.GetSwizzleOffset(srcX + x, srcY + y, 0); long dstOffset = (uint)dstSwizzle.GetSwizzleOffset(dstX + x, dstY + y, 0); byte[] texel = vmm.ReadBytes(srcAddress + srcOffset, bytesPerPixel); vmm.WriteBytes(dstAddress + dstOffset, texel); } } return(true); }
private void UploadVertexArrays(NvGpuVmm vmm, GalPipelineState state) { Profile.Begin(Profiles.GPU.Engine3d.UploadVertexArrays); long ibPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress); long iboKey = vmm.GetPhysicalAddress(ibPosition); int indexEntryFmt = ReadRegister(NvGpuEngine3dReg.IndexArrayFormat); int indexCount = ReadRegister(NvGpuEngine3dReg.IndexBatchCount); int primCtrl = ReadRegister(NvGpuEngine3dReg.VertexBeginGl); GalPrimitiveType primType = (GalPrimitiveType)(primCtrl & 0xffff); GalIndexFormat indexFormat = (GalIndexFormat)indexEntryFmt; int indexEntrySize = 1 << indexEntryFmt; if (indexEntrySize > 4) { throw new InvalidOperationException("Invalid index entry size \"" + indexEntrySize + "\"!"); } if (indexCount != 0) { int ibSize = indexCount * indexEntrySize; bool iboCached = _gpu.Renderer.Rasterizer.IsIboCached(iboKey, (uint)ibSize); bool usesLegacyQuads = primType == GalPrimitiveType.Quads || primType == GalPrimitiveType.QuadStrip; if (!iboCached || _gpu.ResourceManager.MemoryRegionModified(vmm, iboKey, (uint)ibSize, NvGpuBufferType.Index)) { if (!usesLegacyQuads) { if (vmm.TryGetHostAddress(ibPosition, ibSize, out IntPtr ibPtr)) { _gpu.Renderer.Rasterizer.CreateIbo(iboKey, ibSize, ibPtr); } else { _gpu.Renderer.Rasterizer.CreateIbo(iboKey, ibSize, vmm.ReadBytes(ibPosition, ibSize)); } } else { byte[] buffer = vmm.ReadBytes(ibPosition, ibSize); if (primType == GalPrimitiveType.Quads) { buffer = QuadHelper.ConvertQuadsToTris(buffer, indexEntrySize, indexCount); } else /* if (PrimType == GalPrimitiveType.QuadStrip) */ { buffer = QuadHelper.ConvertQuadStripToTris(buffer, indexEntrySize, indexCount); } _gpu.Renderer.Rasterizer.CreateIbo(iboKey, ibSize, buffer); } } if (!usesLegacyQuads) { _gpu.Renderer.Rasterizer.SetIndexArray(ibSize, indexFormat); } else { if (primType == GalPrimitiveType.Quads) { _gpu.Renderer.Rasterizer.SetIndexArray(QuadHelper.ConvertSizeQuadsToTris(ibSize), indexFormat); } else /* if (PrimType == GalPrimitiveType.QuadStrip) */ { _gpu.Renderer.Rasterizer.SetIndexArray(QuadHelper.ConvertSizeQuadStripToTris(ibSize), indexFormat); } } } List <GalVertexAttrib>[] attribs = new List <GalVertexAttrib> [32]; for (int attr = 0; attr < 16; attr++) { int packed = ReadRegister(NvGpuEngine3dReg.VertexAttribNFormat + attr); int arrayIndex = packed & 0x1f; if (attribs[arrayIndex] == null) { attribs[arrayIndex] = new List <GalVertexAttrib>(); } long vbPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + arrayIndex * 4); if (vbPosition == 0) { continue; } bool isConst = ((packed >> 6) & 1) != 0; int offset = (packed >> 7) & 0x3fff; GalVertexAttribSize size = (GalVertexAttribSize)((packed >> 21) & 0x3f); GalVertexAttribType type = (GalVertexAttribType)((packed >> 27) & 0x7); bool isRgba = ((packed >> 31) & 1) != 0; // Check vertex array is enabled to avoid out of bounds exception when reading bytes bool enable = (ReadRegister(NvGpuEngine3dReg.VertexArrayNControl + arrayIndex * 4) & 0x1000) != 0; // Note: 16 is the maximum size of an attribute, // having a component size of 32-bits with 4 elements (a vec4). if (enable) { byte[] data = vmm.ReadBytes(vbPosition + offset, 16); attribs[arrayIndex].Add(new GalVertexAttrib(attr, isConst, offset, data, size, type, isRgba)); } } state.VertexBindings = new GalVertexBinding[32]; for (int index = 0; index < 32; index++) { if (attribs[index] == null) { continue; } int control = ReadRegister(NvGpuEngine3dReg.VertexArrayNControl + index * 4); bool enable = (control & 0x1000) != 0; if (!enable) { continue; } long vbPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + index * 4); long vbEndPos = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNEndAddr + index * 2); int vertexDivisor = ReadRegister(NvGpuEngine3dReg.VertexArrayNDivisor + index * 4); bool instanced = ReadRegisterBool(NvGpuEngine3dReg.VertexArrayNInstance + index); int stride = control & 0xfff; if (instanced && vertexDivisor != 0) { vbPosition += stride * (_currentInstance / vertexDivisor); } if (vbPosition > vbEndPos) { // Instance is invalid, ignore the draw call continue; } long vboKey = vmm.GetPhysicalAddress(vbPosition); long vbSize = (vbEndPos - vbPosition) + 1; int modifiedVbSize = (int)vbSize; // If quads convert size to triangle length if (stride == 0) { if (primType == GalPrimitiveType.Quads) { modifiedVbSize = QuadHelper.ConvertSizeQuadsToTris(modifiedVbSize); } else if (primType == GalPrimitiveType.QuadStrip) { modifiedVbSize = QuadHelper.ConvertSizeQuadStripToTris(modifiedVbSize); } } bool vboCached = _gpu.Renderer.Rasterizer.IsVboCached(vboKey, modifiedVbSize); if (!vboCached || _gpu.ResourceManager.MemoryRegionModified(vmm, vboKey, vbSize, NvGpuBufferType.Vertex)) { if ((primType == GalPrimitiveType.Quads | primType == GalPrimitiveType.QuadStrip) && stride != 0) { // Convert quad buffer to triangles byte[] data = vmm.ReadBytes(vbPosition, vbSize); if (primType == GalPrimitiveType.Quads) { data = QuadHelper.ConvertQuadsToTris(data, stride, (int)(vbSize / stride)); } else { data = QuadHelper.ConvertQuadStripToTris(data, stride, (int)(vbSize / stride)); } _gpu.Renderer.Rasterizer.CreateVbo(vboKey, data); } else if (vmm.TryGetHostAddress(vbPosition, vbSize, out IntPtr vbPtr)) { _gpu.Renderer.Rasterizer.CreateVbo(vboKey, (int)vbSize, vbPtr); } else { _gpu.Renderer.Rasterizer.CreateVbo(vboKey, vmm.ReadBytes(vbPosition, vbSize)); } } state.VertexBindings[index].Enabled = true; state.VertexBindings[index].Stride = stride; state.VertexBindings[index].VboKey = vboKey; state.VertexBindings[index].Instanced = instanced; state.VertexBindings[index].Divisor = vertexDivisor; state.VertexBindings[index].Attribs = attribs[index].ToArray(); } Profile.End(Profiles.GPU.Engine3d.UploadVertexArrays); }
private void UploadVertexArrays(NvGpuVmm Vmm, GalPipelineState State) { long IbPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress); long IboKey = Vmm.GetPhysicalAddress(IbPosition); int IndexEntryFmt = ReadRegister(NvGpuEngine3dReg.IndexArrayFormat); int IndexCount = ReadRegister(NvGpuEngine3dReg.IndexBatchCount); int PrimCtrl = ReadRegister(NvGpuEngine3dReg.VertexBeginGl); GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff); GalIndexFormat IndexFormat = (GalIndexFormat)IndexEntryFmt; int IndexEntrySize = 1 << IndexEntryFmt; if (IndexEntrySize > 4) { throw new InvalidOperationException("Invalid index entry size \"" + IndexEntrySize + "\"!"); } if (IndexCount != 0) { int IbSize = IndexCount * IndexEntrySize; bool IboCached = Gpu.Renderer.Rasterizer.IsIboCached(IboKey, (uint)IbSize); bool UsesLegacyQuads = PrimType == GalPrimitiveType.Quads || PrimType == GalPrimitiveType.QuadStrip; if (!IboCached || Gpu.ResourceManager.MemoryRegionModified(Vmm, IboKey, (uint)IbSize, NvGpuBufferType.Index)) { if (!UsesLegacyQuads) { if (Vmm.TryGetHostAddress(IbPosition, IbSize, out IntPtr IbPtr)) { Gpu.Renderer.Rasterizer.CreateIbo(IboKey, IbSize, IbPtr); } else { Gpu.Renderer.Rasterizer.CreateIbo(IboKey, IbSize, Vmm.ReadBytes(IbPosition, IbSize)); } } else { byte[] Buffer = Vmm.ReadBytes(IbPosition, IbSize); if (PrimType == GalPrimitiveType.Quads) { Buffer = QuadHelper.ConvertIbQuadsToTris(Buffer, IndexEntrySize, IndexCount); } else /* if (PrimType == GalPrimitiveType.QuadStrip) */ { Buffer = QuadHelper.ConvertIbQuadStripToTris(Buffer, IndexEntrySize, IndexCount); } Gpu.Renderer.Rasterizer.CreateIbo(IboKey, IbSize, Buffer); } } if (!UsesLegacyQuads) { Gpu.Renderer.Rasterizer.SetIndexArray(IbSize, IndexFormat); } else { if (PrimType == GalPrimitiveType.Quads) { Gpu.Renderer.Rasterizer.SetIndexArray(QuadHelper.ConvertIbSizeQuadsToTris(IbSize), IndexFormat); } else /* if (PrimType == GalPrimitiveType.QuadStrip) */ { Gpu.Renderer.Rasterizer.SetIndexArray(QuadHelper.ConvertIbSizeQuadStripToTris(IbSize), IndexFormat); } } } List <GalVertexAttrib>[] Attribs = new List <GalVertexAttrib> [32]; for (int Attr = 0; Attr < 16; Attr++) { int Packed = ReadRegister(NvGpuEngine3dReg.VertexAttribNFormat + Attr); int ArrayIndex = Packed & 0x1f; if (Attribs[ArrayIndex] == null) { Attribs[ArrayIndex] = new List <GalVertexAttrib>(); } long VbPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + ArrayIndex * 4); if (VbPosition == 0) { continue; } bool IsConst = ((Packed >> 6) & 1) != 0; int Offset = (Packed >> 7) & 0x3fff; GalVertexAttribSize Size = (GalVertexAttribSize)((Packed >> 21) & 0x3f); GalVertexAttribType Type = (GalVertexAttribType)((Packed >> 27) & 0x7); bool IsRgba = ((Packed >> 31) & 1) != 0; //Note: 16 is the maximum size of an attribute, //having a component size of 32-bits with 4 elements (a vec4). byte[] Data = Vmm.ReadBytes(VbPosition + Offset, 16); Attribs[ArrayIndex].Add(new GalVertexAttrib(Attr, IsConst, Offset, Data, Size, Type, IsRgba)); } State.VertexBindings = new GalVertexBinding[32]; for (int Index = 0; Index < 32; Index++) { if (Attribs[Index] == null) { continue; } int Control = ReadRegister(NvGpuEngine3dReg.VertexArrayNControl + Index * 4); bool Enable = (Control & 0x1000) != 0; if (!Enable) { continue; } long VbPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4); long VbEndPos = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNEndAddr + Index * 2); int VertexDivisor = ReadRegister(NvGpuEngine3dReg.VertexArrayNDivisor + Index * 4); bool Instanced = ReadRegisterBool(NvGpuEngine3dReg.VertexArrayNInstance + Index); int Stride = Control & 0xfff; if (Instanced && VertexDivisor != 0) { VbPosition += Stride * (CurrentInstance / VertexDivisor); } if (VbPosition > VbEndPos) { //Instance is invalid, ignore the draw call continue; } long VboKey = Vmm.GetPhysicalAddress(VbPosition); long VbSize = (VbEndPos - VbPosition) + 1; bool VboCached = Gpu.Renderer.Rasterizer.IsVboCached(VboKey, VbSize); if (!VboCached || Gpu.ResourceManager.MemoryRegionModified(Vmm, VboKey, VbSize, NvGpuBufferType.Vertex)) { if (Vmm.TryGetHostAddress(VbPosition, VbSize, out IntPtr VbPtr)) { Gpu.Renderer.Rasterizer.CreateVbo(VboKey, (int)VbSize, VbPtr); } else { Gpu.Renderer.Rasterizer.CreateVbo(VboKey, Vmm.ReadBytes(VbPosition, VbSize)); } } State.VertexBindings[Index].Enabled = true; State.VertexBindings[Index].Stride = Stride; State.VertexBindings[Index].VboKey = VboKey; State.VertexBindings[Index].Instanced = Instanced; State.VertexBindings[Index].Divisor = VertexDivisor; State.VertexBindings[Index].Attribs = Attribs[Index].ToArray(); } }
private void UploadVertexArrays(NvGpuVmm Vmm) { long IndexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress); int IndexEntryFmt = ReadRegister(NvGpuEngine3dReg.IndexArrayFormat); int IndexFirst = ReadRegister(NvGpuEngine3dReg.IndexBatchFirst); int IndexCount = ReadRegister(NvGpuEngine3dReg.IndexBatchCount); GalIndexFormat IndexFormat = (GalIndexFormat)IndexEntryFmt; int IndexEntrySize = 1 << IndexEntryFmt; if (IndexEntrySize > 4) { throw new InvalidOperationException(); } if (IndexCount != 0) { int IbSize = IndexCount * IndexEntrySize; bool IboCached = Gpu.Renderer.Rasterizer.IsIboCached(IndexPosition, (uint)IbSize); if (!IboCached || Vmm.IsRegionModified(IndexPosition, (uint)IbSize, NvGpuBufferType.Index)) { byte[] Data = Vmm.ReadBytes(IndexPosition, (uint)IbSize); Gpu.Renderer.Rasterizer.CreateIbo(IndexPosition, Data); } Gpu.Renderer.Rasterizer.SetIndexArray(IndexPosition, IbSize, IndexFormat); } List <GalVertexAttrib>[] Attribs = new List <GalVertexAttrib> [32]; for (int Attr = 0; Attr < 16; Attr++) { int Packed = ReadRegister(NvGpuEngine3dReg.VertexAttribNFormat + Attr); int ArrayIndex = Packed & 0x1f; if (Attribs[ArrayIndex] == null) { Attribs[ArrayIndex] = new List <GalVertexAttrib>(); } Attribs[ArrayIndex].Add(new GalVertexAttrib( Attr, ((Packed >> 6) & 0x1) != 0, (Packed >> 7) & 0x3fff, (GalVertexAttribSize)((Packed >> 21) & 0x3f), (GalVertexAttribType)((Packed >> 27) & 0x7), ((Packed >> 31) & 0x1) != 0)); } int VertexFirst = ReadRegister(NvGpuEngine3dReg.VertexArrayFirst); int VertexCount = ReadRegister(NvGpuEngine3dReg.VertexArrayCount); int PrimCtrl = ReadRegister(NvGpuEngine3dReg.VertexBeginGl); for (int Index = 0; Index < 32; Index++) { if (Attribs[Index] == null) { continue; } int Control = ReadRegister(NvGpuEngine3dReg.VertexArrayNControl + Index * 4); bool Enable = (Control & 0x1000) != 0; long VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4); long VertexEndPos = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNEndAddr + Index * 2); if (!Enable) { continue; } int Stride = Control & 0xfff; long VbSize = (VertexEndPos - VertexPosition) + 1; bool VboCached = Gpu.Renderer.Rasterizer.IsVboCached(VertexPosition, VbSize); if (!VboCached || Vmm.IsRegionModified(VertexPosition, VbSize, NvGpuBufferType.Vertex)) { byte[] Data = Vmm.ReadBytes(VertexPosition, VbSize); Gpu.Renderer.Rasterizer.CreateVbo(VertexPosition, Data); } Gpu.Renderer.Rasterizer.SetVertexArray(Index, Stride, VertexPosition, Attribs[Index].ToArray()); } GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff); if (IndexCount != 0) { Gpu.Renderer.Rasterizer.DrawElements(IndexPosition, IndexFirst, PrimType); } else { Gpu.Renderer.Rasterizer.DrawArrays(VertexFirst, VertexCount, PrimType); } }
private void Execute(NvGpuVmm vmm, int[] arguments) { if (_currentVideoCodec == VideoCodec.H264) { int frameDataSize = vmm.ReadInt32(_decoderContextAddress + 0x48); H264ParameterSets Params = MemoryHelper.Read <H264ParameterSets>(vmm.Memory, vmm.GetPhysicalAddress(_decoderContextAddress + 0x58)); H264Matrices matrices = new H264Matrices() { ScalingMatrix4 = vmm.ReadBytes(_decoderContextAddress + 0x1c0, 6 * 16), ScalingMatrix8 = vmm.ReadBytes(_decoderContextAddress + 0x220, 2 * 64) }; byte[] frameData = vmm.ReadBytes(_frameDataAddress, frameDataSize); _h264Decoder.Decode(Params, matrices, frameData); } else if (_currentVideoCodec == VideoCodec.Vp9) { int frameDataSize = vmm.ReadInt32(_decoderContextAddress + 0x30); Vp9FrameKeys keys = new Vp9FrameKeys() { CurrKey = vmm.GetPhysicalAddress(_vpxCurrLumaAddress), Ref0Key = vmm.GetPhysicalAddress(_vpxRef0LumaAddress), Ref1Key = vmm.GetPhysicalAddress(_vpxRef1LumaAddress), Ref2Key = vmm.GetPhysicalAddress(_vpxRef2LumaAddress) }; Vp9FrameHeader header = MemoryHelper.Read <Vp9FrameHeader>(vmm.Memory, vmm.GetPhysicalAddress(_decoderContextAddress + 0x48)); Vp9ProbabilityTables probs = new Vp9ProbabilityTables() { SegmentationTreeProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x387, 0x7), SegmentationPredProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x38e, 0x3), Tx8x8Probs = vmm.ReadBytes(_vpxProbTablesAddress + 0x470, 0x2), Tx16x16Probs = vmm.ReadBytes(_vpxProbTablesAddress + 0x472, 0x4), Tx32x32Probs = vmm.ReadBytes(_vpxProbTablesAddress + 0x476, 0x6), CoefProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x5a0, 0x900), SkipProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x537, 0x3), InterModeProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x400, 0x1c), InterpFilterProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x52a, 0x8), IsInterProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x41c, 0x4), CompModeProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x532, 0x5), SingleRefProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x580, 0xa), CompRefProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x58a, 0x5), YModeProbs0 = vmm.ReadBytes(_vpxProbTablesAddress + 0x480, 0x20), YModeProbs1 = vmm.ReadBytes(_vpxProbTablesAddress + 0x47c, 0x4), PartitionProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x4e0, 0x40), MvJointProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x53b, 0x3), MvSignProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x53e, 0x3), MvClassProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x54c, 0x14), MvClass0BitProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x540, 0x3), MvBitsProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x56c, 0x14), MvClass0FrProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x560, 0xc), MvFrProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x542, 0x6), MvClass0HpProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x548, 0x2), MvHpProbs = vmm.ReadBytes(_vpxProbTablesAddress + 0x54a, 0x2) }; byte[] frameData = vmm.ReadBytes(_frameDataAddress, frameDataSize); _vp9Decoder.Decode(keys, header, probs, frameData); } else { ThrowUnimplementedCodec(); } }
private void TextureCopy(NvGpuVmm Vmm, NvGpuPBEntry PBEntry) { CopyOperation Operation = (CopyOperation)ReadRegister(NvGpuEngine2dReg.CopyOperation); bool SrcLinear = ReadRegister(NvGpuEngine2dReg.SrcLinear) != 0; int SrcWidth = ReadRegister(NvGpuEngine2dReg.SrcWidth); int SrcHeight = ReadRegister(NvGpuEngine2dReg.SrcHeight); bool DstLinear = ReadRegister(NvGpuEngine2dReg.DstLinear) != 0; int DstWidth = ReadRegister(NvGpuEngine2dReg.DstWidth); int DstHeight = ReadRegister(NvGpuEngine2dReg.DstHeight); int DstPitch = ReadRegister(NvGpuEngine2dReg.DstPitch); int DstBlkDim = ReadRegister(NvGpuEngine2dReg.DstBlockDimensions); TextureSwizzle DstSwizzle = DstLinear ? TextureSwizzle.Pitch : TextureSwizzle.BlockLinear; int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf); long Key = Vmm.GetPhysicalAddress(MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress)); long SrcAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress); long DstAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.DstAddress); bool IsFbTexture = Gpu.Engine3d.IsFrameBufferPosition(Key); if (IsFbTexture && DstLinear) { DstSwizzle = TextureSwizzle.BlockLinear; } TextureInfo DstTexture = new TextureInfo( DstAddress, DstWidth, DstHeight, DstBlockHeight, DstBlockHeight, DstSwizzle, GalTextureFormat.A8B8G8R8); if (IsFbTexture) { //TODO: Change this when the correct frame buffer resolution is used. //Currently, the frame buffer size is hardcoded to 1280x720. SrcWidth = 1280; SrcHeight = 720; Gpu.Renderer.FrameBuffer.GetBufferData(Key, (byte[] Buffer) => { CopyTexture( Vmm, DstTexture, Buffer, SrcWidth, SrcHeight); }); } else { long Size = SrcWidth * SrcHeight * 4; byte[] Buffer = Vmm.ReadBytes(SrcAddress, Size); CopyTexture( Vmm, DstTexture, Buffer, SrcWidth, SrcHeight); } }