Saya mencoba melakukan pemasangan perangkat keras tetapi saya memukul beberapa masalah kinerja yang aneh. Framerate rata-rata sekitar 45, tapi sangat berombak.
- Terang
- SynchronizeWithVerticalRetrace = false
- IsFixedTimeStep = false
- PresentationInterval = PresentInterval.Immediate
Gambar di bawah ini menunjukkan waktu pengukuran saya (dengan Stopwatch
). Grafik paling atas adalah waktu yang dihabiskan dalam Draw
metode dan grafik bawah adalah waktu dari akhir Draw
hingga awalUpdate
Paku hampir persis 1 detik terpisah dan selalu 2,3,4 atau 5 kali dari waktu biasanya. Bingkai segera setelah lonjakan tidak membutuhkan waktu sama sekali. Saya telah memeriksa bahwa itu bukan pemulung.
Saat ini saya sedang memasang mesh yang terdiri dari 12 segitiga dan 36 simpul sebagai daftar segitiga (saya tahu itu tidak optimal, tetapi itu hanya untuk pengujian) dengan 1 juta instance. Jika saya mengumpulkan panggilan penarikan instans ke dalam bagian-bagian kecil dari 250 contoh masing-masing masalah teratasi, tetapi penggunaan cpu meningkat secara signifikan. Proses di atas adalah pada contoh 10.000 per panggilan undian, yang jauh lebih mudah di cpu.
Jika saya menjalankan game dalam layar penuh, grafik bawah hampir tidak ada, tetapi masalah yang sama terjadi sekarang dalam Draw
metode.
Berikut ini adalah run di dalam PIX , yang tidak masuk akal bagi saya sama sekali. Tampaknya untuk beberapa frame tidak ada rendering yang dilakukan ...
Ada ide, apa yang menyebabkan ini?
EDIT : Seperti yang diminta, bagian yang relevan dari kode render
A CubeBuffer
dibuat dan diinisialisasi, lalu diisi dengan kubus. Jika jumlah kubus di atas batas tertentu, yang baru CubeBuffer
dibuat, dan sebagainya. Setiap buffer menarik semua instance dalam satu panggilan.
Informasi yang diperlukan hanya sekali saja static
(vertex, indeks buffer dan deklarasi vertex; meskipun sejauh ini tidak ada perbedaan). Teksturnya 512x512
Seri()
device.Clear(Color.DarkSlateGray);
device.RasterizerState = new RasterizerState() { };
device.BlendState = new BlendState { };
device.DepthStencilState = new DepthStencilState() { DepthBufferEnable = true };
//samplerState=new SamplerState() { AddressU = TextureAddressMode.Mirror, AddressV = TextureAddressMode.Mirror, Filter = TextureFilter.Linear };
device.SamplerStates[0] = samplerState
effect.CurrentTechnique = effect.Techniques["InstancingTexColorLight"];
effect.Parameters["xView"].SetValue(cam.viewMatrix);
effect.Parameters["xProjection"].SetValue(projectionMatrix);
effect.Parameters["xWorld"].SetValue(worldMatrix);
effect.Parameters["cubeTexture"].SetValue(texAtlas);
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
pass.Apply();
foreach (var buf in CubeBuffers)
buf.Draw();
base.Draw(gameTime);
CubeBuffer
[StructLayout(LayoutKind.Sequential)]
struct InstanceInfoOpt9
{
public Matrix World;
public Vector2 Texture;
public Vector4 Light;
};
static VertexBuffer geometryBuffer = null;
static IndexBuffer geometryIndexBuffer = null;
static VertexDeclaration instanceVertexDeclaration = null;
VertexBuffer instanceBuffer = null;
InstanceInfoOpt9[] Buffer = new InstanceInfoOpt9[MaxCubeCount];
Int32 bufferCount=0
Init()
{
if (geometryBuffer == null)
{
geometryBuffer = new VertexBuffer(Device, typeof (VertexPositionTexture), 36, BufferUsage.WriteOnly);
geometryIndexBuffer = new IndexBuffer(Device, typeof (Int32), 36, BufferUsage.WriteOnly);
vertices = new[]{...}
geometryBuffer.SetData(vertices);
indices = new[]{...}
geometryIndexBuffer.SetData(indices);
var instanceStreamElements = new VertexElement[6];
instanceStreamElements[0] = new VertexElement(sizeof (float)*0, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 1);
instanceStreamElements[1] = new VertexElement(sizeof (float)*4, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 2);
instanceStreamElements[2] = new VertexElement(sizeof (float)*8, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 3);
instanceStreamElements[3] = new VertexElement(sizeof (float)*12, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 4);
instanceStreamElements[4] = new VertexElement(sizeof (float)*16, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 5);
instanceStreamElements[5] = new VertexElement(sizeof (float)*18, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 6);
instanceVertexDeclaration = new VertexDeclaration(instanceStreamElements);
}
instanceBuffer = new VertexBuffer(Device, instanceVertexDeclaration, MaxCubeCount, BufferUsage.WriteOnly);
instanceBuffer.SetData(Buffer);
bindings = new[]
{
new VertexBufferBinding(geometryBuffer),
new VertexBufferBinding(instanceBuffer, 0, 1),
};
}
AddRandomCube(Vector3 pos)
{
if(cubes.Count >= MaxCubeCount)
return null;
Vector2 tex = new Vector2(rnd.Next(0, 16), rnd.Next(0, 16))
Vector4 l= new Vector4((float)rnd.Next(), (float)rnd.Next(), (float)rnd.Next(), (float)rnd.Next());
var cube = new InstanceInfoOpt9(Matrix.CreateTranslation(pos),tex, l);
Buffer[bufferCount++] = cube;
return cube;
}
Draw()
{
Device.Indices = geometryIndexBuffer;
Device.SetVertexBuffers(bindings);
Device.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, 36, 0, 12, bufferCount);
}
Shader
float4x4 xView;
float4x4 xProjection;
float4x4 xWorld;
texture cubeTexture;
sampler TexColorLightSampler = sampler_state
{
texture = <cubeTexture>;
mipfilter = LINEAR;
minfilter = LINEAR;
magfilter = LINEAR;
};
struct InstancingVSTexColorLightInput
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
};
struct InstancingVSTexColorLightOutput
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
float4 Light : TEXCOORD1;
};
InstancingVSTexColorLightOutput InstancingVSTexColorLight(InstancingVSTexColorLightInput input, float4x4 instanceTransform : TEXCOORD1, float2 instanceTex : TEXCOORD5, float4 instanceLight : TEXCOORD6)
{
float4x4 preViewProjection = mul (xView, xProjection);
float4x4 preWorldViewProjection = mul (xWorld, preViewProjection);
InstancingVSTexColorLightOutput output;
float4 pos = input.Position;
pos = mul(pos, transpose(instanceTransform));
pos = mul(pos, preWorldViewProjection);
output.Position = pos;
output.Light = instanceLight;
output.TexCoord = float2((input.TexCoord.x / 16.0f) + (1.0f / 16.0f * instanceTex.x),
(input.TexCoord.y / 16.0f) + (1.0f / 16.0f * instanceTex.y));
return output;
}
float4 InstancingPSTexColorLight(InstancingVSTexColorLightOutput input) : COLOR0
{
float4 color = tex2D(TexColorLightSampler, input.TexCoord);
color.r = color.r * input.Light.r;
color.g = color.g * input.Light.g;
color.b = color.b * input.Light.b;
color.a = color.a * input.Light.a;
return color;
}
technique InstancingTexColorLight
{
pass Pass0
{
VertexShader = compile vs_3_0 InstancingVSTexColorLight();
PixelShader = compile ps_3_0 InstancingPSTexColorLight();
}
}
sumber
Jawaban:
Saya menduga bahwa kinerja Anda terikat GPU. Anda hanya meminta perangkat grafis Anda untuk melakukan lebih banyak pekerjaan per unit waktu daripada yang mampu ditangani; 36 juta simpul per bingkai adalah angka yang cukup baik, dan pemasangan perangkat keras sebenarnya dapat meningkatkan jumlah pekerjaan pemrosesan yang diperlukan pada sisi GPU dari persamaan tersebut. Gambar poligon lebih sedikit.
Mengapa mengurangi ukuran bets membuat masalah hilang? Karena itu membuat CPU membutuhkan waktu lebih lama untuk memproses sebuah bingkai, yang berarti menghabiskan lebih sedikit waktu
Present()
untuk menunggu di dalam menunggu GPU untuk menyelesaikan rendering. Itulah yang saya pikir sedang dilakukan selama jeda di akhirDraw()
panggilan Anda .Alasan di balik waktu spesifik celah lebih sulit untuk ilahi tanpa memahami seluruh kode, tapi saya juga tidak yakin itu penting. Lakukan lebih banyak pekerjaan pada CPU, atau kurangi kerja pada GPU, sehingga beban kerja Anda tidak merata.
Lihat artikel ini di blog Shawn Hargreaves untuk informasi lebih lanjut.
sumber
IsFixedTimeStep
set kefalse
, Jika game berjalan terlalu lambat, XNA akan memanggilUpdate()
beberapa kali berturut-turut untuk mengejar ketinggalan, dengan sengaja menjatuhkan frame dalam proses. ApakahIsRunningSlowly
disetel ke true selama bingkai ini? Adapun waktu yang aneh - itu membuat saya sedikit heran. Apakah Anda menjalankan dalam mode berjendela? Apakah perilaku tetap dalam mode layar penuh?IsFixedTimeStep=true
. Grafik bawah menunjukkan waktu antara akhir pengundian saya dan awal panggilan pembaruan dari frame berikutnya. Frame tidak jatuh, saya memanggil metode draw dan membayar harga CPU untuk mereka (grafik atas). Perilaku yang sama dalam layar penuh dan melintasi resolusi.Saya pikir Anda memiliki masalah sampah ... mungkin Anda membuat / menghancurkan banyak objek dan bahwa paku adalah rutinitas pengumpul sampah yang bekerja ...
pastikan untuk menggunakan kembali semua struktur memori Anda ... dan jangan terlalu sering menggunakan 'baru'
sumber