private void UploadTexture(NvGpuVmm Vmm, long BasePosition, int TexIndex, int HndIndex) { long Position = BasePosition + HndIndex * 4; int TextureHandle = Vmm.ReadInt32(Position); 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 TextureAddress = Vmm.ReadInt64(TicPosition + 4) & 0xffffffffffff; long Tag = TextureAddress; TextureAddress = Vmm.GetPhysicalAddress(TextureAddress); if (IsFrameBufferPosition(TextureAddress)) { //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.BindFrameBufferTexture(TextureAddress, TexIndex, Sampler); } else { GalTexture NewTexture = TextureFactory.MakeTexture(Vmm, TicPosition); long Size = (uint)TextureHelper.GetTextureSize(NewTexture); if (Gpu.Renderer.TryGetCachedTexture(Tag, Size, out GalTexture Texture)) { if (NewTexture.Equals(Texture) && !Vmm.IsRegionModified(Tag, Size, NvGpuBufferType.Texture)) { Gpu.Renderer.BindTexture(Tag, TexIndex); return; } } byte[] Data = TextureFactory.GetTextureData(Vmm, TicPosition); Gpu.Renderer.SetTextureAndSampler(Tag, Data, NewTexture, Sampler); Gpu.Renderer.BindTexture(Tag, TexIndex); } }
private void UploadVertexArrays(NvGpuVmm Vmm) { long IndexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress); int IndexSize = ReadRegister(NvGpuEngine3dReg.IndexArrayFormat); int IndexFirst = ReadRegister(NvGpuEngine3dReg.IndexBatchFirst); int IndexCount = ReadRegister(NvGpuEngine3dReg.IndexBatchCount); GalIndexFormat IndexFormat = (GalIndexFormat)IndexSize; IndexSize = 1 << IndexSize; if (IndexSize > 4) { throw new InvalidOperationException(); } if (IndexSize != 0) { int IbSize = IndexCount * IndexSize; bool IboCached = Gpu.Renderer.IsIboCached(IndexPosition, (uint)IbSize); if (!IboCached || Vmm.IsRegionModified(IndexPosition, (uint)IbSize, NvGpuBufferType.Index)) { byte[] Data = Vmm.ReadBytes(IndexPosition, (uint)IbSize); Gpu.Renderer.CreateIbo(IndexPosition, Data); } Gpu.Renderer.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 = 0; if (IndexCount != 0) { VbSize = (VertexEndPos - VertexPosition) + 1; } else { VbSize = VertexCount * Stride; } bool VboCached = Gpu.Renderer.IsVboCached(VertexPosition, VbSize); if (!VboCached || Vmm.IsRegionModified(VertexPosition, VbSize, NvGpuBufferType.Vertex)) { byte[] Data = Vmm.ReadBytes(VertexPosition, VbSize); Gpu.Renderer.CreateVbo(VertexPosition, Data); } Gpu.Renderer.SetVertexArray(Index, Stride, VertexPosition, Attribs[Index].ToArray()); } GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff); if (IndexCount != 0) { Gpu.Renderer.DrawElements(IndexPosition, IndexFirst, PrimType); } else { Gpu.Renderer.DrawArrays(VertexFirst, VertexCount, PrimType); } }