Example #1
0
        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);
            }
        }
Example #2
0
        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);
            }
        }