Skip to main content
GameDev.net gamedev.net

PRO Tired of ads? Read GameDev.net ad-free and help keep the community independent with GameDev Pro — $3/month.

Compute Shader for Terrain Rendering

Compute Shader for Terrain Rendering

2,591 1
Was going to get an early night tonight, but an hour past my target I'm still messing around with Direct3D 11 Compute Shaders.

For less than 2hrs from first-keypress to a working algorithm I'm quite impressed, and the CS definitely seems to suit image processing algorithms nicely. Definitely a lot nicer than using pixel shaders!

Texture2D texHeightMap : register( t0 ); RWTexture1D bufferResults : register( u0 );groupshared float groupResults[16 * 16];groupshared float4 stats;[numthreads(16, 16, 1)]void csMain( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ){   	// Gid  = The xyz index as spun up by the actual application call	//		  e.g. if ::Dispatch(16,16,1) is used then this will index into those bounds	// DTid = Similar to above, but the global offset, so for [numthreads(16,16,1)] and	//        ::Dispatch(16,16,1) this variable will range between 0-255,0-255,0	// GTid = The offset within the [numthreads()] bounds e.g. 0-15,0-15,0	// GI   = The flattened offset for this group e.g. 0-255 (16*16)		// Sample the appropriate 16x16 region	groupResults[GI] = texHeightMap.Load( uint3( DTid.xy, 0 ) ).r;		// Block until all threads have finished reading	GroupMemoryBarrierWithGroupSync();		// Then sum up the details	if(GI == 0)	{		// Thread #0 computes the minimum		// value from the raw data		float mn = 1e9f;				for(uint i = 0; i < 16 * 16; ++i)			if(groupResults < mn)				mn = groupResults;				// Store!		stats.r = mn;	}	else if(GI == 1)	{		// Thread #1 computes the maximum value		// from the raw data		float mx = -1e9f;				for(uint i = 0; i < 16 * 16; ++i)			if(groupResults > mx)				mx = groupResults;				// Store!		stats.g = mx;	}	else if(GI == 2)	{		// Thread #2 computes the average value		// from the raw data		float avg = 0.0f;				for(uint i = 0; i < 16 * 16; ++i)			avg += groupResults;					avg /= (16.0f * 16.0f);				// Store!		stats.b = avg;	}	else if(GI == 3)	{		// Thread #3 computes the standard		// deviation of the raw data		float avg = 0.0f;				for(uint i = 0; i < 16 * 16; ++i)			avg += groupResults;					avg /= (16.0f * 16.0f);				float stdDev = 0.0f;				for(uint i = 0; i < 16 * 16; ++i)			stdDev += pow(groupResults - avg, 2);				stdDev /= ((16.0f*16.0f)-1.0f);				stats.a = sqrt(stdDev);	}		GroupMemoryBarrierWithGroupSync();		if( GI == 0 )	{		// Determine which cell in the ouput to write		uint outIdx = Gid.x + Gid.y * 16;				// Store!		bufferResults[outIdx] = stats;	}}


It's basically a three-phase algorithm:
1. All 256 threads read one sample from the heightmap and store it in group-shared memory
2. Once complete the first 4 threads (leaving 252 idle) each calculate one of the statistics. In theory these will be done concurrently.
3. Once all four statistics are finished computing it's written to the actual output buffer by the 1st thread (255 threads idle)

Bit pointless to guess the performance profile, but it should be the sum of the slowest or most delayed read, then the most expensive of the four statistics, then the time to write to the 1D texture. I could definitely implement it better, but plenty of scope for lovely concurrent execution [grin]

When run over a 256x256 heightmap gives me:

LOG: Ran compute shader pre-pass, generated 256-element look-up table (4096 bytes) in 0.02ms. Used 16x16 groups of 16x16 threads over a 256x256 heightmap (65536 threads in total). [RunComputeShaderPrePass(...) @ line 1406]	Result 0 (for tile 0,0 starting at 0,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 1 (for tile 1,0 starting at 16,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 2 (for tile 2,0 starting at 32,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 3 (for tile 3,0 starting at 48,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 4 (for tile 4,0 starting at 64,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 5 (for tile 5,0 starting at 80,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 6 (for tile 6,0 starting at 96,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 7 (for tile 7,0 starting at 112,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 8 (for tile 8,0 starting at 128,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 9 (for tile 9,0 starting at 144,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 10 (for tile 10,0 starting at 160,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 11 (for tile 11,0 starting at 176,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 12 (for tile 12,0 starting at 192,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 13 (for tile 13,0 starting at 208,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 14 (for tile 14,0 starting at 224,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 15 (for tile 15,0 starting at 240,0): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 16 (for tile 0,1 starting at 0,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 17 (for tile 1,1 starting at 16,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 18 (for tile 2,1 starting at 32,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 19 (for tile 3,1 starting at 48,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 20 (for tile 4,1 starting at 64,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 21 (for tile 5,1 starting at 80,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 22 (for tile 6,1 starting at 96,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 23 (for tile 7,1 starting at 112,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 24 (for tile 8,1 starting at 128,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 25 (for tile 9,1 starting at 144,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 26 (for tile 10,1 starting at 160,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 27 (for tile 11,1 starting at 176,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 28 (for tile 12,1 starting at 192,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 29 (for tile 13,1 starting at 208,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 30 (for tile 14,1 starting at 224,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 31 (for tile 15,1 starting at 240,16): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 32 (for tile 0,2 starting at 0,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 33 (for tile 1,2 starting at 16,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 34 (for tile 2,2 starting at 32,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 35 (for tile 3,2 starting at 48,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 36 (for tile 4,2 starting at 64,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 37 (for tile 5,2 starting at 80,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 38 (for tile 6,2 starting at 96,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 39 (for tile 7,2 starting at 112,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 40 (for tile 8,2 starting at 128,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 41 (for tile 9,2 starting at 144,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 42 (for tile 10,2 starting at 160,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 43 (for tile 11,2 starting at 176,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 44 (for tile 12,2 starting at 192,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 45 (for tile 13,2 starting at 208,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 46 (for tile 14,2 starting at 224,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 47 (for tile 15,2 starting at 240,32): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 48 (for tile 0,3 starting at 0,48): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 49 (for tile 1,3 starting at 16,48): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 50 (for tile 2,3 starting at 32,48): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 51 (for tile 3,3 starting at 48,48): Minimum = 0.000, Maximum = 0.110, Average = 0.001, Standard Deviation = 0.008	Result 52 (for tile 4,3 starting at 64,48): Minimum = 0.000, Maximum = 0.333, Average = 0.027, Standard Deviation = 0.081	Result 53 (for tile 5,3 starting at 80,48): Minimum = 0.000, Maximum = 0.333, Average = 0.028, Standard Deviation = 0.083	Result 54 (for tile 6,3 starting at 96,48): Minimum = 0.000, Maximum = 0.333, Average = 0.021, Standard Deviation = 0.065	Result 55 (for tile 7,3 starting at 112,48): Minimum = 0.000, Maximum = 0.165, Average = 0.004, Standard Deviation = 0.020	Result 56 (for tile 8,3 starting at 128,48): Minimum = 0.000, Maximum = 0.161, Average = 0.006, Standard Deviation = 0.023	Result 57 (for tile 9,3 starting at 144,48): Minimum = 0.000, Maximum = 0.165, Average = 0.014, Standard Deviation = 0.041	Result 58 (for tile 10,3 starting at 160,48): Minimum = 0.000, Maximum = 0.196, Average = 0.015, Standard Deviation = 0.044	Result 59 (for tile 11,3 starting at 176,48): Minimum = 0.000, Maximum = 0.157, Average = 0.008, Standard Deviation = 0.025	Result 60 (for tile 12,3 starting at 192,48): Minimum = 0.000, Maximum = 0.027, Average = 0.000, Standard Deviation = 0.002	Result 61 (for tile 13,3 starting at 208,48): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 62 (for tile 14,3 starting at 224,48): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 63 (for tile 15,3 starting at 240,48): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 64 (for tile 0,4 starting at 0,64): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 65 (for tile 1,4 starting at 16,64): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 66 (for tile 2,4 starting at 32,64): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 67 (for tile 3,4 starting at 48,64): Minimum = 0.000, Maximum = 0.333, Average = 0.027, Standard Deviation = 0.081	Result 68 (for tile 4,4 starting at 64,64): Minimum = 0.443, Maximum = 1.000, Average = 0.945, Standard Deviation = 0.115	Result 69 (for tile 5,4 starting at 80,64): Minimum = 0.667, Maximum = 1.000, Average = 0.971, Standard Deviation = 0.083	Result 70 (for tile 6,4 starting at 96,64): Minimum = 0.302, Maximum = 1.000, Average = 0.788, Standard Deviation = 0.196	Result 71 (for tile 7,4 starting at 112,64): Minimum = 0.000, Maximum = 0.780, Average = 0.426, Standard Deviation = 0.218	Result 72 (for tile 8,4 starting at 128,64): Minimum = 0.000, Maximum = 0.498, Average = 0.191, Standard Deviation = 0.136	Result 73 (for tile 9,4 starting at 144,64): Minimum = 0.310, Maximum = 0.733, Average = 0.503, Standard Deviation = 0.090	Result 74 (for tile 10,4 starting at 160,64): Minimum = 0.333, Maximum = 0.737, Average = 0.651, Standard Deviation = 0.113	Result 75 (for tile 11,4 starting at 176,64): Minimum = 0.047, Maximum = 0.737, Average = 0.413, Standard Deviation = 0.224	Result 76 (for tile 12,4 starting at 192,64): Minimum = 0.000, Maximum = 0.082, Average = 0.006, Standard Deviation = 0.018	Result 77 (for tile 13,4 starting at 208,64): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 78 (for tile 14,4 starting at 224,64): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 79 (for tile 15,4 starting at 240,64): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 80 (for tile 0,5 starting at 0,80): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 81 (for tile 1,5 starting at 16,80): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 82 (for tile 2,5 starting at 32,80): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 83 (for tile 3,5 starting at 48,80): Minimum = 0.000, Maximum = 0.333, Average = 0.028, Standard Deviation = 0.083	Result 84 (for tile 4,5 starting at 64,80): Minimum = 0.533, Maximum = 1.000, Average = 0.927, Standard Deviation = 0.116	Result 85 (for tile 5,5 starting at 80,80): Minimum = 0.502, Maximum = 0.996, Average = 0.779, Standard Deviation = 0.151	Result 86 (for tile 6,5 starting at 96,80): Minimum = 0.000, Maximum = 0.925, Average = 0.488, Standard Deviation = 0.305	Result 87 (for tile 7,5 starting at 112,80): Minimum = 0.000, Maximum = 0.380, Average = 0.157, Standard Deviation = 0.091	Result 88 (for tile 8,5 starting at 128,80): Minimum = 0.055, Maximum = 0.733, Average = 0.402, Standard Deviation = 0.185	Result 89 (for tile 9,5 starting at 144,80): Minimum = 0.263, Maximum = 0.737, Average = 0.638, Standard Deviation = 0.116	Result 90 (for tile 10,5 starting at 160,80): Minimum = 0.251, Maximum = 0.737, Average = 0.611, Standard Deviation = 0.177	Result 91 (for tile 11,5 starting at 176,80): Minimum = 0.000, Maximum = 0.737, Average = 0.313, Standard Deviation = 0.304	Result 92 (for tile 12,5 starting at 192,80): Minimum = 0.000, Maximum = 0.008, Average = 0.000, Standard Deviation = 0.000	Result 93 (for tile 13,5 starting at 208,80): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 94 (for tile 14,5 starting at 224,80): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 95 (for tile 15,5 starting at 240,80): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 96 (for tile 0,6 starting at 0,96): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 97 (for tile 1,6 starting at 16,96): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 98 (for tile 2,6 starting at 32,96): Minimum = 0.000, Maximum = 0.000, Average = 0.000, Standard Deviation = 0.000	Result 99 (for tile 3,6 starting at 48,96): Minimum = 0.000, Maximum = 0.333, Average = 0.027, Standard Deviation = 0.080	Result 100 (for tile 4,6 starting at 64,96): Minimum = 0.498, Maximum = 1.000, Average = 0.693, Standard Deviation = 0.184	Result 101 (for tile 5,6 starting at 80,96): Minimum = 0.000, Maximum = 0.686


Discussion

Loading comments...