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 (QueryKeyUpload(Vmm, Key, Cb.Size, NvGpuBufferType.ConstBuffer)) { IntPtr Source = Vmm.GetHostAddress(Cb.Position, Cb.Size); Gpu.Renderer.Buffer.SetData(Key, Cb.Size, Source); } 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) { IntPtr DataAddress = Vmm.GetHostAddress(Cb.Position, Cb.Size); Gpu.Renderer.Shader.SetConstBuffer(BasePosition + (uint)Offset, Cbuf, Cb.Size, DataAddress); } } } }
private void UploadConstBuffers(NvGpuVmm Vmm, GalPipelineState State) { for (int Stage = 0; Stage < State.ConstBufferKeys.Length; Stage++) { for (int Index = 0; Index < State.ConstBufferKeys[Stage].Length; Index++) { ConstBuffer Cb = ConstBuffers[Stage][Index]; long Key = Cb.Position; if (Cb.Enabled && QueryKeyUpload(Vmm, Key, Cb.Size, NvGpuBufferType.ConstBuffer)) { IntPtr Source = Vmm.GetHostAddress(Key, Cb.Size); Gpu.Renderer.Buffer.SetData(Key, Cb.Size, Source); } State.ConstBufferKeys[Stage][Index] = Key; } } }
private void UploadVertexArrays(NvGpuVmm Vmm, GalPipelineState State) { long IndexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress); long IboKey = Vmm.GetPhysicalAddress(IndexPosition); int IndexEntryFmt = ReadRegister(NvGpuEngine3dReg.IndexArrayFormat); 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 || QueryKeyUpload(Vmm, 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)); } 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 VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4); long VertexEndPos = 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) { VertexPosition += Stride * (CurrentInstance / VertexDivisor); } if (VertexPosition > VertexEndPos) { //Instance is invalid, ignore the draw call continue; } long VboKey = Vmm.GetPhysicalAddress(VertexPosition); long VbSize = (VertexEndPos - VertexPosition) + 1; bool VboCached = Gpu.Renderer.Rasterizer.IsVboCached(VboKey, VbSize); if (!VboCached || QueryKeyUpload(Vmm, VboKey, VbSize, NvGpuBufferType.Vertex)) { IntPtr DataAddress = Vmm.GetHostAddress(VertexPosition, VbSize); Gpu.Renderer.Rasterizer.CreateVbo(VboKey, (int)VbSize, DataAddress); } 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); 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 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 || QueryKeyUpload(Vmm, IboKey, (uint)IbSize, NvGpuBufferType.Index)) { if (!UsesLegacyQuads) { IntPtr DataAddress = Vmm.GetHostAddress(IbPosition, IbSize); Gpu.Renderer.Rasterizer.CreateIbo(IboKey, IbSize, DataAddress); } 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 VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + ArrayIndex * 4); int Offset = (Packed >> 7) & 0x3fff; //Note: 16 is the maximum size of an attribute, //having a component size of 32-bits with 4 elements (a vec4). IntPtr Pointer = Vmm.GetHostAddress(VertexPosition + Offset, 16); Attribs[ArrayIndex].Add(new GalVertexAttrib( Attr, ((Packed >> 6) & 0x1) != 0, Offset, Pointer, (GalVertexAttribSize)((Packed >> 21) & 0x3f), (GalVertexAttribType)((Packed >> 27) & 0x7), ((Packed >> 31) & 0x1) != 0)); } 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 VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4); long VertexEndPos = 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) { VertexPosition += Stride * (CurrentInstance / VertexDivisor); } if (VertexPosition > VertexEndPos) { //Instance is invalid, ignore the draw call continue; } long VboKey = Vmm.GetPhysicalAddress(VertexPosition); long VbSize = (VertexEndPos - VertexPosition) + 1; bool VboCached = Gpu.Renderer.Rasterizer.IsVboCached(VboKey, VbSize); if (!VboCached || QueryKeyUpload(Vmm, VboKey, VbSize, NvGpuBufferType.Vertex)) { IntPtr DataAddress = Vmm.GetHostAddress(VertexPosition, VbSize); Gpu.Renderer.Rasterizer.CreateVbo(VboKey, (int)VbSize, DataAddress); } 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(); } }