public bool MemoryRegionModified(NvGpuVmm Vmm, long Position, long Size, NvGpuBufferType Type) { HashSet <long> Uploaded = UploadedKeys[(int)Type]; if (!Uploaded.Add(Position)) { return(false); } return(Vmm.IsRegionModified(Position, Size, Type)); }
public bool MemoryRegionModified(NvGpuVmm vmm, long position, long size, NvGpuBufferType type) { HashSet <long> uploaded = _uploadedKeys[(int)type]; if (!uploaded.Add(position)) { return(false); } return(vmm.IsRegionModified(position, size, type)); }
private bool QueryKeyUpload(NvGpuVmm Vmm, long Key, long Size, NvGpuBufferType Type) { List <long> Uploaded = UploadedKeys[(int)Type]; if (Uploaded.Contains(Key)) { return(false); } Uploaded.Add(Key); return(Vmm.IsRegionModified(Key, Size, Type)); }
private void TextureCopy(NvGpuVmm Vmm) { CopyOperation Operation = (CopyOperation)ReadRegister(NvGpuEngine2dReg.CopyOperation); int DstFormat = ReadRegister(NvGpuEngine2dReg.DstFormat); 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); int SrcFormat = ReadRegister(NvGpuEngine2dReg.SrcFormat); bool SrcLinear = ReadRegister(NvGpuEngine2dReg.SrcLinear) != 0; int SrcWidth = ReadRegister(NvGpuEngine2dReg.SrcWidth); int SrcHeight = ReadRegister(NvGpuEngine2dReg.SrcHeight); int SrcPitch = ReadRegister(NvGpuEngine2dReg.SrcPitch); int SrcBlkDim = ReadRegister(NvGpuEngine2dReg.SrcBlockDimensions); int DstBlitX = ReadRegister(NvGpuEngine2dReg.BlitDstX); int DstBlitY = ReadRegister(NvGpuEngine2dReg.BlitDstY); int DstBlitW = ReadRegister(NvGpuEngine2dReg.BlitDstW); int DstBlitH = ReadRegister(NvGpuEngine2dReg.BlitDstH); long BlitDuDx = ReadRegisterFixed1_31_32(NvGpuEngine2dReg.BlitDuDxFract); long BlitDvDy = ReadRegisterFixed1_31_32(NvGpuEngine2dReg.BlitDvDyFract); long SrcBlitX = ReadRegisterFixed1_31_32(NvGpuEngine2dReg.BlitSrcXFract); long SrcBlitY = ReadRegisterFixed1_31_32(NvGpuEngine2dReg.BlitSrcYFract); GalImageFormat SrcImgFormat = ImageUtils.ConvertSurface((GalSurfaceFormat)SrcFormat); GalImageFormat DstImgFormat = ImageUtils.ConvertSurface((GalSurfaceFormat)DstFormat); GalMemoryLayout SrcLayout = GetLayout(SrcLinear); GalMemoryLayout DstLayout = GetLayout(DstLinear); int SrcBlockHeight = 1 << ((SrcBlkDim >> 4) & 0xf); int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf); long SrcAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress); long DstAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.DstAddress); long SrcKey = Vmm.GetPhysicalAddress(SrcAddress); long DstKey = Vmm.GetPhysicalAddress(DstAddress); GalImage SrcTexture = new GalImage( SrcWidth, SrcHeight, 1, SrcBlockHeight, SrcLayout, SrcImgFormat); GalImage DstTexture = new GalImage( DstWidth, DstHeight, 1, DstBlockHeight, DstLayout, DstImgFormat); SrcTexture.Pitch = SrcPitch; DstTexture.Pitch = DstPitch; Gpu.ResourceManager.SendTexture(Vmm, SrcKey, SrcTexture); Gpu.ResourceManager.SendTexture(Vmm, DstKey, DstTexture); int SrcBlitX1 = (int)(SrcBlitX >> 32); int SrcBlitY1 = (int)(SrcBlitY >> 32); int SrcBlitX2 = (int)(SrcBlitX + DstBlitW * BlitDuDx >> 32); int SrcBlitY2 = (int)(SrcBlitY + DstBlitH * BlitDvDy >> 32); Gpu.Renderer.RenderTarget.Copy( SrcKey, DstKey, SrcBlitX1, SrcBlitY1, SrcBlitX2, SrcBlitY2, DstBlitX, DstBlitY, DstBlitX + DstBlitW, DstBlitY + DstBlitH); //Do a guest side copy aswell. This is necessary when //the texture is modified by the guest, however it doesn't //work when resources that the gpu can write to are copied, //like framebuffers. ImageUtils.CopyTexture( Vmm, SrcTexture, DstTexture, SrcAddress, DstAddress, SrcBlitX1, SrcBlitY1, DstBlitX, DstBlitY, DstBlitW, DstBlitH); Vmm.IsRegionModified(DstKey, ImageUtils.GetSize(DstTexture), NvGpuBufferType.Texture); }
private void TextureCopy(NvGpuVmm vmm) { CopyOperation operation = (CopyOperation)ReadRegister(NvGpuEngine2dReg.CopyOperation); int dstFormat = ReadRegister(NvGpuEngine2dReg.DstFormat); bool dstLinear = ReadRegister(NvGpuEngine2dReg.DstLinear) != 0; int dstWidth = ReadRegister(NvGpuEngine2dReg.DstWidth); int dstHeight = ReadRegister(NvGpuEngine2dReg.DstHeight); int dstDepth = ReadRegister(NvGpuEngine2dReg.DstDepth); int dstLayer = ReadRegister(NvGpuEngine2dReg.DstLayer); int dstPitch = ReadRegister(NvGpuEngine2dReg.DstPitch); int dstBlkDim = ReadRegister(NvGpuEngine2dReg.DstBlockDimensions); int srcFormat = ReadRegister(NvGpuEngine2dReg.SrcFormat); bool srcLinear = ReadRegister(NvGpuEngine2dReg.SrcLinear) != 0; int srcWidth = ReadRegister(NvGpuEngine2dReg.SrcWidth); int srcHeight = ReadRegister(NvGpuEngine2dReg.SrcHeight); int srcDepth = ReadRegister(NvGpuEngine2dReg.SrcDepth); int srcLayer = ReadRegister(NvGpuEngine2dReg.SrcLayer); int srcPitch = ReadRegister(NvGpuEngine2dReg.SrcPitch); int srcBlkDim = ReadRegister(NvGpuEngine2dReg.SrcBlockDimensions); int dstBlitX = ReadRegister(NvGpuEngine2dReg.BlitDstX); int dstBlitY = ReadRegister(NvGpuEngine2dReg.BlitDstY); int dstBlitW = ReadRegister(NvGpuEngine2dReg.BlitDstW); int dstBlitH = ReadRegister(NvGpuEngine2dReg.BlitDstH); long blitDuDx = ReadRegisterFixed1_31_32(NvGpuEngine2dReg.BlitDuDxFract); long blitDvDy = ReadRegisterFixed1_31_32(NvGpuEngine2dReg.BlitDvDyFract); long srcBlitX = ReadRegisterFixed1_31_32(NvGpuEngine2dReg.BlitSrcXFract); long srcBlitY = ReadRegisterFixed1_31_32(NvGpuEngine2dReg.BlitSrcYFract); GalImageFormat srcImgFormat = ImageUtils.ConvertSurface((GalSurfaceFormat)srcFormat); GalImageFormat dstImgFormat = ImageUtils.ConvertSurface((GalSurfaceFormat)dstFormat); GalMemoryLayout srcLayout = GetLayout(srcLinear); GalMemoryLayout dstLayout = GetLayout(dstLinear); int srcBlockHeight = 1 << ((srcBlkDim >> 4) & 0xf); int dstBlockHeight = 1 << ((dstBlkDim >> 4) & 0xf); long srcAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress); long dstAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.DstAddress); long srcKey = vmm.GetPhysicalAddress(srcAddress); long dstKey = vmm.GetPhysicalAddress(dstAddress); bool isSrcLayered = false; bool isDstLayered = false; GalTextureTarget srcTarget = GalTextureTarget.TwoD; if (srcDepth != 0) { srcTarget = GalTextureTarget.TwoDArray; srcDepth++; isSrcLayered = true; } else { srcDepth = 1; } GalTextureTarget dstTarget = GalTextureTarget.TwoD; if (dstDepth != 0) { dstTarget = GalTextureTarget.TwoDArray; dstDepth++; isDstLayered = true; } else { dstDepth = 1; } GalImage srcTexture = new GalImage( srcWidth, srcHeight, 1, srcDepth, 1, srcBlockHeight, 1, srcLayout, srcImgFormat, srcTarget); GalImage dstTexture = new GalImage( dstWidth, dstHeight, 1, dstDepth, 1, dstBlockHeight, 1, dstLayout, dstImgFormat, dstTarget); srcTexture.Pitch = srcPitch; dstTexture.Pitch = dstPitch; long GetLayerOffset(GalImage image, int layer) { int targetMipLevel = image.MaxMipmapLevel <= 1 ? 1 : image.MaxMipmapLevel - 1; return(ImageUtils.GetLayerOffset(image, targetMipLevel) * layer); } int srcLayerIndex = -1; if (isSrcLayered && _gpu.ResourceManager.TryGetTextureLayer(srcKey, out srcLayerIndex) && srcLayerIndex != 0) { srcKey = srcKey - GetLayerOffset(srcTexture, srcLayerIndex); } int dstLayerIndex = -1; if (isDstLayered && _gpu.ResourceManager.TryGetTextureLayer(dstKey, out dstLayerIndex) && dstLayerIndex != 0) { dstKey = dstKey - GetLayerOffset(dstTexture, dstLayerIndex); } _gpu.ResourceManager.SendTexture(vmm, srcKey, srcTexture); _gpu.ResourceManager.SendTexture(vmm, dstKey, dstTexture); if (isSrcLayered && srcLayerIndex == -1) { for (int layer = 0; layer < srcTexture.LayerCount; layer++) { _gpu.ResourceManager.SetTextureArrayLayer(srcKey + GetLayerOffset(srcTexture, layer), layer); } srcLayerIndex = 0; } if (isDstLayered && dstLayerIndex == -1) { for (int layer = 0; layer < dstTexture.LayerCount; layer++) { _gpu.ResourceManager.SetTextureArrayLayer(dstKey + GetLayerOffset(dstTexture, layer), layer); } dstLayerIndex = 0; } int srcBlitX1 = (int)(srcBlitX >> 32); int srcBlitY1 = (int)(srcBlitY >> 32); int srcBlitX2 = (int)(srcBlitX + dstBlitW * blitDuDx >> 32); int srcBlitY2 = (int)(srcBlitY + dstBlitH * blitDvDy >> 32); _gpu.Renderer.RenderTarget.Copy( srcTexture, dstTexture, srcKey, dstKey, srcLayerIndex, dstLayerIndex, srcBlitX1, srcBlitY1, srcBlitX2, srcBlitY2, dstBlitX, dstBlitY, dstBlitX + dstBlitW, dstBlitY + dstBlitH); //Do a guest side copy aswell. This is necessary when //the texture is modified by the guest, however it doesn't //work when resources that the gpu can write to are copied, //like framebuffers. // FIXME: SUPPORT MULTILAYER CORRECTLY HERE (this will cause weird stuffs on the first layer) ImageUtils.CopyTexture( vmm, srcTexture, dstTexture, srcAddress, dstAddress, srcBlitX1, srcBlitY1, dstBlitX, dstBlitY, dstBlitW, dstBlitH); vmm.IsRegionModified(dstKey, ImageUtils.GetSize(dstTexture), NvGpuBufferType.Texture); }
private void UploadVertexArrays(NvGpuVmm Vmm) { long IndexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress); long IboKey = Vmm.GetPhysicalAddress(IndexPosition); 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(IboKey, (uint)IbSize); if (!IboCached || Vmm.IsRegionModified(IboKey, (uint)IbSize, NvGpuBufferType.Index)) { IntPtr DataAddress = Vmm.GetHostAddress(IndexPosition, IbSize); Gpu.Renderer.Rasterizer.CreateIbo(IboKey, IbSize, DataAddress); } Gpu.Renderer.Rasterizer.SetIndexArray(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; } long VboKey = Vmm.GetPhysicalAddress(VertexPosition); int Stride = Control & 0xfff; long VbSize = (VertexEndPos - VertexPosition) + 1; bool VboCached = Gpu.Renderer.Rasterizer.IsVboCached(VboKey, VbSize); if (!VboCached || Vmm.IsRegionModified(VboKey, VbSize, NvGpuBufferType.Vertex)) { IntPtr DataAddress = Vmm.GetHostAddress(VertexPosition, VbSize); Gpu.Renderer.Rasterizer.CreateVbo(VboKey, (int)VbSize, DataAddress); } Gpu.Renderer.Rasterizer.SetVertexArray(Stride, VboKey, Attribs[Index].ToArray()); } GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff); if (IndexCount != 0) { int VertexBase = ReadRegister(NvGpuEngine3dReg.VertexArrayElemBase); Gpu.Renderer.Rasterizer.DrawElements(IboKey, IndexFirst, VertexBase, PrimType); } else { Gpu.Renderer.Rasterizer.DrawArrays(VertexFirst, VertexCount, PrimType); } }
private void UploadTexture(NvGpuVmm Vmm, long BasePosition, int TexIndex, int HndIndex) { long Position = BasePosition + HndIndex * 4; int TextureHandle = Vmm.ReadInt32(Position); if (TextureHandle == 0) { //TODO: Is this correct? //Some games like puyo puyo will have 0 handles. //It may be just normal behaviour or a bug caused by sync issues. //The game does initialize the value properly after through. return; } int TicIndex = (TextureHandle >> 0) & 0xfffff; int TscIndex = (TextureHandle >> 20) & 0xfff; long TicPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.TexHeaderPoolOffset); long TscPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.TexSamplerPoolOffset); TicPosition += TicIndex * 0x20; TscPosition += TscIndex * 0x20; GalTextureSampler Sampler = TextureFactory.MakeSampler(Gpu, Vmm, TscPosition); long Key = Vmm.ReadInt64(TicPosition + 4) & 0xffffffffffff; Key = Vmm.GetPhysicalAddress(Key); if (IsFrameBufferPosition(Key)) { //This texture is a frame buffer texture, //we shouldn't read anything from memory and bind //the frame buffer texture instead, since we're not //really writing anything to memory. Gpu.Renderer.FrameBuffer.BindTexture(Key, TexIndex); } else { GalTexture NewTexture = TextureFactory.MakeTexture(Vmm, TicPosition); long Size = (uint)TextureHelper.GetTextureSize(NewTexture); bool HasCachedTexture = false; if (Gpu.Renderer.Texture.TryGetCachedTexture(Key, Size, out GalTexture Texture)) { if (NewTexture.Equals(Texture) && !Vmm.IsRegionModified(Key, Size, NvGpuBufferType.Texture)) { Gpu.Renderer.Texture.Bind(Key, TexIndex); HasCachedTexture = true; } } if (!HasCachedTexture) { byte[] Data = TextureFactory.GetTextureData(Vmm, TicPosition); Gpu.Renderer.Texture.Create(Key, Data, NewTexture); } Gpu.Renderer.Texture.Bind(Key, TexIndex); } Gpu.Renderer.Texture.SetSampler(Sampler); }