Jump to content
  • Advertisement
Sign in to follow this  
widmowyfox

create big instance buffer

This topic is 911 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, i tried to create really big instance buffer, like 100 000 000 or more but theres 2 problems:

 

1. Even 10 000 000 is very hard to render, even when i display 100 or less instances, why?

 

2.Buffer cant be create with size bigger than about 18 000 000, how can i achieve that?

 

Is it ok to create huge instance buffer?  What are the alternatives ? 

const int n = 270;
	mInstancedData.resize(n*n*n);
	
	float width = 1000.0f;
	float height = 1.0f;
	float depth = 1000.0f;
	
	float x = -0.5f*width;
	float y = -0.5f*height;
	float z = -0.5f*depth;
	float dx = width / (n-1);
	float dy = height / (n-1);
	float dz = depth / (n-1);

	float r1;
	float r2;
	for(int k = 0; k < n; ++k)
	{
		for(int i = 0; i < n; ++i)
		{
			for(int j = 0; j < n; ++j)
			{
	
				XMMATRIX Offset;
				r1=MathHelper::RandF(0.0f, -256.0f);
				r2=MathHelper::RandF(0.0f, -256.0f);

				XMMATRIX rotacja=XMMatrixRotationY(MathHelper::RandF(0.0f, 2.0f));
				XMMATRIX rotacja2=XMMatrixRotationZ(1.57);
				XMMATRIX rotacja3=XMMatrixRotationX(-1.57);
				XMMATRIX Scale = XMMatrixScaling(MathHelper::RandF(2.0f, 3.0f), MathHelper::RandF(1.0f, 1.0f), MathHelper::RandF(1.0f, 5.0f));
			
				Offset = XMMatrixTranslation(r1, mTerrain.GetHeight(r1,r2)-0.5, r2);
			

	XMStoreFloat4x4(&mInstancedData[k*n*n + i*n + j].World, Scale*rotacja2*rotacja3*rotacja*Offset);

			
			}
		}
	}
		D3D11_BUFFER_DESC vbd1;
    vbd1.Usage = D3D11_USAGE_DYNAMIC;
	vbd1.ByteWidth = sizeof(InstancedData) * mInstancedData.size();
    vbd1.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vbd1.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    vbd1.MiscFlags = 0;
	vbd1.StructureByteStride = 0;

    HR(md3dDevice->CreateBuffer(&vbd1, 0, &mInstancedBuffer));

Share this post


Link to post
Share on other sites
Advertisement
Yeah you generally shouldn't make gigabyte sized buffers.
Even if you only use the first 100 bytes of the buffer, Windows only knows that you need to access the buffer (not how much of it) so it will page the whole gigabyte in and out of VRAM.

Share this post


Link to post
Share on other sites

ok so maybe i describe what I try to do. I want to create 100 areas with 1 000 000 instance each (1 instance=2 tris-simply grid). Instance have grass texture 1024x1024 with alpha clip. Every instance have random position in area. I render only 1 area in same time( distance to camera) so i need this 100 000 000 only to save position of every instance but I generate only 1 000 000 instances=2 mil tris. Not big number i think, i have 16 gb of ram.What should i do to achieve this goal?  Should i create buffer for each area? 100 buffers. It does not sound too good.

Share this post


Link to post
Share on other sites
Theoretically GPUs are able to process lot of vertices, but you will have some limiting factors. For one memory bandwidth. If the vertex shader is so optimized, that it will be optimized to output such an insane number of vertices per frame, then you will get bandwidth issues. The second fun will be, when I understood you right, that you want to render grass (obviously single blades of grass ;-) ), most likely alpha blended ? This will result in lot of overdraw (no early z-rejection) and you need to sort it when changing the camera angle. Caching your data in 100 buffers sounds like a better approach.

Share this post


Link to post
Share on other sites


(1 instance=2 tris-simply grid)

Thats not a good idea... you should aim for at lot more triangles per instance.  Because the way gpu's work (look up wavefront/warp size) 2 triangles per instance would lead to under utilization.  It would be better for you to create clusters of grass instead and randomly place those.

Share this post


Link to post
Share on other sites

I understand.@Ashaman73 I don't generate single blades, but single bushes (picture).

 I must use 3d model editor to create group of grass bushes? Can I do it in-code?

What is the best method to generate grass? 
void TerrainApp::BuildGrassGeometryBuffers()
{
	D3D11_RASTERIZER_DESC noCullDesc;
	ZeroMemory(&noCullDesc, sizeof(D3D11_RASTERIZER_DESC));
	noCullDesc.FillMode = D3D11_FILL_SOLID;
	noCullDesc.CullMode = D3D11_CULL_NONE;
	noCullDesc.FrontCounterClockwise = false;
	noCullDesc.DepthClipEnable = true;

	HR(md3dDevice->CreateRasterizerState(&noCullDesc, &NoCullRS));

	GeometryGenerator::MeshData grass;
	GeometryGenerator geoGen;
	geoGen.CreateGrid(1,1,2,2,grass);

	mGrassVertexOffset=0;
mGrassIndexCount=grass.Indices.size();
mGrassIndexOffset=0;

UINT totalVertexCount=grass.Vertices.size();
UINT totalIndexCount=mGrassIndexCount;

vertices.resize(totalVertexCount);
UINT k = 0;
for(size_t i = 0; i < grass.Vertices.size(); ++i, ++k)
	{
		vertices[k].Pos    = grass.Vertices[i].Position;
		vertices[k].Normal = grass.Vertices[i].Normal;
		vertices[k].Tex    = grass.Vertices[i].TexC;
	}


  D3D11_BUFFER_DESC vbd;
    vbd.Usage = D3D11_USAGE_IMMUTABLE;
	vbd.ByteWidth = sizeof(Vertex::Basic32) * totalVertexCount;
    vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vbd.CPUAccessFlags = 0;
    vbd.MiscFlags = 0;
    D3D11_SUBRESOURCE_DATA vinitData;
    vinitData.pSysMem = &vertices[0];
    HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mGrassVB));

	
	indices.insert(indices.end(), grass.Indices.begin(), grass.Indices.end());

	D3D11_BUFFER_DESC ibd;
    ibd.Usage = D3D11_USAGE_IMMUTABLE;
	ibd.ByteWidth = sizeof(UINT) * totalIndexCount;
    ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
    ibd.CPUAccessFlags = 0;
    ibd.MiscFlags = 0;
    D3D11_SUBRESOURCE_DATA iinitData;
	iinitData.pSysMem = &indices[0];
    HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &mGrassIB));}

 

 

2rz9vyo.jpg

Edited by widmowyfox

Share this post


Link to post
Share on other sites

I would try to use geometry shaders and such...

 

I got grass working the following way:

A masking texture determined where grass would spawn on terrain, and I used a vertex shader without input to generate points (SV_VertexID provided a means of calculating UV for looking up in masking texture, and for calculating position of grass quad) with Draw(texwidth*texheight).. Those points was then run through a geometry shader, which produced triangles. This shader also oriented the grass quads to align with terrain normal at that point, and randomized the size (Edit: size was also multiplied by the masking value, so my masking texture could thin out grass where needed) and rotation of each quad..

The point is that I didn't send a single vertex to anything, but simply provided a grayscale texture to determine where grass should be and the rest was automated :D

 

Edit: I also provided random offsets to each quad position, so the grass wouldn't be aligned in neat rows...

Edited by vinterberg

Share this post


Link to post
Share on other sites

I think it would be best to prefer a medium sized buffer of geometry data that contains many bushes or grass blades or whatever, and another medium sized instance buffer. It's kind of like a hierarchical placement in this way. Combining instance id and vertex id along with some data structure to align your models to the ground, you can get a ton of throughput this way. Also using the ids you can create a shader based pnrg to generate placements and orientations while avoiding a bunch of matrix transform data. Consider that AMD gpus are not very good at rendering batches of geometry under something like 256 vertices -- so a bush that's only a few quads is going to be very inefficient to render even if you instance it.

 

Alternatively keep doing what you're doing but pack your matrices more efficiently. Perhaps 3 floats for position and 4 half-precision floats for a quaternion storing orientation. 20 bytes vs 64? Do you even need a full rotation? Maybe just spin it around an axis, you can store a normalized vector into 4 bytes just fine if it's not animating and spin it along that using instance id.

Edited by Dingleberry

Share this post


Link to post
Share on other sites

Thanks for all messages, I will try to change matrix to float3 only and load it from disk for instances, rotation will be calculated in shader. I have 1 more question. When I generate more bushes in 1 instance how can i calculate every bush hight on ground?

@Dingleberry "Combining instance id and vertex id along with some data structure to align your models to the ground"

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!