рдореЗрд╖реЛрдкреНрдЯрд╛рдЗрдЬрд╝рд░ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЗ рджреМрд░рд╛рди, рдЕрдХреНрд╕рд░ рдпрд╣ рд╕рд╡рд╛рд▓ рдЙрдарддрд╛ рд╣реИ: "рдХреНрдпрд╛ рдпрд╣ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо SIMD рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реИ?"
рдкреБрд╕реНрддрдХрд╛рд▓рдп рдкреНрд░рджрд░реНрд╢рди-рдЙрдиреНрдореБрдЦ рд╣реИ, рд▓реЗрдХрд┐рди SIMD рд╣рдореЗрд╢рд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЧрддрд┐ рд▓рд╛рдн рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, SIMD рдХреЛрдб рдХреЛ рдХрдо рдкреЛрд░реНрдЯреЗрдмрд▓ рдФрд░ рдХрдо рд░рдЦрд░рдЦрд╛рд╡ рдпреЛрдЧреНрдп рдмрдирд╛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдкреНрд░рддреНрдпреЗрдХ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╕рдордЭреМрддрд╛ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдЬрдм рдкреНрд░рджрд░реНрд╢рди рд╕рд░реНрд╡реЛрдкрд░рд┐ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ SSE рдФрд░ NEON рдирд┐рд░реНрджреЗрд╢ рд╕реЗрдЯ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ SIMD рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдФрд░ рдмрдирд╛рдП рд░рдЦрдирд╛ рд╣реЛрдЧрд╛ред рдЕрдиреНрдп рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдЖрдкрдХреЛ рдпрд╣ рд╕рдордЭрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ SIMD рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рднрд╛рд╡ рдХреНрдпрд╛ рд╣реИред рдЖрдЬ рд╣рдо SSEn / AVXn рдирд┐рд░реНрджреЗрд╢ рд╕реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рдЬреЛрдбрд╝реЗ рдЧрдП рдПрдХ рдирдП рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдореИрд▓рд╛ рдвреЛрдиреЗ рд╡рд╛рд▓реЗ рд╕рд░рд▓реАрдХрд░рдг рдХреЛ рдЧрддрд┐ рджреЗрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗред

рд╣рдорд╛рд░реЗ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдХреЗ рд▓рд┐рдП, рд╣рдо рдерд╛рдИ рдмреБрджреНрдз рдореЙрдбрд▓ рдХреЛ 6 рдорд┐рд▓рд┐рдпрди рддреНрд░рд┐рдХреЛрдг рд╕реЗ рдЗрд╕ рд╕рдВрдЦреНрдпрд╛ рдХреЗ 0.1% рддрдХ рд╕рд░рд▓ рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рд▓рдХреНрд╖реНрдп x64 рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЗ рд▓рд┐рдП Microsoft Visual Studio 2019 рдХрдВрдкрд╛рдЗрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд╕реНрдХреЗрд▓рд░ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдПрдХ рдЗрдВрдЯреЗрд▓ рдХреЛрд░ i7-8700K рдереНрд░реЗрдб (~ 4.4 рд╣рд░реНрдЯреНрдЬ рдкрд░) рдореЗрдВ рд▓рдЧрднрдЧ 210 рдПрдордПрд╕ рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдХреЗ рдпреБрдХреНрддрд┐рдХрд░рдг рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рд▓рдЧрднрдЧ 28.5 рдорд┐рд▓рд┐рдпрди рддреНрд░рд┐рдХреЛрдг рд╕реЗ рдореЗрд▓ рдЦрд╛рддреА рд╣реИред рд╢рд╛рдпрдж рдпрд╣ рдЕрднреНрдпрд╛рд╕ рдореЗрдВ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдЙрдкрдХрд░рдгреЛрдВ рдХреА рдЕрдзрд┐рдХрддрдо рдХреНрд╖рдорддрд╛рдУрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрддреНрд╕реБрдХ рдерд╛ред
рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдЧреНрд░рд┐рдб рдХреЛ рдЯреБрдХрдбрд╝реЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдХреЗ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╕рдорд╛рдирд╛рдВрддрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕реАрдорд╛рдУрдВ рдХреЛ рдмрдирд╛рдП рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрдиреЗрдХреНрдЯрд┐рд╡рд┐рдЯреА рдХрд╛ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЕрдм рд╣рдо рдЦреБрдж рдХреЛ рд╡рд┐рд╢реБрджреНрдз рд░реВрдк рд╕реЗ SIMD рдЕрдиреБрдХреВрд▓рди рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдмрдВрдзрд┐рдд рдХрд░реЗрдВрдЧреЗред
рд╕рд╛рдд рдорд╛рдк
рдЕрдиреБрдХреВрд▓рди рдХреА рд╕рдВрднрд╛рд╡рдирд╛рдУрдВ рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо Intel VTune рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░реЛрдлрд╛рдЗрд▓рд┐рдВрдЧ рдХрд░реЗрдВрдЧреЗред рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ 100 рдмрд╛рд░ рдЪрд▓рд╛рдПрдВ рдХрд┐ рдкрд░реНрдпрд╛рдкреНрдд рдбреЗрдЯрд╛ рд╣реИред

рдпрд╣рд╛рдВ рдореИрдВрдиреЗ рдкреНрд░рддреНрдпреЗрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рд╕рдордп рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕рд╛рде рд╣реА рдмрд╛рдзрд╛рдУрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдорд╛рдЗрдХреНрд░реЛрдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдореЛрдб рдЪрд╛рд▓реВ рдХрд┐рдпрд╛ред рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдПрдХ рд╕реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдпреБрдХреНрддрд┐рдХрд░рдг рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЛ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдЪрдХреНрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдХрд╛рд░реНрдпреЛрдВ рдХреА рд╕реВрдЪреА рд╕рдордп рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХреНрд░рдордмрджреНрдз рд╣реЛрддреА рд╣реИред рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рд╕рдордЭрдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╡реЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдХреНрд░рдо рдореЗрдВ рд╣реИрдВ:
rescalePositions
рдПрдХ рд╣реА рдХреНрдпреВрдм рдореЗрдВ рд╕рднреА рдХреЛрдиреЗ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп rescalePositions
рд╣реИ, рдЬреЛ computeVertexIds
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрд░рд┐рдорд╛рдгреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ computeVertexIds
computeVertexIds
рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рдЖрдХрд╛рд░ рдХреЗ рдПрдХ рд╕рдорд╛рди рдЧреНрд░рд┐рдб рдкрд░ рдкреНрд░рддреНрдпреЗрдХ рд╢реАрд░реНрд╖ рдХреЗ рд▓рд┐рдП рдПрдХ 30-рдмрд┐рдЯ рдкрд░рд┐рдорд╛рдгрд┐рдд рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рдкреНрд░рддреНрдпреЗрдХ рдЕрдХреНрд╖ рдХреЛ рдЧреНрд░рд┐рдб рдкрд░ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдЧреНрд░рд┐рдб рдЖрдХрд╛рд░ 10 рдмрд┐рдЯ, рдЗрд╕рд▓рд┐рдП рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ 30 рд╣реИ)countTriangles
рддреНрд░рд┐рдХреЛрдг рдХреА рдЕрдиреБрдорд╛рдирд┐рдд рд╕рдВрдЦреНрдпрд╛ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдПрдХ рдЧреНрд░рд┐рдб рдЧреНрд░рд┐рдб рдореЗрдВ рд╕рднреА рдХреЛрдиреЗ рдХреЗ рдорд┐рд▓рди рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП рдЗрдиреЛрд╡реЗрдЯрд░ рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рдЧреНрд░рд┐рдб рдХреЗ рдЖрдХрд╛рд░ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдЧрд╛редfillVertexCells
рдПрдХ рддрд╛рд▓рд┐рдХрд╛ рднрд░рддрд╛ рд╣реИ рдЬреЛ рд╕рдВрдмрдВрдзрд┐рдд рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЗ рд╕рднреА рдХреЛрдиреЗ рдХреЛ fillVertexCells
рдХрд░рддрд╛ рд╣реИ; рдПрдХ рд╣реА рдЖрдИрдбреА рдХреЗ рд╕рд╛рде рд╕рднреА рдХреЛрдиреЗ рдПрдХ рд╕реЗрд▓ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реИрдВfillCellQuadrics
рд╕реЗрд▓ рдЬреНрдпрд╛рдорд┐рддрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рдордЧреНрд░ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдкреНрд░рддрд┐рдмрд┐рдВрдмрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рддреНрдпреЗрдХ рдХреЛрд╢рд┐рдХрд╛ рдХреЗ рд▓рд┐рдП Quadric
рд╕рдВрд░рдЪрдирд╛ ( Quadric
рд╕рдордорд┐рдд рдореИрдЯреНрд░рд┐рдХреНрд╕) рднрд░рддрд╛ рд╣реИfillCellRemap
рдкреНрд░рддреНрдпреЗрдХ рд╕реЗрд▓ рдХреЗ рд▓рд┐рдП рд╡рд░реНрдЯреЗрдХреНрд╕ рдЗрдВрдбреЗрдХреНрд╕ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕ рд╕реЗрд▓ рдореЗрдВ рдПрдХ рдХреЛрдиреЗ рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реИ, рдФрд░ fillCellRemap
рдХрдо рдХрд░рддрд╛ рд╣реИfilterTriangles
рдкрд╣рд▓реЗ рдмрдирд╛рдП рдЧрдП рд╡рд░реНрдЯреЗрдХреНрд╕-рд╕реЗрд▓-рд╡рд░реНрдЯреЗрдХреНрд╕ рдЯреЗрдмрд▓ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рддреНрд░рд┐рдХреЛрдг рдХрд╛ рдЕрдВрддрд┐рдо рд╕реЗрдЯ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ; рдЕрдиреБрднрд╡рд╣реАрди рдЕрдиреБрд╡рд╛рдж рдФрд╕рддрди ~ 5% рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рддреНрд░рд┐рдХреЛрдг рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдлрд╝рдВрдХреНрд╢рди рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рддрд╛ рд╣реИред
computeVertexIds
рдФрд░
countTriangles
рдХреЛ рдХрдИ рдмрд╛рд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо
countTriangles
рд▓рд┐рдП рдореЗрд╖ рдЖрдХрд╛рд░ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ, рддреНрд░рд┐рдХреЛрдг рдХреА рд▓рдХреНрд╖реНрдп рд╕рдВрдЦреНрдпрд╛ (рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ 6000) рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рддреНрд╡рд░рд┐рдд рдмрд╛рдЗрдирд░реА рдЦреЛрдЬ рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рдХрд░рддрд╛ рд╣реИ рдФрд░ рддреНрд░рд┐рдХреЛрдг рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рдореЗрд╖ рдЖрдХрд╛рд░ рдкреНрд░рддреНрдпреЗрдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдкрд░ рдЙрддреНрдкрдиреНрди рдХрд░реЗрдЧрд╛ред рдЕрдиреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдПрдХ рдмрд╛рд░ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рдорд╛рд░реА рдлрд╝рд╛рдЗрд▓ рдореЗрдВ, рдкрд╛рдВрдЪ рдЦреЛрдЬ рдкрд╛рд╕ 40
3 рдХрд╛ рд▓рдХреНрд╖реНрдп рдЬрд╛рд▓ рдЖрдХрд╛рд░ рджреЗрддреЗ рд╣реИрдВред
VTune рдорджрдж рд╕реЗ рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рд╕рдмрд╕реЗ рд╕рдВрд╕рд╛рдзрди-рдЧрд╣рди рдлрд╝рдВрдХреНрд╢рди рд╡рд╣ рд╣реИ рдЬреЛ рдХреНрд╡рд╛рдбрдЯреНрд░рд┐рдХреНрд╕ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ: рдпрд╣ 21 рдПрд╕ рдХреЗ рдХреБрд▓ рдирд┐рд╖реНрдкрд╛рджрди рд╕рдордп рдХрд╛ рд▓рдЧрднрдЧ рдЖрдзрд╛ рд▓реЗрддрд╛ рд╣реИред рдпрд╣ SIMD рдХреЗ рдЕрдиреБрдХреВрд▓рди рдХреЗ рд▓рд┐рдП рдкрд╣рд▓рд╛ рд▓рдХреНрд╖реНрдп рд╣реИред
SIMD рдЯреБрдХрдбрд╝рд╛ рджреНрд╡рд╛рд░рд╛ рдЯреБрдХрдбрд╝рд╛
рдЪрд▓реЛ рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреНрдпрд╛ рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ, рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП
fillCellQuadrics
рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:
static void fillCellQuadrics(Quadric* cell_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* vertex_cells) { for (size_t i = 0; i < index_count; i += 3) { unsigned int i0 = indices[i + 0]; unsigned int i1 = indices[i + 1]; unsigned int i2 = indices[i + 2]; unsigned int c0 = vertex_cells[i0]; unsigned int c1 = vertex_cells[i1]; unsigned int c2 = vertex_cells[i2]; bool single_cell = (c0 == c1) & (c0 == c2); float weight = single_cell ? 3.f : 1.f; Quadric Q; quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], weight); if (single_cell) { quadricAdd(cell_quadrics[c0], Q); } else { quadricAdd(cell_quadrics[c0], Q); quadricAdd(cell_quadrics[c1], Q); quadricAdd(cell_quadrics[c2], Q); } } }
рдлрд╝рдВрдХреНрд╢рди рд╕рднреА рддреНрд░рд┐рднреБрдЬреЛрдВ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдХрд░рддрд╛ рд╣реИ, рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреНрд╡рд╛рдбреНрд░рд┐рдХ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рд╕реЗрд▓ рдХреЗ рдХреНрд╡рд╛рдбреНрд░рд┐рдХреНрд╕ рдореЗрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИред рдХреНрд╡рд╛рдбреНрд░рд┐рдХ - 4 ├Ч 4 рд╕рдордорд┐рдд рдореИрдЯреНрд░рд┐рдХреНрд╕, 10 рдлреНрд▓реЛрдЯрд┐рдВрдЧ-рдкреЙрдЗрдВрдЯ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
struct Quadric { float a00; float a10, a11; float a20, a21, a22; float b0, b1, b2, c; };
рдПрдХ рдЪрддреБрд╖реНрдХреЛрдг рдХреА рдЧрдгрдирд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рддреНрд░рд┐рднреБрдЬ рдХреЗ рд▓рд┐рдП рд╕рдорддрд▓ рд╕рдореАрдХрд░рдг рдХреЛ рд╣рд▓ рдХрд░рдирд╛ рд╣реЛрддрд╛ рд╣реИ, рдПрдХ рджреНрд╡рд┐рдШрд╛рдд рдореИрдЯреНрд░рд┐рдХреНрд╕ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдирд╛ рдФрд░ рдЗрд╕реЗ рддреНрд░рд┐рднреБрдЬ рдХреЗ рдХреНрд╖реЗрддреНрд░рдлрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рддреМрд▓рдирд╛:
static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d) { Q.a00 = a * a; Q.a10 = b * a; Q.a11 = b * b; Q.a20 = c * a; Q.a21 = c * b; Q.a22 = c * c; Q.b0 = d * a; Q.b1 = d * b; Q.b2 = d * c; Qc = d * d; } static void quadricFromTriangle(Quadric& Q, const Vector3& p0, const Vector3& p1, const Vector3& p2, float weight) { Vector3 p10 = {p1.x - p0.x, p1.y - p0.y, p1.z - p0.z}; Vector3 p20 = {p2.x - p0.x, p2.y - p0.y, p2.z - p0.z}; Vector3 normal = { p10.y * p20.z - p10.z * p20.y, p10.z * p20.x - p10.x * p20.z, p10.x * p20.y - p10.y * p20.x }; float area = normalize(normal); float distance = normal.x*p0.x + normal.y*p0.y + normal.z*p0.z; quadricFromPlane(Q, normal.x, normal.y, normal.z, -distance); quadricMul(Q, area * weight); }
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдлреНрд▓реЛрдЯрд┐рдВрдЧ рдкреЙрдЗрдВрдЯ рдСрдкрд░реЗрд╢рди рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ SIMD рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдорд╛рдирд╛рдВрддрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрдХреНрдЯрд░ рдХреЛ 4-рд╡реНрдпрд╛рдкреА SIMD рд╡реЗрдХреНрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ
Quadric
рд╣реИрдВ, рдФрд░
Quadric
рд╕рдВрд░рдЪрдирд╛ рдХреЛ 10 рдХреЗ рдмрдЬрд╛рдп 12 рдлрд╝реНрд▓реЛрдЯрд┐рдВрдЧ рдкреЙрдЗрдВрдЯ рдирдВрдмрд░реЛрдВ рдореЗрдВ рдмрджрд▓рддреЗ рд╣реИрдВ, рддрд╛рдХрд┐ рдпрд╣ рддреАрди SIMD рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдореЗрдВ рд╕рдЯреАрдХ рд░реВрдк рд╕реЗ рдлрд┐рдЯ рд╣реЛ рдЬрд╛рдП (рдЖрдХрд╛рд░ рдореЗрдВ рд╡реГрджреНрдзрд┐ рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдирд╣реАрдВ рдХрд░рддреА) рдФрд░ рдлрд╝реАрд▓реНрдбреНрд╕ рдХреЗ рдХреНрд░рдо рдХреЛ рдмрджрд▓ рджреЗрдВ рддрд╛рдХрд┐ рдЧрдгрдирд╛ рдХрд░реЗрдВ
quadricFromPlane
рдЕрдзрд┐рдХ рд╕рдорд╛рди рд╣реЛ рдЧрдпрд╛:
struct Quadric { float a00, a11, a22; float pad0; float a10, a21, a20; float pad1; float b0, b1, b2, c; };
рдпрд╣рд╛рдВ, рдХреБрдЫ рдЧрдгрдирд╛, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕реНрдХреЗрд▓рд░ рдЙрддреНрдкрд╛рдж, рдПрд╕рдПрд╕рдИ рдХреЗ рдкреБрд░рд╛рдиреЗ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХреЗ рдЕрдиреБрд░реВрдк рдирд╣реАрдВ рд╣реИрдВред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдПрдХ рд╕реНрдХреЗрд▓рд░ рдЙрддреНрдкрд╛рдж рдХреЗ рд▓рд┐рдП рдПрдХ рдирд┐рд░реНрджреЗрд╢ SSE4.1 рдореЗрдВ рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛, рдЬреЛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рд╣реИред
static void fillCellQuadrics(Quadric* cell_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* vertex_cells) { const int yzx = _MM_SHUFFLE(3, 0, 2, 1); const int zxy = _MM_SHUFFLE(3, 1, 0, 2); const int dp_xyz = 0x7f; for (size_t i = 0; i < index_count; i += 3) { unsigned int i0 = indices[i + 0]; unsigned int i1 = indices[i + 1]; unsigned int i2 = indices[i + 2]; unsigned int c0 = vertex_cells[i0]; unsigned int c1 = vertex_cells[i1]; unsigned int c2 = vertex_cells[i2]; bool single_cell = (c0 == c1) & (c0 == c2); __m128 p0 = _mm_loadu_ps(&vertex_positions[i0].x); __m128 p1 = _mm_loadu_ps(&vertex_positions[i1].x); __m128 p2 = _mm_loadu_ps(&vertex_positions[i2].x); __m128 p10 = _mm_sub_ps(p1, p0); __m128 p20 = _mm_sub_ps(p2, p0); __m128 normal = _mm_sub_ps( _mm_mul_ps( _mm_shuffle_ps(p10, p10, yzx), _mm_shuffle_ps(p20, p20, zxy)), _mm_mul_ps( _mm_shuffle_ps(p10, p10, zxy), _mm_shuffle_ps(p20, p20, yzx))); __m128 areasq = _mm_dp_ps(normal, normal, dp_xyz);
рдЗрд╕ рдХреЛрдб рдореЗрдВ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реИ; рд╣рдо рдмрд╣реБрддрд╛рдпрдд рд╕реЗ рдЕрдирд▓рдЧреНрдб рд▓реЛрдб / рд╕реНрдЯреЛрд░ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╡реЗрдХреНрдЯрд░ 3 рдХреЗ рдЗрдирдкреБрдЯ рдХреЛ рд╕рдВрд░реЗрдЦрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдмрд┐рдирд╛ рдкрдврд╝реЗ рд▓рд┐рдЦреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рджрдВрдб рдирд╣реАрдВ рд▓рдЧрддрд╛ рд╣реИред рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкрд╣рд▓реЗ рдЫрдорд╛рд╣реА рдореЗрдВ рд╡реИрдХреНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдЕрдЪреНрдЫрд╛ рд╣реИ - рд╣рдорд╛рд░реЗ рд╡реИрдХреНрдЯрд░ рдореЗрдВ рддреАрди рдШрдЯрдХ рд╣реЛрддреЗ рд╣реИрдВ, рдФрд░ рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ (рдХреНрд╖реЗрддреНрд░реЛрдВ / рдХреНрд╖реЗрддреНрд░ / рджреВрд░реА рдХреА рдЧрдгрдирд╛ рджреЗрдЦреЗрдВ), рдЬрдмрдХрд┐ рдкреНрд░реЛрд╕реЗрд╕рд░ рд╕рдорд╛рдирд╛рдВрддрд░ рдореЗрдВ 4 рдСрдкрд░реЗрд╢рди рдХрд░рддрд╛ рд╣реИред рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ, рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рд╕рдорд╛рдирд╛рдВрддрд░рдХрд░рдг рдиреЗ рдХреИрд╕реЗ рдорджрдж рдХреА рд╣реИред

fillCellQuadrics
рдХреА рдПрдХ рд╕реМ рд╢реБрд░реБрдЖрдд рдЕрдм 9.8 рдХреЗ рдмрдЬрд╛рдп 5.3 рдПрд╕ рдореЗрдВ рдЪрд▓рддреА рд╣реИ, рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рдСрдкрд░реЗрд╢рди рдкрд░ рд▓рдЧрднрдЧ 45 рдПрдордПрд╕ рдмрдЪрд╛рддрд╛ рд╣реИ - рдмреБрд░рд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдмрд╣реБрдд рдкреНрд░рднрд╛рд╡рд╢рд╛рд▓реА рдирд╣реАрдВ рд╣реИред рдХрдИ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдореЗрдВ, рд╣рдо рдЪрд╛рд░ рдШрдЯрдХреЛрдВ рдХреЗ рдмрдЬрд╛рдп рддреАрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рд╕рд╛рде рд╣реА рд╕рдЯреАрдХ рдЧреБрдгрд╛ рднреА рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдХрд╛рдлреА рдорд╣рддреНрд╡рдкреВрд░реНрдг рджреЗрд░реА рджреЗрддрд╛ рд╣реИред рдпрджрд┐ рдЖрдкрдиреЗ рдкрд╣рд▓реЗ SIMD рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢ рд▓рд┐рдЦреЗ рдереЗ, рддреЛ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд╕реНрдХреЗрд▓рд░ рдЙрддреНрдкрд╛рдж рдХреЛ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рдПред
рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ рдмрд╛рд░ рдореЗрдВ рдЪрд╛рд░ рд╡реИрдХреНрдЯрд░ рдХрд░рдиреЗ рдЪрд╛рд╣рд┐рдПред рдПрдХ SIMD рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рдПрдХ рдкреВрд░реНрдг рд╡реЗрдХреНрдЯрд░ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рддреАрди рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ - рдПрдХ рдореЗрдВ рд╣рдо
x
рдЪрд╛рд░ рдШрдЯрдХреЛрдВ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рддреЗ рд╣реИрдВ, рджреВрд╕рд░реЗ рдореЗрдВ рд╣рдо
рдФрд░ рддреАрд╕рд░реЗ
z
рдореЗрдВ рд╕реНрдЯреЛрд░ рдХрд░реЗрдВрдЧреЗред рдпрд╣рд╛рдВ рдПрдХ рдмрд╛рд░ рдореЗрдВ рдХрд╛рдо рдХреЗ рд▓рд┐рдП рдЪрд╛рд░ рд╡реИрдХреНрдЯрд░ рдХреА рдЬрд░реВрд░рдд рд╣реЛрддреА рд╣реИ: рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╣рдо рдПрдХ рд╕рд╛рде рдЪрд╛рд░ рддреНрд░рд┐рдХреЛрдгреЛрдВ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░реЗрдВрдЧреЗред
рдбрд╛рдпрдиреЗрдорд┐рдХ рдЗрдВрдбреЗрдХреНрд╕рд┐рдВрдЧ рдХреЗ рд╕рд╛рде рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХрдИ рдПрд░реЗрдЬрд╝ рд╣реИрдВред рдЖрдорддреМрд░ рдкрд░, рдпрд╣
x
/
y
/
z
рдШрдЯрдХреЛрдВ рдХреЗ рддреИрдпрд╛рд░ рд╕рд░рдгрд┐рдпреЛрдВ рдореЗрдВ рдбреЗрдЯрд╛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИ (рдпрд╛ рдпреЛрдВ рдХрд╣реЗрдВ рдХрд┐ рдЖрдорддреМрд░ рдкрд░ рдЫреЛрдЯреЗ SIMD рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП,
float x[8], y[8], z[8]
, рдЗрдирдкреБрдЯ рдореЗрдВ 8 рдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд▓рд┐рдПред рдбреЗрдЯрд╛: рдЗрд╕реЗ AoSoA (рд╕рд░рдгреА рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХрд╛ рд╕рд░рдгрд┐рдпрд╛рдБ) рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдХреИрд╢ рд▓реЛрдХреЗрд▓рд┐рдЯреА рдФрд░ SIMD рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдореЗрдВ рд▓реЛрдб рдХрд░рдиреЗ рдореЗрдВ рдЖрд╕рд╛рдиреА рдХреЗ рдмреАрдЪ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╕рдВрддреБрд▓рди рджреЗрддрд╛ рд╣реИ), рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рдбрд╛рдпрдирд╛рдорд┐рдХ рдЗрдВрдбреЗрдХреНрд╕рд┐рдВрдЧ рдмрд╣реБрдд рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧреА, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣ рдЪрд╛рд░ рддреНрд░рд┐рдХреЛрдгреАрдп рдбреЗрдЯрд╛ рд▓реЛрдб рдХрд░реЗрдВ, рдФрд░ рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡реИрдХреНрдЯрд░ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВред рдореИрдХреНрд░реЛ
_MM_TRANSPOSE
рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд░реВрдк рд╕реЗ, рдЖрдкрдХреЛ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ SIMD рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рдЪрд╛рд░ рдкрд░рд┐рдорд┐рдд рдЪрддреБрд╖реНрдХреЛрдгреЛрдВ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдШрдЯрдХ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдкрд╛рд╕
__m128 Q_a00
рд╕рд╛рде рдЪрд╛рд░ рдкрд░рд┐рдорд┐рдд
__m128 Q_a00
рдХреЗ рдЪрд╛рд░ рдШрдЯрдХ
a00
)ред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдХреНрд╡рд╛рдбреНрд░рд┐рдХреНрд╕ рдкрд░ рдСрдкрд░реЗрд╢рди 4-рд╡рд╛рдЗрдб SIMD рдирд┐рд░реНрджреЗрд╢реЛрдВ рдореЗрдВ рдХрд╛рдлреА рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдлрд┐рдЯ рд╣реЛрддреЗ рд╣реИрдВ, рдФрд░ рд░реВрдкрд╛рдВрддрд░рдг рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреЛрдб рдХреЛ рдзреАрдорд╛ рдХрд░ рджреЗрддрд╛ рд╣реИ - рдЗрд╕рд▓рд┐рдП, рд╣рдо рдХреЗрд╡рд▓ рд╢реБрд░реБрдЖрддреА рд╡реИрдХреНрдЯрд░реЛрдВ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рд╡рд┐рдорд╛рди рд╕рдореАрдХрд░рдгреЛрдВ рдХреЛ рд╡рд╛рдкрд╕ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрд╕реА рднрд╛рдЧ рдХреЛ рдЪрд▓рд╛рддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рд╣рдордиреЗ рдХреНрд╡рд╛рдбреНрд░рд┐рдХреНрд╕ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рджреЛрд╣рд░рд╛рдПрдВ рдЪрд╛рд░ рдмрд╛рд░ред рдпрд╣рд╛рдВ рд╡рд╣ рдХреЛрдб рд╣реИ рдЬреЛ рддрдм рд╕рдорддрд▓ рдХреЗ рд╕рдореАрдХрд░рдгреЛрдВ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ (рд╢реЗрд╖ рднрд╛рдЧреЛрдВ рдХреЛ рд╕рдВрдХреНрд╖рд┐рдкреНрддрддрд╛ рдХреЗ рд▓рд┐рдП рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ):
unsigned int i00 = indices[(i + 0) * 3 + 0]; unsigned int i01 = indices[(i + 0) * 3 + 1]; unsigned int i02 = indices[(i + 0) * 3 + 2]; unsigned int i10 = indices[(i + 1) * 3 + 0]; unsigned int i11 = indices[(i + 1) * 3 + 1]; unsigned int i12 = indices[(i + 1) * 3 + 2]; unsigned int i20 = indices[(i + 2) * 3 + 0]; unsigned int i21 = indices[(i + 2) * 3 + 1]; unsigned int i22 = indices[(i + 2) * 3 + 2]; unsigned int i30 = indices[(i + 3) * 3 + 0]; unsigned int i31 = indices[(i + 3) * 3 + 1]; unsigned int i32 = indices[(i + 3) * 3 + 2];
рдХреЛрдб рдереЛрдбрд╝рд╛ рд▓рдВрдмрд╛ рд╣реЛ рдЧрдпрд╛ рд╣реИ: рдЕрдм рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдореЗрдВ рдЪрд╛рд░ рддреНрд░рд┐рдХреЛрдгреЛрдВ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рд╣рдореЗрдВ рдЕрдм рдЗрд╕рдХреЗ рд▓рд┐рдП SSE4.1 рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, SIMD рдЗрдХрд╛рдЗрдпреЛрдВ рдХреЛ рдЕрдзрд┐рдХ рдХреБрд╢рд▓рддрд╛ рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдЗрд╕рдиреЗ рдХреИрд╕реЗ рдорджрдж рдХреАред

рдареАрдХ рд╣реИ, рдареАрдХ рд╣реИред рдХреЛрдб рдмрд╣реБрдд рдХрдо рдЧрддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░ рдЪреБрдХрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐
fillCellQuadrics
рдлрд╝рдВрдХреНрд╢рди рдЕрдм SIMD рдХреЗ рдмрд┐рдирд╛ рдореВрд▓ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд░реВрдк рдореЗрдВ рд▓рдЧрднрдЧ рджреЛрдЧреБрдирд╛ рддреЗрдЬреА рд╕реЗ рдЪрд▓рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рдЬрдЯрд┐рд▓рддрд╛ рдореЗрдВ рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рд╡реГрджреНрдзрд┐ рдХреЛ рд╕рд╣реА рдард╣рд░рд╛рддрд╛ рд╣реИред рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд░реВрдк рд╕реЗ, рдЖрдк AVX2 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкреНрд░рддрд┐ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдореЗрдВ 8 рддреНрд░рд┐рдХреЛрдг рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рдЖрдкрдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд▓реВрдк рдХреЛ рд╕реНрдкрд┐рди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА (рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ, рдпрд╣ рд╕рднреА рдХреЛрдб ISPC рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдЪреНрдЫрд╛ рдХреЛрдб рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореЗрд░реЗ рднреЛрд▓реЗ рдкреНрд░рдпрд╛рд╕ рд╕рдлрд▓ рдирд╣реАрдВ рд╣реБрдП: рд▓реЛрдб / рд╕реНрдЯреЛрд░ рдЕрдиреБрдХреНрд░рдореЛрдВ рдХреЗ рдмрдЬрд╛рдп рдЙрдиреНрд╣реЛрдВрдиреЗ рджреГрдврд╝рддрд╛ рд╕реЗ рдПрдХ рдЗрдХрдЯреНрдард╛ / рдмрд┐рдЦрд░рд╛рд╡ рдЬрд╛рд░реА рдХрд┐рдпрд╛, рдЬреЛ рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рдзреАрдорд╛ рдХрд░ рджреЗрддрд╛ рд╣реИ)ред рдЪрд▓реЛ рдХреБрдЫ рдФрд░ рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВред
AVX2 = SSE2 + SSE2
AVX2 рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдПрдХ рдереЛрдбрд╝рд╛ рд╕рд╛ idiosyncratic рд╕реЗрдЯ рд╣реИред рдЗрд╕рдореЗрдВ 8-рд╡рд╛рдЗрдб рдлреНрд▓реЛрдЯрд┐рдВрдЧ рдкреЙрдЗрдВрдЯ рд░рдЬрд┐рд╕реНрдЯрд░ рд╣реИрдВ, рдФрд░ рдПрдХ рдирд┐рд░реНрджреЗрд╢ 8 рдСрдкрд░реЗрд╢рди рдХрд░ рд╕рдХрддрд╛ рд╣реИ; рд▓реЗрдХрд┐рди рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдирд┐рд░реНрджреЗрд╢ рд░рдЬрд┐рд╕реНрдЯрд░ рдХреЗ рджреЛ рд╣рд┐рд╕реНрд╕реЛрдВ рдкрд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рджреЛ SSE2 рдирд┐рд░реНрджреЗрд╢реЛрдВ рд╕реЗ рднрд┐рдиреНрди рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ (рдЬрд╣рд╛рдБ рддрдХ рдореИрдВ рд╕рдордЭрддрд╛ рд╣реВрдВ, AVX2 рд╕рдорд░реНрдерди рд╡рд╛рд▓реЗ рдкрд╣рд▓реЗ рдкреНрд░реЛрд╕реЗрд╕рд░ рдиреЗ рдкреНрд░рддреНрдпреЗрдХ рдирд┐рд░реНрджреЗрд╢ рдХреЛ рджреЛ рдпрд╛ рдЕрдзрд┐рдХ рдорд╛рдЗрдХреНрд░реЛрдлрд╝рд╛рд░рд░реЗрд╢рди рдореЗрдВ рдбрд┐рдХреЛрдб рдХрд┐рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкреНрд░рджрд░реНрд╢рди рд▓рд╛рдн рдирд┐рд░реНрджреЗрд╢ рдирд┐рдХрд╛рд▓рдиреЗ рдХреЗ рдЪрд░рдг рддрдХ рд╕реАрдорд┐рдд рдерд╛)ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП,
_mm_dp_ps
рджреЛ SSE2 рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЗ рдмреАрдЪ рдПрдХ рд╕реНрдХреЗрд▓рд░ рдЙрддреНрдкрд╛рдж рдХрд░рддрд╛ рд╣реИ, рдФрд░
_mm256_dp_ps
рджреЛ
_mm256_dp_ps
рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЗ рджреЛ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЗ рдмреАрдЪ рджреЛ рд╕реНрдХреЗрд▓рд░ рдЙрддреНрдкрд╛рдж рдмрдирд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдкреНрд░рддреНрдпреЗрдХ рдЖрдзреЗ рдХреЗ рд▓рд┐рдП 4-рдЪреМрдбрд╝рд╛ рддрдХ рд╕реАрдорд┐рдд рд╣реИред
рдЗрд╕ рд╡рдЬрд╣ рд╕реЗ, AVX2 рдХреЛрдб рдЕрдХреНрд╕рд░ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ "8-рд╡рд╛рдЗрдб SIMD" рд╕реЗ рднрд┐рдиреНрди рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рдпрд╣ рд╣рдорд╛рд░реЗ рдкрдХреНрд╖ рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ: 4-рд╡рд╛рдЗрдб рд╡реИрдХреНрдЯрд░ рдХрд╛ рдкреНрд░рддреНрдпрд╛рд░реЛрдкрдг рдХрд░рдХреЗ рд╡реИрд╢реНрд╡реАрдХрд░рдг рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рд╣рдо SIMD рдХреЗ рдкрд╣рд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рд▓реМрдЯрддреЗ рд╣реИрдВ рдФрд░ SSE2 рдХреЗ рдмрдЬрд╛рдп AVX2 рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рд▓реВрдк рдХреЛ рджреЛрдЧреБрдирд╛ рдХрд░рддреЗ рд╣реИрдВред / рдПрд╕рдПрд╕рдИ рекред рд╣рдореЗрдВ рдЕрднреА рднреА 4-рд╡рд╛рдЗрдб рд╡реИрдХреНрдЯрд░ рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдФрд░ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рд╣рдо
_mm256
рдореЗрдВ
__m128
рд╕реЗ
__m256
рдФрд░
_mm_
рд╕реЗ
_mm256
рдХреЛ рдХрдИ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдореЗрдВ
_mm256
рд╣реИрдВ:
unsigned int i00 = indices[(i + 0) * 3 + 0]; unsigned int i01 = indices[(i + 0) * 3 + 1]; unsigned int i02 = indices[(i + 0) * 3 + 2]; unsigned int i10 = indices[(i + 1) * 3 + 0]; unsigned int i11 = indices[(i + 1) * 3 + 1]; unsigned int i12 = indices[(i + 1) * 3 + 2]; __m256 p0 = _mm256_loadu2_m128( &vertex_positions[i10].x, &vertex_positions[i00].x); __m256 p1 = _mm256_loadu2_m128( &vertex_positions[i11].x, &vertex_positions[i01].x); __m256 p2 = _mm256_loadu2_m128( &vertex_positions[i12].x, &vertex_positions[i02].x); __m256 p10 = _mm256_sub_ps(p1, p0); __m256 p20 = _mm256_sub_ps(p2, p0); __m256 normal = _mm256_sub_ps( _mm256_mul_ps( _mm256_shuffle_ps(p10, p10, yzx), _mm256_shuffle_ps(p20, p20, zxy)), _mm256_mul_ps( _mm256_shuffle_ps(p10, p10, zxy), _mm256_shuffle_ps(p20, p20, yzx))); __m256 areasq = _mm256_dp_ps(normal, normal, dp_xyz); __m256 area = _mm256_sqrt_ps(areasq); __m256 areanz = _mm256_cmp_ps(area, _mm256_setzero_ps(), _CMP_NEQ_OQ); normal = _mm256_and_ps(_mm256_div_ps(normal, area), areanz); __m256 distance = _mm256_dp_ps(normal, p0, dp_xyz); __m256 negdistance = _mm256_sub_ps(_mm256_setzero_ps(), distance); __m256 normalnegdist = _mm256_blend_ps(normal, negdistance, 0x88); __m256 Qx = _mm256_mul_ps(normal, normal); __m256 Qy = _mm256_mul_ps( _mm256_shuffle_ps(normal, normal, _MM_SHUFFLE(3, 2, 2, 1)), _mm256_shuffle_ps(normal, normal, _MM_SHUFFLE(3, 0, 1, 0))); __m256 Qz = _mm256_mul_ps(negdistance, normalnegdist);
рдпрд╣рд╛рдВ рдЖрдк рдкреНрд░рд╛рдкреНрдд
Qx
/
Qz
/
Qz
рдкреНрд░рддреНрдпреЗрдХ 128-рдмрд┐рдЯ рдЖрдзреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЛ рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрд╕реА рдХреЛрдб рдХреЛ рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рд╣рдо рдХреНрд╡рд╛рдбреНрд░рд┐рдХреНрд╕ рдореЗрдВ рдЬреЛрдбрд╝рддреЗ рдереЗред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рдорд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЕрдЧрд░ рдПрдХ рддреНрд░рд┐рдХреЛрдг рдореЗрдВ рдПрдХ рд╕реЗрд▓ рдореЗрдВ рддреАрди рдХреЛрдиреЗ рд╣реЛрддреЗ рд╣реИрдВ (
single_cell == true
), рддреЛ рдпрд╣ рдмрд╣реБрдд рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рдЕрдиреНрдп рддреНрд░рд┐рдХреЛрдг рдореЗрдВ рдХрд┐рд╕реА рдЕрдиреНрдп рдХрдХреНрд╖ рдореЗрдВ рддреАрди рдХреЛрдиреЗ рд╣реЛрдВ, рдФрд░ рд╣рдо AVX2 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдХреНрд╡рд╛рдбрдЯреНрд░рд┐рдХреНрд╕ рдХрд╛ рдЕрдВрддрд┐рдо рдПрдХрддреНрд░реАрдХрд░рдг рдХрд░рддреЗ рд╣реИрдВ:
unsigned int c00 = vertex_cells[i00]; unsigned int c01 = vertex_cells[i01]; unsigned int c02 = vertex_cells[i02]; unsigned int c10 = vertex_cells[i10]; unsigned int c11 = vertex_cells[i11]; unsigned int c12 = vertex_cells[i12]; bool single_cell = (c00 == c01) & (c00 == c02) & (c10 == c11) & (c10 == c12); if (single_cell) { area = _mm256_mul_ps(area, _mm256_set1_ps(3.f)); Qx = _mm256_mul_ps(Qx, area); Qy = _mm256_mul_ps(Qy, area); Qz = _mm256_mul_ps(Qz, area); Quadric& q00 = cell_quadrics[c00]; Quadric& q10 = cell_quadrics[c10]; __m256 q0x = _mm256_loadu2_m128(&q10.a00, &q00.a00); __m256 q0y = _mm256_loadu2_m128(&q10.a10, &q00.a10); __m256 q0z = _mm256_loadu2_m128(&q10.b0, &q00.b0); _mm256_storeu2_m128(&q10.a00, &q00.a00, _mm256_add_ps(q0x, Qx)); _mm256_storeu2_m128(&q10.a10, &q00.a10, _mm256_add_ps(q0y, Qy)); _mm256_storeu2_m128(&q10.b0, &q00.b0, _mm256_add_ps(q0z, Qz)); } else {
рдкрд░рд┐рдгрд╛рдореА рдХреЛрдб рд╣рдорд╛рд░реЗ рдЕрд╕рдлрд▓ SSE2 рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд╕рд░рд▓, рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдФрд░ рддреЗрдЬрд╝ рд╣реИ:

рдмреЗрд╢рдХ, рд╣рдордиреЗ 8 рдмрд╛рд░ рддреНрд╡рд░рдг рд╣рд╛рд╕рд┐рд▓ рдирд╣реАрдВ рдХрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ 2.45 рдмрд╛рд░ред рд▓реЛрдб рдФрд░ рд╕реНрдЯреЛрд░ рд╕рдВрдЪрд╛рд▓рди рдЕрднреА рднреА 4-рдЪреМрдбрд╝рд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдореЗрдВ рдбрд╛рдпрдирд╛рдорд┐рдХ рдЗрдВрдбреЗрдХреНрд╕рд┐рдВрдЧ рдХреЗ рдХрд╛рд░рдг рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдореЗрдореЛрд░реА рд▓реЗрдЖрдЙрдЯ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЧрдгрдирд╛ SIMD рдХреЗ рд▓рд┐рдП рдЗрд╖реНрдЯрддрдо рдирд╣реАрдВ рд╣реИрдВред рд▓реЗрдХрд┐рди рдЕрдм
fillCellQuadrics
рдЕрдм рд╣рдорд╛рд░реЗ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ рдЕрдбрд╝рдЪрди рдирд╣реАрдВ рд╣реИ, рдФрд░ рдЖрдк рдЕрдиреНрдп рдХрд╛рд░реНрдпреЛрдВ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЪрд╛рд░реЛрдВ рдУрд░, рдмрдЪреНрдЪреЛрдВ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░реЛ
рд╣рдордиреЗ рдЯреЗрд╕реНрдЯ рд░рди рдкрд░ 4.8 рд╕реЗрдХрдВрдб (рдкреНрд░рддреНрдпреЗрдХ рд░рди рдкрд░ 48 рдПрдордПрд╕) рдХреЛ рдмрдЪрд╛рдпрд╛, рдФрд░ рдЕрдм рд╣рдорд╛рд░рд╛ рдореБрдЦреНрдп рдШреБрд╕рдкреИрдард┐рдпрд╛
countTriangles
ред рдпрд╣ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдХрд╛рд░реНрдп рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдПрдХ рдмрд╛рд░ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рдкрд╛рдВрдЪ рдмрд╛рд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
static size_t countTriangles(const unsigned int* vertex_ids, const unsigned int* indices, size_t index_count) { size_t result = 0; for (size_t i = 0; i < index_count; i += 3) { unsigned int id0 = vertex_ids[indices[i + 0]]; unsigned int id1 = vertex_ids[indices[i + 1]]; unsigned int id2 = vertex_ids[indices[i + 2]]; result += (id0 != id1) & (id0 != id2) & (id1 != id2); } return result; }
рдлрд╝рдВрдХреНрд╢рди рд╕рднреА рд╕реНрд░реЛрдд рддреНрд░рд┐рдХреЛрдгреЛрдВ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдХреЛрдиреЗ рдХреЗ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛рдУрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рдХреЗ рдЧреИрд░-рдкрддрд▓реЗ рддреНрд░рд┐рдХреЛрдгреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рддреБрд░рдВрдд рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрд╕реЗ SIMD рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреИрд╕реЗ рд╕рдорд╛рдирд╛рдВрддрд░ рдХрд┐рдпрд╛ рдЬрд╛рдП ... рдЬрдм рддрдХ рдЖрдк рдПрдХрддреНрд░рд┐рдд рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред
AVX2 рдирд┐рд░реНрджреЗрд╢ рд╕реЗрдЯ рдиреЗ x64 SIMD рдореЗрдВ рдЗрдХрдЯреНрдард╛ / рддрд┐рддрд░ рдмрд┐рддрд░ рдирд┐рд░реНрджреЗрд╢ рдкрд░рд┐рд╡рд╛рд░ рдХреЛ рдЬреЛрдбрд╝рд╛ рд╣реИ; рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ 4 рдпрд╛ 8 рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╡реЗрдХреНрдЯрд░ рд░рдЬрд┐рд╕реНрдЯрд░ рд▓реЗрддрд╛ рд╣реИ - рдФрд░ рд╕рд╛рде рд╣реА 4 рдпрд╛ 8 рд▓реЛрдб рдХрд░рддрд╛ рд╣реИ рдпрд╛ рд╕рдВрдЪрд╛рд▓рди рдХреЛ рдмрдЪрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдпрд╣рд╛рдВ рдЗрдХрдЯреНрдард╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рддреАрди рдЗрдВрдбреЗрдХреНрд╕ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдПрдХ рдмрд╛рд░ (рдпрд╛ 4 рдпрд╛ 8 рдХреЗ рд╕рдореВрд╣реЛрдВ рдореЗрдВ) рдХреЗ рд▓рд┐рдП рдЗрдХрдЯреНрдард╛ рд░рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрдВрдЯреЗрд▓ рдкреНрд░реЛрд╕реЗрд╕рд░ рдкрд░ рдЗрдХрдЯреНрдард╛ рдРрддрд┐рд╣рд╛рд╕рд┐рдХ рд░реВрдк рд╕реЗ рдмрд╣реБрдд рдзреАрдорд╛ рд░рд╣рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЪрд▓реЛ рдЗрд╕реЗ рдЖрдЬрд╝рдорд╛рдПрдВред рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рд╣рдо 8 рддреНрд░рд┐рдХреЛрдгреЛрдВ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдЕрдкрд▓реЛрдб рдХрд░рддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рдкрд┐рдЫрд▓реЗ рдкреНрд░рдпрд╛рд╕ рдХреЗ рд╕рдорд╛рди рд╡реИрдХреНрдЯрд░ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд╕рдВрдмрдВрдзрд┐рдд рддрддреНрд╡реЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рддреЗ рд╣реИрдВ:
for (size_t i = 0; i < (triangle_count & ~7); i += 8) { __m256 tri0 = _mm256_loadu2_m128( (const float*)&indices[(i + 4) * 3 + 0], (const float*)&indices[(i + 0) * 3 + 0]); __m256 tri1 = _mm256_loadu2_m128( (const float*)&indices[(i + 5) * 3 + 0], (const float*)&indices[(i + 1) * 3 + 0]); __m256 tri2 = _mm256_loadu2_m128( (const float*)&indices[(i + 6) * 3 + 0], (const float*)&indices[(i + 2) * 3 + 0]); __m256 tri3 = _mm256_loadu2_m128( (const float*)&indices[(i + 7) * 3 + 0], (const float*)&indices[(i + 3) * 3 + 0]); _MM_TRANSPOSE8_LANE4_PS(tri0, tri1, tri2, tri3); __m256i i0 = _mm256_castps_si256(tri0); __m256i i1 = _mm256_castps_si256(tri1); __m256i i2 = _mm256_castps_si256(tri2); __m256i id0 = _mm256_i32gather_epi32((int*)vertex_ids, i0, 4); __m256i id1 = _mm256_i32gather_epi32((int*)vertex_ids, i1, 4); __m256i id2 = _mm256_i32gather_epi32((int*)vertex_ids, i2, 4); __m256i deg = _mm256_or_si256( _mm256_cmpeq_epi32(id1, id2), _mm256_or_si256( _mm256_cmpeq_epi32(id0, id1), _mm256_cmpeq_epi32(id0, id2))); result += 8 - _mm_popcnt_u32(_mm256_movemask_epi8(deg)) / 4; }
_MM_TRANSPOSE8_LANE4_PS
рдореЗрдВ
_MM_TRANSPOSE8_LANE4_PS
рдореИрдХреНрд░реЛ
_MM_TRANSPOSE8_LANE4_PS
рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИ, рдЬреЛ рдорд╛рдирдХ рд╢реАрд░реНрд╖ рд▓реЗрдЦ рдореЗрдВ рдирд╣реАрдВ рдкрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрд╕рд╛рдиреА рд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рдЪрд╛рд░ рдПрд╡реАрдПрдХреНрд╕ 2 рд╡реИрдХреНрдЯрд░ рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдПрдХ рджреВрд╕рд░реЗ рд╕реЗ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рджреЛ 4 ├Ч 4 рдореИрдЯреНрд░рд┐рд╕реЗрд╕ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИ:
#define _MM_TRANSPOSE8_LANE4_PS(row0, row1, row2, row3) \ do { \ __m256 __t0, __t1, __t2, __t3; \ __t0 = _mm256_unpacklo_ps(row0, row1); \ __t1 = _mm256_unpackhi_ps(row0, row1); \ __t2 = _mm256_unpacklo_ps(row2, row3); \ __t3 = _mm256_unpackhi_ps(row2, row3); \ row0 = _mm256_shuffle_ps(__t0, __t2, _MM_SHUFFLE(1, 0, 1, 0)); \ row1 = _mm256_shuffle_ps(__t0, __t2, _MM_SHUFFLE(3, 2, 3, 2)); \ row2 = _mm256_shuffle_ps(__t1, __t3, _MM_SHUFFLE(1, 0, 1, 0)); \ row3 = _mm256_shuffle_ps(__t1, __t3, _MM_SHUFFLE(3, 2, 3, 2)); \ } while (0)
SSE2 / AVX2 рдЗрдВрд╕реНрдЯреНрд░рдХреНрд╢рди рд╕реЗрдЯреНрд╕ рдореЗрдВ рдХреБрдЫ рдлреАрдЪрд░реНрд╕ рдХреЗ рдХрд╛рд░рдг, рд╣рдореЗрдВ рд╡реИрдХреНрдЯрд░ рдЯреНрд░рд╛рдВрд╕рдкреЛрдЬрд╝ рдХрд░рддреЗ рд╕рдордп рдлреНрд▓реЛрдЯрд┐рдВрдЧ рдкреЙрдЗрдВрдЯ рд░рдЬрд┐рд╕реНрдЯрд░ рдСрдкрд░реЗрд╢рдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдо рдбреЗрдЯрд╛ рдХреЛ рдереЛрдбрд╝рд╛ рд▓рд╛рдкрд░рд╡рд╛рд╣реА рд╕реЗ рд▓реЛрдб рдХрд░ рд░рд╣реЗ рд╣реИрдВ; рд▓реЗрдХрд┐рди рдпрд╣ рдореВрд▓ рд░реВрдк рд╕реЗ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛, рдХреНрдпреЛрдВрдХрд┐ рдкреНрд░рджрд░реНрд╢рди рд╣рдореЗрдВ рдЗрдХрдЯреНрдард╛ рдХрд░рддреЗ рд╣реИрдВ:

рдЕрдм
countTriangles
рд▓рдЧрднрдЧ 27% рддреЗрдЬ рд╣реИ, рдФрд░ рднрдпрд╛рдирдХ рд╕реАрдкреАрдЖрдИ (рдкреНрд░рддрд┐ рдирд┐рд░реНрджреЗрд╢ рдЪрдХреНрд░) рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ: рд╣рдо рд▓рдЧрднрдЧ рдЪрд╛рд░ рдЧреБрдирд╛ рдХрдо рдирд┐рд░реНрджреЗрд╢ рднреЗрдЬрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЗрдХрдЯреНрдард╛ рд╣реЛрдиреЗ рдореЗрдВ рдмрд╣реБрдд рд╕рдордп рд▓рдЧрддрд╛ рд╣реИред рдпрд╣ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдордЧреНрд░ рдХрд╛рдо рдХреЛ рдЧрддрд┐ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдкреНрд░рджрд░реНрд╢рди рд▓рд╛рдн рдХреБрдЫ рдирд┐рд░рд╛рд╢рд╛рдЬрдирдХ рд╣реИред рд╣рдо рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдореЗрдВ
fillCellQuadrics
рд╕реЗ рдЖрдЧреЗ
fillCellQuadrics
рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣реЗ, рдЬреЛ рд╣рдореЗрдВ рд╕реВрдЪреА рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдЕрдВрддрд┐рдо рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рд▓рд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдордиреЗ рдЕрднреА рддрдХ рдирд╣реАрдВ рджреЗрдЦрд╛ рд╣реИред
рдЕрдзреНрдпрд╛рдп 6, рдЬрд╣рд╛рдВ рд╕рдм рдХреБрдЫ рдЙрд╕реА рддрд░рд╣ рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджреЗрддрд╛ рд╣реИ рдЬреИрд╕реЗ рдЙрд╕реЗ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП
рдЕрдВрддрд┐рдо рдлрд╝рдВрдХреНрд╢рди
computeVertexIds
ред рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдореЗрдВ, рдпрд╣ 6 рдмрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЕрдиреБрдХреВрд▓рди рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрддреНрдХреГрд╖реНрдЯ рд▓рдХреНрд╖реНрдп рдХрд╛ рднреА рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИред рдкрд╣рд▓реА рдмрд╛рд░ рд╣рдо рдПрдХ рдлрд╝рдВрдХреНрд╢рди рджреЗрдЦрддреЗ рд╣реИрдВ рдЬреЛ SIMD рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рдЕрдиреБрдХреВрд▓рди рдХреЗ рд▓рд┐рдП рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд▓рдЧрддрд╛ рд╣реИ:
static void computeVertexIds(unsigned int* vertex_ids, const Vector3* vertex_positions, size_t vertex_count, int grid_size) { assert(grid_size >= 1 && grid_size <= 1024); float cell_scale = float(grid_size - 1); for (size_t i = 0; i < vertex_count; ++i) { const Vector3& v = vertex_positions[i]; int xi = int(vx * cell_scale + 0.5f); int yi = int(vy * cell_scale + 0.5f); int zi = int(vz * cell_scale + 0.5f); vertex_ids[i] = (xi << 20) | (yi << 10) | zi; } }
рдкрд┐рдЫрд▓реА рдЕрдиреБрдХреВрд▓рди рдХреЗ рдмрд╛рдж, рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИ: рдЪрдХреНрд░ 4 рдпрд╛ 8 рдмрд╛рд░ рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░реЗрдВ, рдХреНрдпреЛрдВрдХрд┐ рдХреЗрд╡рд▓ рдПрдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреЛ рдЧрддрд┐ рджреЗрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИ, рд╡реЗрдХреНрдЯрд░ рдШрдЯрдХреЛрдВ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВ рдФрд░ рд╕рдорд╛рдирд╛рдВрддрд░ рдореЗрдВ рдЧрдгрдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВред рдЪрд▓реЛ AVX2 рдХреЗ рд╕рд╛рде рдХрд░рддреЗ рд╣реИрдВ, рдПрдХ рд╕рдордп рдореЗрдВ 8 рдХреЛрдиреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХрд░рддреЗ рд╣реИрдВ:
__m256 scale = _mm256_set1_ps(cell_scale); __m256 half = _mm256_set1_ps(0.5f); for (size_t i = 0; i < (vertex_count & ~7); i += 8) { __m256 vx = _mm256_loadu2_m128( &vertex_positions[i + 4].x, &vertex_positions[i + 0].x); __m256 vy = _mm256_loadu2_m128( &vertex_positions[i + 5].x, &vertex_positions[i + 1].x); __m256 vz = _mm256_loadu2_m128( &vertex_positions[i + 6].x, &vertex_positions[i + 2].x); __m256 vw = _mm256_loadu2_m128( &vertex_positions[i + 7].x, &vertex_positions[i + 3].x); _MM_TRANSPOSE8_LANE4_PS(vx, vy, vz, vw); __m256i xi = _mm256_cvttps_epi32( _mm256_add_ps(_mm256_mul_ps(vx, scale), half)); __m256i yi = _mm256_cvttps_epi32( _mm256_add_ps(_mm256_mul_ps(vy, scale), half)); __m256i zi = _mm256_cvttps_epi32( _mm256_add_ps(_mm256_mul_ps(vz, scale), half)); __m256i id = _mm256_or_si256( zi, _mm256_or_si256( _mm256_slli_epi32(xi, 20), _mm256_slli_epi32(yi, 10))); _mm256_storeu_si256((__m256i*)&vertex_ids[i], id); }
рдФрд░ рдкрд░рд┐рдгрд╛рдо рджреЗрдЦреЗрдВ:
рд╣рдордиреЗ computeVertexIds
рджреЛ рдмрд╛рд░ рддреНрд╡рд░рд┐рдд рдХрд┐рдпрд╛ред рд╕рднреА рдЕрдиреБрдХреВрд▓рди рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП, рдХрд╛рд░реНрдпрдХреНрд░рдо рдХрд╛ рдХреБрд▓ рдирд┐рд╖реНрдкрд╛рджрди рд╕рдордп рд▓рдЧрднрдЧ 120 рдПрдордПрд╕ рддрдХ рдХрдо рд╣реЛ рдЧрдпрд╛ рдерд╛, рдЬреЛ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб 50 рдорд┐рд▓рд┐рдпрди рддреНрд░рд┐рдХреЛрдг рдХреА рдЧрдгрдирд╛ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИредрдРрд╕рд╛ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рд╣рдордиреЗ рдлрд┐рд░ рд╕реЗ рдЕрдкреЗрдХреНрд╖рд┐рдд рдЙрддреНрдкрд╛рджрдХрддрд╛ рд╡реГрджреНрдзрд┐ рд╣рд╛рд╕рд┐рд▓ рдирд╣реАрдВ рдХреА рд╣реИ: рдХреНрдпрд╛ computeVertexIds
рдпрд╣ рд╕рдорд╛рдирд╛рдВрддрд░реАрдХрд░рдг рдХреЗ рдмрд╛рдж рджреЛ рдмрд╛рд░ рд╕реЗ рдЕрдзрд┐рдХ рддреЗрдЬреА рдирд╣реАрдВ рд▓рд╛ рд╕рдХрддрд╛ рд╣реИ? рдЗрд╕ рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рдпрд╣ рджреЗрдЦрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ рдХрд┐ рдпрд╣ рдХрд╛рд░реНрдп рдХрд┐рддрдирд╛ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИредcomputeVertexIds
рдЗрд╕реЗ рдПрдХ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рдкреНрд░рд╛рд░рдВрдн рдХреЗ рд▓рд┐рдП рдЫрд╣ рдмрд╛рд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: рдмрд╛рдЗрдирд░реА рдЦреЛрдЬ рдХреЗ рджреМрд░рд╛рди рдкрд╛рдВрдЪ рдмрд╛рд░ рдФрд░ рдЕрдВрддрд┐рдо рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛рдУрдВ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╛рд░ рдЕрдВрдд рдореЗрдВ рдЬреЛ рдЖрдЧреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рд░ рдмрд╛рд░ рдЗрд╕ рдлрдВрдХреНрд╢рди рдореЗрдВ 3 рдорд┐рд▓рд┐рдпрди рд╡рд░реНрд╕реЗрдЯреНрд╕ рдкреНрд░реЛрд╕реЗрд╕ рд╣реЛрддреЗ рд╣реИрдВ, рдкреНрд░рддреНрдпреЗрдХ рд╡рд░реНрдЯреЗрдХреНрд╕ рдХреЗ рд▓рд┐рдП 12 рдмрд╛рдЗрдЯреНрд╕ рдкрдврд╝рдирд╛ рдФрд░ 4 рдмрд╛рдЗрдЯреНрд╕ рд▓рд┐рдЦрдирд╛редрдХреБрд▓ рдорд┐рд▓рд╛рдХрд░, рдЗрдиреЛрд╡реЗрдЯрд░ рдХреЗ 100 рд╕реЗ рдЕрдзрд┐рдХ рд░рди, рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ 1.8 рдмрд┐рд▓рд┐рдпрди рд╡рд░реНрдЯрд┐рдХрд▓ рдкреНрд░реЛрд╕реЗрд╕ рд╣реЛрддреЗ рд╣реИрдВ, 21 рдЬреАрдмреА рдкрдврд╝рдирд╛ рдФрд░ 7 рдЬреАрдмреА рд╡рд╛рдкрд╕ рд▓рд┐рдЦрдирд╛ред 1.46 рд╕реЗрдХрдВрдб рдореЗрдВ 28 рдЬреАрдмреА рдХреА рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП 19 рдЬреАрдмреА / рдПрд╕ рдХреЗ рдмрд╕ рдмреИрдВрдбрд╡рд┐рдбреНрде рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рд╣рдо рдореЗрдореЛрд░реА рдмреИрдВрдбрд╡рд┐рдбреНрде рдХреЛ рдЪрд▓рд╛рдХрд░ рдЪреЗрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ memcmp(block1, block2, 512 MB)
ред рдкрд░рд┐рдгрд╛рдо 45 рдПрдордПрд╕ рд╣реИ, рдпрд╛рдиреА, рдПрдХ рдХреЛрд░ рдкрд░ рд▓рдЧрднрдЧ 22 рдЬреАрдмреА / рдПрд╕ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдПрдЖрдИрдбреАрдП 64 рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдореЗрд░реЗ рд╕рд┐рд╕реНрдЯрдо рдкрд░ 31 рдЬреАрдмреА / рдПрд╕ рддрдХ рд░реАрдб рдЧрддрд┐ рджрд┐рдЦрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдХрдИ рдХреЛрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ)ред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╣рдо рдЕрдзрд┐рдХрддрдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдореЗрдореЛрд░реА рд╕реАрдорд╛ рдХреЗ рдХрд░реАрдм рдЖ рдЧрдП рд╣реИрдВ, рдФрд░ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рдФрд░ рд╡реГрджреНрдзрд┐ рдХреЗ рд▓рд┐рдП рдЗрди рдХреЛрдиреЗ рдХреА рдХрд░реАрдм рдкреИрдХрд┐рдВрдЧ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рддрд╛рдХрд┐ рд╡реЗ 12 рдмрд╛рдЗрдЯреНрд╕ рд╕реЗ рдХрдо рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░ рд▓реЗрдВредрдирд┐рд╖реНрдХрд░реНрд╖
рд╣рдордиреЗ рдПрдХ рдмрд╣реБрдд рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЕрдиреБрдХреВрд▓рд┐рдд рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд▓рд┐рдпрд╛, рдЬреЛ 28 рдорд┐рд▓рд┐рдпрди рддреНрд░рд┐рдХреЛрдг рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рдХреА рдЧрддрд┐ рд╕реЗ рдмрд╣реБрдд рдмрдбрд╝реА рдЧреНрд░рд┐рдб рдХреЛ рд╕рд░рд▓ рдХрд░рддрд╛ рд╣реИ, рдФрд░ SSE рдФрд░ AVX рдирд┐рд░реНрджреЗрд╢ рд╕реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рд▓рдЧрднрдЧ рджреЛ рдмрд╛рд░, 50 рдорд┐рд▓рд┐рдпрди рддреНрд░рд┐рдХреЛрдг рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рддрдХ рдЧрддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрд╕ рдпрд╛рддреНрд░рд╛ рдХреЗ рджреМрд░рд╛рди, рд╣рдореЗрдВ SIMD рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд░реАрдХреЗ рд╕реАрдЦрдиреЗ рдкрдбрд╝реЗ: 3-рд╡рд╛рдЗрдб рд╡реИрдХреНрдЯрд░ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░рдЬрд┐рд╕реНрдЯрд░, SoA рдЯреНрд░рд╛рдВрд╕рдкреЛрдЬрд╝, AVX2 рджреЛ 3-рд╡рд╛рдЗрдб рд╡реИрдХреНрдЯрд░ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢, рд╕реНрдХреЗрд▓рд░ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдбреЗрдЯрд╛ рд▓реЛрдбрд┐рдВрдЧ рдХреЛ рдЧрддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢ рдЗрдХрдЯреНрдард╛ рдХрд░рдирд╛ рдФрд░ рдЖрдЦрд┐рд░рдХрд╛рд░ред рд╣рдордиреЗ рд╕реАрдзреЗ рд╕реНрдЯреНрд░реАрдорд┐рдВрдЧ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП AVX2 рд▓рдЧрд╛рдпрд╛редSIMD рдЕрдХреНрд╕рд░ рдЕрдиреБрдХреВрд▓рди рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╢реБрд░реБрдЖрддреА рдмрд┐рдВрджреБ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ: рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рд╡рд┐рд╢рд┐рд╖реНрдЯ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рдЕрд▓реНрдЧреЛрд░рд┐рдердорд┐рдХ рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝реЗрд╢рди рдФрд░ рдорд╛рдЗрдХреНрд░реЛрдкреЛрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝реЗрд╢рди рдХреЗ рдХрдИ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдореЗрд╖ рддрд░реНрдХрд╕рдВрдЧрддрддрд╛ рдЧрдИ рд╣реИред рд▓реЗрдХрд┐рди рдХреБрдЫ рдмрд┐рдВрджреБ рдкрд░, рдпреЗ рд╕рдВрднрд╛рд╡рдирд╛рдПрдВ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддреА рд╣реИрдВ, рдФрд░ рдпрджрд┐ рдкреНрд░рджрд░реНрд╢рди рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рддреЛ SIMD рдПрдХ рд╢рд╛рдирджрд╛рд░ рдЙрдкрдХрд░рдг рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рддреЛ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИредрдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрдирдореЗрдВ рд╕реЗ рдХреМрди рд╕реА рдЕрдиреБрдХреВрд▓рди рдореБрдЦреНрдп рд╢рд╛рдЦрд╛ рдореЗрдВ рдЖрдПрдЧреА meshoptimizer
: рдЕрдВрдд рдореЗрдВ, рдпрд╣ рдХреЗрд╡рд▓ рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рдпреЛрдЧ рд╣реИ рдХрд┐ рдХреЛрдб рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдореЗрдВ рдореВрд▓рднреВрдд рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рдмрд┐рдирд╛ рдХрд┐рддрдирд╛ рдУрд╡рд░рдХреНрд▓реЙрдХрд┐рдВрдЧ рд╣реИред рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рд▓реЗрдЦ рдЬрд╛рдирдХрд╛рд░реАрдкреВрд░реНрдг рдирд┐рдХрд▓рд╛ рдФрд░ рдЖрдкрдХреЛ рдХреЛрдб рдХреЗ рдЕрдиреБрдХреВрд▓рди рдХреЗ рд▓рд┐рдП рд╡рд┐рдЪрд╛рд░ рджреЗрдЧрд╛ред рдЗрд╕ рд▓реЗрдЦ рдХреЗ рдЕрдВрддрд┐рдо рд╕реНрд░реЛрдд рдпрд╣рд╛рдБ рд╣реИрдВ ; рдпрд╣ рдХрд╛рд░реНрдп рдореЗрдЬрд╝рдкреЛрдЯреАрдорд╛рдЗрдЬрд╝рд░ 99ab49 рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ, рдФрд░ рдерд╛рдИ рдмреБрджреНрдз рдореЙрдбрд▓ рд╕реНрдХреЗрдЪрдлреИрдм рдкрд░ рдкреНрд░рдХрд╛рд╢рд┐рдд рд╣реБрдЖ рд╣реИ ред