Compute Shader for Terrain Rendering
2,591
1
Advertisement
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!
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:
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
Advertisement
Advertisement
Advertisement
Discussion