1 / 47

Tessellation in a Low Poly World

Tessellation in a Low Poly World. Nicolas Thibieroz AMD Graphics Products Group nicolas.thibieroz@amd.com Original materials from Bill Bilodeau. GDC Paris 2008. Low. Medium. High. What is Tessellation?. Tessellation is the process of adding new primitives into an existing model

cutter
Download Presentation

Tessellation in a Low Poly World

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Tessellation in a Low Poly World Nicolas Thibieroz AMD Graphics Products Group nicolas.thibieroz@amd.com Original materials from Bill Bilodeau GDC Paris 2008

  2. Low Medium High What is Tessellation? • Tessellation is the process of adding new primitives into an existing model • Triangle counts can be “dialed in” by adjusting the tessellation level

  3. Input Assembler Tessellator Vertex Shader Rasterizer Pixel Shader AMD Hardware Tessellator Memory / Resources Memory / Resources Output Merger

  4. Hardware tessellation allows you to render more polygons for better silhouettes Initial concept artwork from Bay Raitt, Valve

  5. Animated Control Cage Pixel Shader Vertex Shader Vertex Shader Pixel Shader Tessellator Surface control cages are easier to work with than individual triangles • Artists prefer to create models this way • Animations are simpler on a control cage • Control cage can be animated on the GPU, then tessellated in a second pass R2VB

  6. Hardware tessellation is a form of compression • Smaller footprint – you only need to store the control cage and possibly a displacement map • Improved bandwidth – less data to transfer from memory to GPU

  7. Three types of primitives, or “superprims”, are supported • Triangles • Quads • Lines

  8. There are two tessellation modes • - Continuous • - Adaptive

  9. Continuous Tessellation • Specify floating point tessellation level per-draw call • Tessellation levels range from 1.0 to 14.99 • Eliminates popping as vertices are added through tessellation Level 2.0 Level 1.0

  10. Level = 1.7 Level = 1.0 Level = 1.1 Level = 1.3 Level = 2.0 Continuous Tessellation • Specify floating point tessellation level per-draw call • Tessellation levels range from 1.0 to 14.99 • Eliminates popping as vertices are added through tessellation Level 2.0 Level 1.0

  11. Edge tessellation factor = 7.x Edge tessellation factor = 3.x Edge tessellation factor = 3.x Edge tessellation factor = 3.x Edge tessellation factor = 3.x Edge tessellation factor = 5.x Edge tessellation factor = 5.x Adaptive allows different levels of tessellation within the same mesh

  12. Transformed Superprim Mesh Pixel Shader Superprim Mesh Vertex Shader Superprim Mesh Vertex Shader Superprim Mesh Vertex Shader Pixel Shader Sampler R2VB Tessellation Factors Stream 1 Pixel Shader Tessellator Stream 0 Adaptive tessellation can be done in real-time using multiple passes

  13. Code Example: Continuous Tessellation // Enable tessellation: TSSetTessellationMode( pd3dDevice, TSMD_ENABLE_CONTINUOUS ); // Set tessellation level: TSSetMaxTessellationLevel( pd3dDevice, sg_fMaxTessellationLevel ); // Select appropriate technique to render our tessellated objects: sg_pEffect->SetTechnique( "RenderTessellatedDisplacedScene" ); // Render all passes with tessellation V( sg_pEffect->Begin( &cPasses, 0 ) ); for ( iPass = 0; iPass < cPasses; iPass++ ) { V( sg_pEffect->BeginPass( iPass ) ); V( TSDrawMeshSubset( sg_pMesh, 0 ) ); V( sg_pEffect->EndPass() ); } V( sg_pEffect->End() ); // Disable tessellation: TSSetTessellationMode( pd3dDevice, TSMD_DISABLE );

  14. (Evaluation Shader) Vertex Shader Tessellator Super-prim Mesh Tessellated Mesh Tessellated and Displaced Mesh Sampler Displacement Map The vertex shader is used as an evaluation shader

  15. Example Code: Evaluation Vertex Shader struct VsInputTessellated { // Barycentric weights for this vertex float3 vBarycentric: BLENDWEIGHT0; // Data from superprim vertex 0: float4 vPositionVert0 : POSITION0; float2 vTexCoordVert0 : TEXCOORD0; float3 vNormalVert0 : NORMAL0; // Data from superprim vertex 1: float4 vPositionVert1 : POSITION4; float2 vTexCoordVert1 : TEXCOORD4; float3 vNormalVert1 : NORMAL4; // Data from superprim vertex 2: float4 vPositionVert2 : POSITION8; float2 vTexCoordVert2 : TEXCOORD8; float3 vNormalVert2 : NORMAL8; };

  16. Example Code: Evaluation Vertex Shader VsOutputTessellated VSRenderTessellatedDisplaced( VsInputTessellated i ) { VsOutputTessellated o; // Compute new position based on the barycentric coordinates: float3 vPosTessOS = i.vPositionVert0.xyz * i.vBarycentric.x + i.vPositionVert1.xyz i.vBarycentric.y + i.vPositionVert2.xyz * i.vBarycentric.z; // Output world-space position: o.vPositionWS = vPosTessOS; // Compute new normal vector for the tessellated vertex: o.vNormalWS = i.vNormalVert0.xyz * i.vBarycentric.x + i.vNormalVert1.xyz * i.vBarycentric.y + i.vNormalVert2.xyz * i.vBarycentric.z; // Compute new texture coordinates based on the barycentric coordinates: o.vTexCoord = i.vTexCoordVert0.xy * i.vBarycentric.x + i.vTexCoordVert1.xy * i.vBarycentric.y + i.vTexCoordVert2.xy * i.vBarycentric.z; // Displace the tessellated vertex (sample the displacement map) o.vPositionWS = DisplaceVertex( vPosTessOS, o.vTexCoord, o.vNormalWS ); // Transform position to screen-space: o.vPosCS =mul( float4( o.vPositionWS, 1.0 ), g_mWorldViewProjection ); return o; } // End of VsOutputTessellated VSRenderTessellatedDisplaced(..)

  17. Bezier Control Points Tessellator Vertex Shader (u,v) P0,0, P0,1 …P3,3 Sampler What if you want to do more? • DirectX 9 has a limit of 15 float4 vertex input components – High order surfaces need more inputs • TSToggleIndicesRetrieval() allows you to fetch the super-prim data from a vertex texture

  18. Other Tessellation Library Functions • TSDrawIndexed(…) • Analogous to DrawIndexedPrimitive(…) • TSDrawNonIndexed(…) • Needed for adaptive tessellation, since every edge needs its own tessellation level • TSSetMinTessellationLevel(…) • Sets the minimum tessellation level for adaptive tessellation • TSComputeNumTessellatedPrimitives(…) • Calculates the number of tessellated primitives that will be generated by the tessellator

  19. Displacement mapping alters tangent space • To do normal mapping we need to rotate tangent space • Alternatively, use model space normal maps • Doesn’t work with animation or tiling

  20. Displacement map lighting • Use the displacement map to calculate the per-pixel normal • Central differencing with neighboring displacements can approximate the derivative • Light with the computed normal • No need to use a normal map

  21. Terrain Rendering: Performance Results Both use the same displacement map (2K x 2K) and identical pixel shaders Rendering with tessellation is > 6X faster and provides memory savings over 44MB! Subtracting the cost of shading

  22. Terrain Tessellation Sample

  23. AMD GPU MeshMapper New tool for generate normal, displacement, and ambient occlusion maps from hi-res and low-res mesh pairs

  24. Advantages of the Tessellator • Saves memory bandwidth and reduces memory footprint • Flexible support for displacement mapping and many kinds of high order surfaces • Easier content creation – artists and animators only need to work with low resolution geometry • Continuous LOD avoids unnecessary triangles • The tessellator is available now on the Xbox 360 and the latest ATI Radeon and FireGL graphics cards • Public availability of tessellation SDK very soon

  25. Harnessing the Power of Multiple GPUs Nicolas Thibieroz AMD Graphics Products Group nicolas.thibieroz@amd.com Original materials from Jon Story & Holger Grün GDC Paris 2008

  26. Why MGPU? • MGPUs can be used to dramatically increase performance and visual quality • At higher screen resolutions • Especially with increased use of MSAA • Many applications become GPU limited at higher screen resolutions • High resolution monitors => mainstream affordability • Achieve next generation performance on today‘s HW • Prototype your next engine • Provides an upgrade path for mainstream parts

  27. Multiple Boards • An increasing number of motherboards can accept 2 or more discrete video cards • Connected by high speed crossover cables • Now possible to fit 4 Radeon HD3850 boards to a single motherboard • CrossFireX technology allows you to harness that performance 2x 4x

  28. Multiple GPUs per Board • The Radeon HD3870 X2 is a single-board multi-GPU architecture • AFR is on by default • Heavy peer to peer communication • Bi-directional 16x lane pipe connecting the 2 GPUs • CrossFireX supports 2 HD3870 X2 boards for Quad GPU performance 2x 4x

  29. Hybrid Crossfire • Combination of integrated and discrete graphics • 3D graphics performance boost • Laptops • Mainstream desktop PCs • Use less power during non-taxing graphical tasks

  30. CrossFire Rendering Modes • Split Frame Rendering / Scissor • Screen is divided into number of GPUs • Dynamic load balancing • Alternate Frame Rendering • GPUs take alternate frames • Vertex processing not duplicated • Highest performing mode

  31. How does AFR Work? CPU GPU0 (Frame N) GPU1 (Frame N+1) Command Command Command Command Command Command Command Command Command Command Command Command

  32. Hardware Considerations • Current MGPU setups are not shared memory architectures • Resources placed in local video memory are duplicated for each GPU • Driver initiates peer to peer (P2P) copies to keep resources in sync • On some chipsets this may involve the CPU • Synchronizes all GPUs • Very heavy impact on performance that can even result in negative scaling

  33. Driver Modes • Compatible AFR Mode • Default mode • Driver checks for AFR unfriendly behaviour • Will P2P copy stale resources • Full AFR Mode (Application Profile) • Driver recognises EXE name • Use a unique name and don‘t change it • Behaviour fully guided by profile • Best performance – no checking • Rename EXE to “AFR-FriendlyD3D.exe“ • Use “AFR-FriendlyOGL.exe“ for OpenGL • No checking : Speed & compatibility test

  34. Detecting the Number of GPUs • Visit http://ati.amd.com/developer • Download project called “CrossFire Detect“ • Statically link to: • “atimgpud_s_x86.lib“ 32 bit version • “atimgpud_s_x64.lib“ 64 bit version • Include header file: • “atimgpud.h“ • Call this function: • INT count = AtiMultiGPUAdapters();

  35. Common Pitfalls & Solutions

  36. Pitfall: Dependencies Between Frames resource A resource A GPU0 (Frame N) GPU1 (Frame N+1) Present (N-1) Draw using A Update resource A Draw using A P2P copy from GPU0 to GPU1 Update resource A Present (N) Present (N+1)

  37. Solution: Resources that Change Every Frame resource A resource A GPU0 (Frame N) GPU1 (Frame N+1) Present (N-1) Update resource A Draw using A Update resource A Draw using A Present (N) Present (N+1)

  38. Solution: Resources that Change Every Few Frames resource A resource A GPU0 (Frame N) GPU1 (Frame N+1) Present (N-1) Update resource A Draw using A Update resource A Draw using A Present (N) Present (N+1) Draw using A Draw using A Present (N+2) Present (N+3) Draw using A Present (N+4)

  39. Pitfalls: In DX10 there are Other Ways to Update Resources... • Drawing to vertex/index buffers • Stream Out • CopyResource() calls • CopySubresourceRegion() calls • GenerateMips() calls • ResolveSubresource() calls

  40. Waiting starves GPU queues Pitfall: Waiting on Queries Waiting limits parallelism CPU Waiting for Query Result!!! Waiting => CPU limitation GPU0 (Frame N) GPU1 (Frame N+1) Command Command Command Command Command Command Command Command Command Command Command Command

  41. Solution: Queries • Avoid using queries whenever possible • - For occlusion queries consider a CPU-based approach • Avoid waiting on query results • - Pick up the result of a query at least N-GPU frames after it was issued • For queries issued every frame • - Create additional query objects for each GPU • - Cycle through them

  42. Pitfall: CPU Access to a Renderable Resource • When the CPU locks a renderable resource it must wait for all GPUs to finish using the resource before acquiring the pointer • All GPUs now have to wait until the CPU unlocks the resource pointer • After the unlock the driver has to update the resource on each GPU via P2P copies • Just don‘t do this – it destroys performance even on a single GPU setup, and is catastrophic for MGPUs

  43. Solutions: Locks / Maps • In DX10 stream to and copy from STAGING textures • In DX9 StretchRect() is always better than Lock() • At resource creation time use the appropriate flags from: • D3D10_USAGE • D3D10_CPU_ACCESS_FLAG • In DX9 never lock static Vertex/Index Buffers because it will cause P2P copies

  44. Concluding Pitfalls & Solutions • Drivers take a conservative approach • Performs checks on resource synchronization • P2P copy if necessary • You know the application best • Determine if a P2P copy is necessary • Talk to us about a profile

  45. AFR-Friendly SDK Sample • Part of the ATI developer SDK • http://ati.amd.com/developer • Detects the number of GPUs • Correctly deals with textures used as render targets • Provides a solution for dealing with mouse cursor lag • Go and take a look!!

  46. Call to Action • MGPUs provide demonstrable performance gains • MGPUs boost visual quality • Plan from day one to make your rendering scale • Detect the number of GPUs • Regularly check for AFR unfriendly behavior • Talk to us...

  47. QUESTIONS? • ? nicolas.thibieroz@amd.com

More Related