{"id":123,"date":"2022-02-28T22:58:28","date_gmt":"2022-02-28T21:58:28","guid":{"rendered":"http:\/\/graphics32\/?page_id=123"},"modified":"2024-03-05T04:58:34","modified_gmt":"2024-03-05T03:58:34","slug":"sse2-optimizations","status":"publish","type":"page","link":"https:\/\/melander.dk\/graphics32\/sse2-optimizations\/","title":{"rendered":"SIMD Optimizations"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">In order to achieve the best possible performance on a given host platform, Graphics32 implements most low level bottlenecks using <a href=\"https:\/\/en.wikipedia.org\/wiki\/Single_instruction,_multiple_data\">SIMD<\/a> optimized assembly instructions. SIMD instructions enable the CPU to execute multiple similar calculations in parallel and is thus particularly well suited for graphics processing where the same operation is often performed on the R, G, B, and possibly A channels, of an image.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Since the level of SIMD support varies with different CPU models, Graphics32 provides different implementations for different SIMD support levels and <a href=\"https:\/\/melander.dk\/graphics32\/cpu-feature-detection\/\" data-type=\"page\" data-id=\"382\">automatically uses the best possible variant<\/a>.<br>The most basic SIMD support is based on the <a href=\"https:\/\/en.wikipedia.org\/wiki\/MMX_(instruction_set)\">MMX<\/a> instruction set. Since MMX was introduced in 1997 it is supported by all processors supported by Delphi and thus Graphics32. Newer processors all support the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Streaming_SIMD_Extensions\">SSE<\/a> (introduced 1999) and <a href=\"https:\/\/en.wikipedia.org\/wiki\/SSE2\">SSE2<\/a> (introduced 2000) instruction sets and today MMX support is <em>only <\/em>included in Graphics32 for backward compatibility and as a reference.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">MMX vs SSE<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The reason to favor SSE* optimizations over MMX optimizations is mainly due to MMX&#8217;s use of the x87 FPU&#8217;s floating point registers. As long as all processing is done solely in fixed point or integer registers, there is no problem, but if floating point calculations needs to be done after MMX has used the FPU registers then an expensive reset of the FPU registers must first be performed or else a floating point exception will be thrown. This reset is performed within the <a href=\"https:\/\/www.felixcloutier.com\/x86\/emms\">EMMS<\/a> function (an intrinsic to the assembler mnemonic with the same name).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It should be noted that even though a call to EMMS uses only a handful of cycles, frequent calls can slow down simple processing such as alpha blending a lot.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The OMIT_MMX compiler conditional<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The support for MMX optimizations can be controlled with the <code>OMIT_MMX<\/code> compiler conditional:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>When <code>OMIT_MMX<\/code> is defined, the MMX optimizations will be entirely disabled.<br>The EMMS function becomes an empty static function that does nothing and which, due to compiler inlining, has no cost.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>When <code>OMIT_MMX<\/code> is not defined, the MMX optimizations will be included and by default the EMMS function will execute the <em>emms<\/em> assembler instruction.<br>However if Graphics32&#8217;s CPU feature detection has selected a newer SIMD technology, such as SSE or SSE2, then the EMMS function just becomes an empty virtual function that does nothing and the cost of calling it is nothing more that a call and return.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Note: As all x86 64-bit processors feature SSE2, <code>OMIT_MMX<\/code> is defined by default here. This not only results in better performance, but also in smaller executables.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In order to achieve the best possible performance on a given host platform, Graphics32 implements most low level bottlenecks using SIMD optimized assembly instructions. SIMD instructions enable the CPU to execute multiple similar calculations in parallel and is thus particularly<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-123","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/melander.dk\/graphics32\/wp-json\/wp\/v2\/pages\/123","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/melander.dk\/graphics32\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/melander.dk\/graphics32\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/melander.dk\/graphics32\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/melander.dk\/graphics32\/wp-json\/wp\/v2\/comments?post=123"}],"version-history":[{"count":10,"href":"https:\/\/melander.dk\/graphics32\/wp-json\/wp\/v2\/pages\/123\/revisions"}],"predecessor-version":[{"id":402,"href":"https:\/\/melander.dk\/graphics32\/wp-json\/wp\/v2\/pages\/123\/revisions\/402"}],"wp:attachment":[{"href":"https:\/\/melander.dk\/graphics32\/wp-json\/wp\/v2\/media?parent=123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}